Documentation

The Ondine API

Four doors to connect your house's assistant to your own systems: your website, your application, your concierge software. JSON, one key, nothing else to install.

Getting started Conversation The house The log The webhook Errors and limits

Getting started

API access is included in the Premium plan. Your key is handed to you by SDO Studio when your property is opened; it is shown nowhere and cannot be recovered, so keep it as you would a password. Every address begins with:

https://europe-west1-comselenadorionserena.cloudfunctions.net/ondine

Every call carries your key in the Authorization header, as a POST, with a JSON body. The server always answers in JSON.

# the shortest call there is: a guest question
curl -X POST https://europe-west1-comselenadorionserena.cloudfunctions.net/ondine/v1/conversation \
  -H "Authorization: Bearer YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"hote":"room-12","message":"Good evening, what time does the spa close?"}'

You would rather we did it

Connecting Ondine to your concierge or booking software can be done by us: we write the integration, test it with your teams and hand it over working. This work is quoted on a day rate, after a conversation about your system. It is not part of the set-up, which covers your house's record, your documents, the bubble on your site and briefing your team.

Write to contact@sdo-studio.com or call +33 6 12 45 35 53.

Data is hosted in Europe. A guest conversation through the API counts towards your plan exactly as one from the website bubble does.

1. The conversation

You pass a guest's message, Ondine answers in their language from your house's record, and tells you what she did.

POST/v1/conversation
FieldTypePurpose
messagestringRequired. What the guest wrote. 4,000 characters at most.
hotestringYour own reference for this guest: a room number, a booking reference. Opens a thread.
conversationstringThe identifier returned by the first call. Send it back to continue the same exchange; Ondine remembers what was said.
languestringOptional, two letters. Without it, Ondine recognises the guest's language on her own.
stream1Optional. The answer then arrives word by word, as text/event-stream.
// response
{
  "conversation": "api_belle-rive_room-12_m1x9k2",
  "reponse": "Good evening. The spa is open daily from 9 am to 8 pm…",
  "actions": [
    { "type": "demander_rendez_vous", "objet": "Couples treatment, 50 min",
      "quand": "Saturday 6.30 pm", "details": "Two people", "nom_hote": "Perrin" }
  ]
}

actions tells you what Ondine wrote into the log during this reply: demander_rendez_vous when the guest asks for a treatment, a table, a transfer or a room, transmettre_a_l_equipe when she does not know. The array is empty if she simply answered.

2. The house

What Ondine knows about your property. You may read it, and keep it current from your own system: a rate that changes, a pool under repair, summer opening times.

POST/v1/etablissement

Without a fiche field, the call reads. With it, the call updates: only the sections you send are changed, the rest stay as they are.

# read
curl -X POST …/v1/etablissement -H "Authorization: Bearer YOUR_KEY" -d '{}'

# update two sections
curl -X POST …/v1/etablissement \
  -H "Authorization: Bearer YOUR_KEY" -H "Content-Type: application/json" \
  -d '{"fiche":{"spa":"Spa open 9 am to 8 pm. Pool under repair until 30 September.",
                "restaurant":"Dinner 7.30 pm to 10.30 pm, closed Mondays."}}'
ResponseContents
nom, type, ville, paysThe identity of the house.
ficheThe sections, as free text: presentation, horaires, chambres, spa, restaurant, transferts, conditions, ton, langues, contact, acces, and any section you add.
documentsThe names of the uploaded documents (menus, brochures) Ondine reads.
A section name is lowercase, without accents or spaces. For a ship: itineraire, escales, retour_a_bord, ponts, restauration, excursions, cabines.

3. The log

Every request Ondine has taken, and your team's decisions. This is how concierge software collects appointments and sends confirmations back.

POST/v1/journal
FieldPurpose
statutOptional: a_confirmer, transmis, confirme, refuse, traite.
limiteOptional, 100 by default, 200 at most. Most recent first.
{
  "journal": [
    { "id": "9935pGvGU93hoFz1SIIS", "type": "rendez_vous", "statut": "a_confirmer",
      "objet": "Table for 4 at Les Rochers", "quand": "Saturday at 8 pm",
      "details": "Booking under Perrin, 4 people", "hote": "Perrin",
      "langue": "fr", "canal": "api", "conversation": "api_belle-rive_…",
      "creeLe": "2026-09-09T18:41:02.113Z" }
  ]
}
POST/v1/journal/{id}/decision

Confirm, decline or mark as handled. decision is confirme, refuse or traite; mot is optional and stays in the log.

curl -X POST …/v1/journal/9935pGvGU93hoFz1SIIS/decision \
  -H "Authorization: Bearer YOUR_KEY" -H "Content-Type: application/json" \
  -d '{"decision":"confirme","mot":"Table 12, on the terrace."}'

4. The webhook

To be told the moment it happens, rather than polling the log. As soon as Ondine records a request, we call your address.

POST/v1/webhook
# set the address and the secret
curl -X POST …/v1/webhook \
  -H "Authorization: Bearer YOUR_KEY" -H "Content-Type: application/json" \
  -d '{"url":"https://your-server.com/ondine","secret":"a-secret-of-yours"}'

# read what is set (the secret is never returned)
curl -X POST …/v1/webhook -H "Authorization: Bearer YOUR_KEY" -d '{}'

# remove the webhook
curl -X POST …/v1/webhook -H "Authorization: Bearer YOUR_KEY" -d '{"url":""}'

We call your address with a POST, once, waiting eight seconds. If you have set a secret, it travels in the X-Ondine-Secret header: compare it before trusting the call. The address must be https.

// what you receive
{
  "etablissement": "belle-rive",
  "envoyeLe": "2026-09-09T18:41:02.113Z",
  "evenement": "rendez_vous",          // or "transmis"
  "id": "9935pGvGU93hoFz1SIIS",          // the log entry
  "objet": "Table for 4 at Les Rochers",
  "quand": "Saturday at 8 pm",
  "details": "Booking under Perrin, 4 people",
  "hote": "Perrin",
  "langue": "fr",
  "canal": "site",
  "conversation": "h_belle-rive_m1x9k2"
}
Answer quickly, with a 200. We do not retry: if your server is away, the request stays in the log and nothing is lost.

Errors and limits

CodeWhat it means
200Done.
400A field is missing or malformed. The body says so, in erreur.
401Key missing or unknown.
403Subscription inactive.
404Unknown door or request.
500Trouble on our side. Try again shortly.

Every error arrives with a body of the form {"erreur":"…"}, written to be shown to a person as it is.

The monthly limit

Each property has a monthly conversation limit, set from the management area. Beyond it the API still answers 200, but with "limite": true: Ondine did not answer herself, she placed the guest's message in the log and returned a holding note in their language. Alert your team at that point.

Rate

No call rate limit is imposed today. We would tell you before setting one. Conversations count towards your plan: beyond the number included, they are billed per unit under your terms.

A question

Write to contact@sdo-studio.com or call +33 6 12 45 35 53. You will speak to the person who wrote this API.