Skip to main content

Authentication

Every request carries your API token in the Authorization header. Send the token as-is, without a Bearer prefix.
The token identifies the account that owns the agents, and every read and write is scoped to it. An agent id from another account returns 404, never someone else’s data.

Agents, versions and deployments

Editing is not deploying. Creating an agent deploys its first version straight away. After that, updating and activating only change the latest version. The live agent keeps serving the old config until you call POST /v1/agents/{agentId}/deploy.
History is append-only. Activating an older version doesn’t rewind anything: it copies that version’s content into a new version on top, so the current config is always the newest one and nothing is lost.

Naming things

Catalog references are written by name and read back by name. Internal ids are accepted too, so you can edit a response and send it straight back. Copy model slugs, voice ids and language codes from Supported models. Language names are matched case-insensitively; responses always come back lowercase. Inference or your own key. Leave apiKey off to run a model on our keys (inference), or add your provider’s key to the entry to run it on your own account (BYOK). Supported models shows which of the two each model supports.
  • Read back masked. Responses never return a key in full. It comes back masked, with only the last four characters showing: "apiKey": "••••••••••••AbCd".
  • Send the full key every time. On create and on update, every BYOK entry needs its full apiKey. A masked value is rejected with INVALID_TYPE, so after a GET, put the full keys back before you send the config.
  • Changing a key doesn’t delete the old one, so older versions still run.
An entry’s language is optional. Send a code (en-IN, any casing) to pick that variant, or leave it out and the plain code for that language (en, not en-IN) is picked for you. A code the model doesn’t offer returns UNKNOWN_LANGUAGE_DOC. It is never swapped for a different variant. Each model’s codes are listed in Supported models.

The config object

Config splits on one question: does this vary by language? The model slots (stt, llm, tts, realtime) are arrays: the first entry is primary, and the rest are fallbacks tried in order. A realtime model goes under realtime instead of stt / llm / tts, because it fills all three roles itself. When a block has realtime, any stt, llm or tts in the same block is ignored and not stored.
Three fields must agree across languages. greeting.interruptible, endCall.enabled and endCall.when are stored once for the whole agent. Setting them differently per language returns MUST_MATCH_ACROSS_LANGUAGES instead of silently picking one. endCall.message is per-language.

Knowledge bases

Give your agent something to know. Upload documents, list website pages or send text, and each one becomes a knowledge base your agent retrieves from during a call. Attach it to an agent by putting its knowledgeId in the agent’s knowledgeBaseIds.
  • One create endpoint. POST /v1/knowledge-bases takes files as multipart/form-data, or website pages or text as JSON.
  • Website pages must all be on one domain. Exactly the pages you list are parsed. Use Discover pages to find them.
  • Processing runs in the background. Poll Get knowledge base status until it’s ready.
  • Edit the content with Edit knowledge base content. Each edit is a new version, selected automatically once it finishes indexing.
  • Versions. A website’s auto-refresh adds a new version on every run. Agents read the current version, and you can roll back with Set current version.
  • Folders group knowledge bases, up to 5 levels deep. Deleting a folder keeps the knowledge bases inside it.

Telephony

Bring your own SIP trunk: register the numbers you already own with a SIP address, and we wire an inbound and an outbound gateway for them. Then attach routing rules to decide which agent each call reaches.
  • sipRegion is one of auto, us002, in002. auto stores no region and lets us pick.
  • mediaEncryption is enable or disable (default disable).
  • transport is udp, tcp or tls (default tls).
  • Numbers are always E.164, with the +.
The phone-number endpoints never return 5xx. An unexpected server fault comes back as 400 with {"message": "Internal Server Error!! "}, so don’t branch on the status class alone. Routing rules use 500 for the same case.
A number can carry one inbound routing rule and many outbound ones. headersToAttributes is inbound-only and headers is outbound-only; putting either on the wrong type returns 400.

Batch calls

Upload a spreadsheet of phone numbers and your agent calls every one of them, right away or on a schedule. One request does it all: POST /v1/batch-calls takes the file and the settings together as multipart/form-data, and the batch starts by itself once the file is parsed.
  • Before you start, you need a number with an outbound gateway, and an outbound routing rule on it that points at your agent. Pass the number as phoneNumber (E.164).
  • The file is .csv, .xls or .xlsx, at most 5 MB, with a phone_number column. Every other column reaches the agent as metadata for that call.
  • schedule, retry and webhook are JSON strings inside the form. Leave schedule out to start calling as soon as parsing finishes.
  • Follow progress with Get batch call: parsing → scheduled or running → completed. A file that can’t be used ends in parse_failed, with the reason in parseError.

Agent sessions

See what happened on every call: what the user and the agent said, how long each stage took, and what it used. GET /v1/agents/sessions returns your sessions newest first, each with its turns. Pass a roomId, an agentId, or both to narrow it down.
  • One turn is one exchange. user and agent carry the transcript and speech times in Unix epoch milliseconds.
  • Each stage is its own block: stt, llm, tts (or realtime for speech-to-speech models), eou and denoise, with the provider, model, latency and usage.
  • A stage that didn’t run is null. The greeting has no stt or llm, and a turn where the user was cut off may have no llm or tts.
  • The agent’s transcript is what it generated. If the user interrupted, it can be longer than what was actually heard; interrupted tells you when.