Sonela

Calling the Sonela API

One secret key and one request, and your own software asks the assistant a question or keeps its manuals up to date — behind the same rules as the assistant your people use.

Who this is for. The person who runs your Sonela workspace makes the key in the dashboard (section 2). Everything after that is for whoever writes the software that will call the API — hand them this page and the key, and nothing else.

1. What it is, and what it is not

The API is a third way to reach the assistant you already have, beside the widget and the hosted page. It answers from the same manuals and, where your workspace has them, the same records and lookups, unless you set the key to read only chosen manuals, lookups and templates (Integration › API keys › Readings), and it is read-only in the same way: no request can change your data.

2. Make a key

In the dashboard, open Integration, then API keys, then New key. The API is part of the Growth and Scale plans.

Field What it decides
What it may do chat asks questions. knowledge.read lists and reads manuals. knowledge.write adds, replaces and removes them. organisations.write adds your customers (section 7) and is a key of its own. Give a key only what the software on it needs.
Data source and end-tenant For a key that asks questions: the source it asks through and the customer whose records it asks about. One key, one customer. Software that serves several customers holds one key for each.
Language The language this key's answers are written in.
Requests a minute, questions a day The key's own limits (section 8). They bound what a lost key could spend, so set them near what the software really needs.
Expires after Optional. A key with no expiry lives until you revoke it.

The key is shown once. It begins sk_live_. We keep only a hash of it, so nobody can show it to you again, us included. Put it in your server's secret store or an environment variable — never in source control, never in a page, never in an app a visitor installs. What a key may do and what it reaches cannot be changed afterwards: make a new key and revoke the old one.

Everyone in your workspace is emailed when a key is made or rotated. If you receive that email and did not expect it, revoke the key.

3. Ask a question

Send the key as a bearer token and the question as JSON. The examples read the key from an environment variable named SONELA_API_KEY.

curl https://api.sonela.ai/api/v1/chat \
  -H "Authorization: Bearer $SONELA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "message": "What are your opening hours?" }'

The answer:

{
  "reply": "We are open nine to five, Monday to Friday.",
  "answered": true,
  "tables": [],
  "answeredFromRecords": false,
  "answeredFromMemory": false,
  "conversation": {
    "id": "0d5b1c1e-…",
    "state": "CfDJ8…",
    "expiresAtUtc": "2026-10-01T09:30:00Z"
  },
  "quota": { "limit": 5000, "remaining": 4210, "resetsAtUtc": "2026-11-01T00:00:00Z" },
  "receivedAtUtc": "2026-09-30T09:30:00Z"
}
Field Meaning
reply The answer, as text. It may carry Markdown.
answered false when the question was turned away before the assistant saw it, and reply is the sentence saying so. Such a turn spends none of your plan's credits and does not extend the conversation.
notFound true when reply says nothing was found on the question, so you can offer the next step yourself; absent otherwise. The question was answered and spent all the same.
tables Rows the answer rests on, when it read your records.
answeredFromRecords Whether the answer read your records or a lookup to get there.
answeredFromMemory Whether an answer already given to the same question was served again. Answers that rest on records are never served this way.
conversation What to send back to carry on (section 4).
quota What is left of your plan's question credits, and when they reset.

A message is at most 2,000 characters. Any other field in the request is ignored: the key has already decided it.

4. Carry on a conversation

To ask a follow-up, send the state the last answer gave you. Leave it out to start again.

{
  "message": "And on Saturdays?",
  "conversation": "CfDJ8…"
}

5. Stream the answer

Ask for a stream with one header and the same request answers as server-sent events, so your software can show the answer as it is written.

curl -N https://api.sonela.ai/api/v1/chat \
  -H "Authorization: Bearer $SONELA_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Accept: text/event-stream" \
  -d '{ "message": "What are your opening hours?" }'
Event Data What to do with it
status { "code": "thinking" | "records" | "writing" } Show progress, or ignore it.
table One table of rows Show it, or wait for the final answer, which carries it again.
text { "text": "…" } Append it to what you have shown.
reset {} Discard everything shown so far; the answer is starting again.
heartbeat {} Nothing. It keeps the connection open.
final The whole answer, exactly as section 3 shows it Replace what you have shown with it. This is the answer.
error A refusal, as section 9 describes them The answer failed after the stream began.

A request that is refused before the answer begins is answered as plain JSON with its status, not as a stream, so check the status and the content type before reading events. Ignore any event this table does not name.

6. Keep your manuals up to date

A key with knowledge.read or knowledge.write reaches the manuals the assistant answers from — the same ones the Manuals screen shows.

Request Scope What it does
GET /api/v1/documents knowledge.read Lists the manuals, how many you may hold, and how they reach the assistant.
GET /api/v1/documents/{id} knowledge.read One manual, with its text.
POST /api/v1/documents knowledge.write Adds a manual: { "title": "…", "content": "…", "publicAudience": true }.
PUT /api/v1/documents/{id} knowledge.write Replaces a manual's title and text.
DELETE /api/v1/documents/{id} knowledge.write Removes a manual.
POST /api/v1/documents/convert knowledge.write Turns a spreadsheet, a Word document or a PDF into text and hands it back. Stores nothing.
curl https://api.sonela.ai/api/v1/documents \
  -H "Authorization: Bearer $SONELA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "title": "Returns policy", "content": "Goods may be returned within 30 days…" }'

A file takes two requests on purpose. Send it to convert as a form upload in a field named file, read what it became, correct anything the conversion got wrong, and save that text as a manual. Nothing reaches the assistant that nobody has had the chance to read.

curl https://api.sonela.ai/api/v1/documents/convert \
  -H "Authorization: Bearer $SONELA_API_KEY" \
  -F "file=@price-list.xlsx"

A manual written by your website's crawl can be read here and is changed only at the site: a write to one answers 409 sop_managed_by_website. One read from your Google Docs is changed only in the Doc, and a write to it answers 409 sop_managed_by_google_docs. One read from SharePoint or OneDrive is changed only in the file, and a write to it answers 409 sop_managed_by_sharepoint. One holding the latest posts of a Facebook page or Instagram profile you added is changed only on the page, and a write to it answers 409 sop_managed_by_social_page. Each document says which it is in fromWebsite, fromGoogleDocs, fromSharePoint and fromSocialPage. publicAudience says whether your public assistant reads a manual: a new one that names none is read only by the assistant your own people sign in to, an update that names none keeps what the manual had, and one from your website or a social page is always public. A manual you add or change is searchable shortly afterwards; the list's index says where that stands.

7. Add your customers

If each of your customers has a database of their own with the same tables, your sign-up flow can add them as it creates them. Connect one customer's database in the dashboard and approve its schema once: it becomes the template. A key with organisations.write, which holds nothing else, then reaches these doors.

Request What it does
POST /api/v1/organisations Connects the customer's database, approves it only if it reads exactly as the template does, copies the template's glossary, and sends the customer to it.
PUT /api/v1/organisations/{id}/route Sends a customer to one of your databases, or moves them: { "dataSourceId": "…" }.
DELETE /api/v1/organisations/{id} Lets a customer go. Their assistant stops at once; their database stays until you remove it in the dashboard.
GET /api/v1/organisations Your customers and the database each one reads.
curl https://api.sonela.ai/api/v1/organisations \
  -H "Authorization: Bearer $SONELA_PROVISIONING_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "endTenantId": "acme", "name": "Acme Ltd",
        "templateDataSourceId": "…",
        "connectionString": "Host=…;Database=acme;Username=sonela_reader;Password=…" }'

endTenantId is the id your voucher endpoint signs for that customer, and {id} in a path is the same id, URL-escaped. A database whose tables, columns or comments differ from the template's is refused with 409 stamp_schema_differs or 409 stamp_notes_differ and a differences list naming the tables; nothing is made, and you connect it in the dashboard instead. A database that belongs to one customer cannot be given to a second: 409 organisation_route_source_owned.

8. Limits

Limit Whose When it is reached
Requests a minute The key's, set by you 429 with Retry-After, in seconds.
Questions a day The key's, set by you 429 api_key_day_spent, with limit, resetsAtUtc and Retry-After. It resets at midnight UTC.
Your plan's question credits The workspace's, shared with the widget and the hosted page. A question costs one, or two if it reads your records. 429 quota_exceeded, with when the period resets.
Manuals written The workspace's 429 with Retry-After.

On any 429, wait for as long as Retry-After says before trying again. Software that retries at once spends the next minute's allowance on refusals.

9. When a request is refused

A refusal is JSON with a status, a title, a detail written for a person, and a code written for your software. Branch on the code, never on the words.

Status and code What it means What to do
401 api_key_invalid The key is unknown, revoked, expired or replaced. Which one is never said. Do not retry. Check the key's row in the dashboard.
403 api_key_scope The key was made without what this request needs. Make a key that has it.
403 api_not_on_plan The workspace's plan does not include the API. Change the plan.
403 assistant_paused Your workspace has paused its assistant. Manuals can still be read and written. Resume it under Integration, Availability.
400 conversation_invalid The conversation's state did not open. Send the message again without it.
429 A limit of section 8. Wait for Retry-After.
503 assistant_not_ready Something the answer needs is not set up in the workspace. Open the dashboard; its setup screen says what is missing.
503 data_source_unavailable
502 provider_failed
Your records, or the AI provider, did not answer. Try again after a pause.
503 api_unavailable The API is switched off. Try again later.
409 document_limit_reached
400 document_too_long
The library is full, or a manual is longer than one may be. Remove a manual, or split the text.
400 document_file_missing
400 document_not_converted
No file arrived in the file field, or it could not be read. The detail says which.
404 No manual of yours has that id. List the manuals again.

10. Rotating and revoking

11. The checklist