Orbitali Docs

Agents

Public API endpoints for configuring realtime voice agents.

Agents define prompt behavior, tool execution, voice settings, and phone number routing.

All endpoints on this page use API key authentication:

Authorization: Bearer $ORBITALI_API_KEY

Public agent endpoints

MethodPathDescription
GET/public/v1/agentsList agents
POST/public/v1/agentsCreate an agent
PUT/public/v1/agents/{agent_id}Replace an agent
PATCH/public/v1/agents/{agent_id}Partially update an agent
GET/public/v1/agents/{agent_id}/toolsList custom tools
POST/public/v1/agents/{agent_id}/toolsCreate a custom tool
PUT/public/v1/agents/{agent_id}/tools/{tool_id}Replace a custom tool
DELETE/public/v1/agents/{agent_id}/tools/{tool_id}Delete a custom tool
GET/public/v1/agents/{agent_id}/mcp-toolsList connected MCP tool selections
PUT/public/v1/agents/{agent_id}/mcp-toolsReplace connected MCP tool selections
GET/public/v1/agents/{agent_id}/knowledgeList knowledge documents
POST/public/v1/agents/{agent_id}/knowledgeUpload a knowledge document
DELETE/public/v1/agents/{agent_id}/knowledge/{document_id}Delete a knowledge document
POST/public/v1/agents/{agent_id}/realtime-sessionsCreate a short-lived WebSocket voice session

Phone number listing and assignment endpoints are documented in Phone Numbers, and call history and agent log endpoints in Calls & Logs. Connected MCP server discovery and tool assignment are documented in MCP Integrations.

Active-agent limits

Agent limits apply to active agents only. Draft and inactive agents can be saved without consuming the active-agent allowance, but only active agents can receive calls or start realtime sessions.

The trial allowance is 1 active agent. Paid plan allowances are controlled by the account's current plan; current defaults are Launch: 2 active agents, Studio: 10 active agents, and Agency: unlimited active agents. If an activation would exceed the current allowance, PUT and PATCH return 409 with code: "AGENT_LIMIT_EXCEEDED".

Create an agent

Creates a draft static, webhook, or http agent and its prompt configuration.

The create endpoint always creates a draft agent. To make an agent available for calls or realtime sessions, update it later with status: "active" using PUT /public/v1/agents/{agent_id} or PATCH /public/v1/agents/{agent_id}.

curl https://api.orbitali.ai/public/v1/agents \
  -X POST \
  -H "Authorization: Bearer $ORBITALI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Receptionist",
    "agentType": "static",
    "language": "en-US",
    "aiIdentityDisclosureTemplateId": "named_agent",
    "voiceName": "eve",
    "phoneNumberAssignments": [
      {
        "phoneNumberId": "40000000-0000-4000-8000-000000000001",
        "handoffPhoneNumber": "+15551234567"
      }
    ],
    "serverUrl": null,
    "serverHeaders": {},
    "serverSecret": null,
    "handoffPhoneNumber": null,
    "promptType": "static",
    "identity": "You are the front desk receptionist for Acme Clinic.",
    "instructions": "Answer caller questions clearly and offer to take a message.",
    "greetingType": "static",
    "staticGreeting": "Thanks for calling Acme Clinic. How can I help?"
  }'

Response:

{
  "id": "9dbf0d0b-2b55-45de-8c41-7a2d9b0ce8e9"
}

Agent request fields

FieldTypeDescription
namestringDisplay name for the agent
agentTypestatic | webhook | httpAgent integration mode. Defaults to webhook when omitted
languagestringRealtime language variant. es-ES requests Castilian Spanish with Spain vocabulary; es-US requests US Spanish with a neutral Latin-American accent and US-Spanish usage.
aiIdentityDisclosureTemplateIdstandard | assistant_of | named_agent | virtual_assistant | named_virtual_assistantApproved mandatory AI identity sentence. Named templates interpolate the agent's name; defaults to standard
voiceNamestringGemini voice profile used for generated speech. Built-ins are eve (warm female), ara (gentle female), rex (friendly male), sal (casual male), and leo (smooth male).
phoneNumberAssignmentsobject[]Claimed phone number assignments. Each item includes phoneNumberId and optional handoffPhoneNumber used when that inbound number transfers to a human
phoneNumberIdsstring[]Legacy-compatible claimed phone number IDs assigned to the agent. New integrations should use phoneNumberAssignments
serverUrlstring | nullWebhook agent endpoint. Required for dynamic prompts and webhook tools. Use null for static and HTTP agents
serverHeadersobjectExtra string headers sent to the Server URL
serverSecretstring | nullSecret used to sign Server URL webhook requests. When present, Orbitali sends x-orbitali-signature as sha256= plus the lowercase hex HMAC-SHA256 digest of the raw JSON body
handoffPhoneNumberstring | nullLegacy fallback phone number used by transfer_call when no per-number handoff applies
promptTypestatic | dynamicWhether instructions are stored directly or fetched from the Server URL. Dynamic prompts are only supported by webhook agents
identitystringWho the agent is and what role it should play
instructionsstringStatic prompt instructions. Required when promptType is static
greetingTypestatic | dynamic | noneHow the first assistant message is selected
staticGreetingstring | nullRequired when greetingType is static

Full PUT and partial PATCH updates also accept status, which can be draft, active, or inactive. Activating an agent counts against the account's active-agent allowance.

Agent types:

  • static: saved identity, instructions, and greeting only. Static agents do not support custom tools.
  • webhook: saved or dynamic prompt config. Dynamic prompts use serverUrl and agent:assistant-request. Custom tools use serverUrl and agent:tool-call events.
  • http: saved prompt config. Custom tools call their own toolUrl with toolMethod and toolHeaders.

AI identity disclosure templates are maintained and versioned by Orbitali. Customers can select an approved template but cannot provide arbitrary mandatory wording. Recording, transcription, privacy, organization, and purpose notices remain separately configurable.

Dynamic prompts require serverUrl and agentType: "webhook". Dynamic greetings require promptType to be dynamic.

Verify signed Server URL requests with the raw request body. Re-serialized or parsed JSON can produce a different HMAC.

Partially update an agent

Updates only the supplied fields and keeps the current phone assignments, prompt fields, greeting fields, and server config unless they are included in the request.

curl https://api.orbitali.ai/public/v1/agents/9dbf0d0b-2b55-45de-8c41-7a2d9b0ce8e9 \
  -X PATCH \
  -H "Authorization: Bearer $ORBITALI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "expectedUpdatedAt": "2026-05-14T12:00:00.000Z",
    "serverUrl": "https://crm.orbitali.ai/api/orbitali/agents"
  }'

The Server URL signing secret can also be updated without resending the full agent:

{
  "expectedUpdatedAt": "2026-05-14T12:00:00.000Z",
  "serverSecret": "..."
}

Response:

{
  "id": "9dbf0d0b-2b55-45de-8c41-7a2d9b0ce8e9"
}

PATCH accepts the same fields as a full update, but every field except expectedUpdatedAt is optional. Use the agent's current updatedAt value from GET /public/v1/agents as expectedUpdatedAt. If the agent changed after that timestamp, PATCH returns 409 so the client can refetch and retry. The merged result must still be valid. For example, promptType: "dynamic" still requires an existing or supplied serverUrl, and greetingType: "dynamic" still requires dynamic prompt mode.

If the update changes a draft agent to status: "active" and the account is already at its active-agent limit, the API returns 409:

{
  "error": "Active agent limit exceeded",
  "code": "AGENT_LIMIT_EXCEEDED",
  "maxAgents": 2
}

Deactivate another active agent or upgrade the account plan before retrying. maxAgents is the active-agent cap for the current plan or trial.

List agents

curl https://api.orbitali.ai/public/v1/agents \
  -H "Authorization: Bearer $ORBITALI_API_KEY"

Response:

[
  {
    "id": "9dbf0d0b-2b55-45de-8c41-7a2d9b0ce8e9",
    "name": "Receptionist",
    "status": "draft",
    "agentType": "webhook",
    "language": "en-US",
    "voiceName": "eve",
    "serverUrl": "https://example.com/orbitali/webhook",
    "serverHeaders": {},
    "serverSecret": null,
    "handoffPhoneNumber": null,
    "phoneNumber": null,
    "toolCount": 1,
    "knowledgeDocumentCount": 0,
    "callsToday": 0,
    "successRate": 0,
    "updatedAt": "2026-05-14T12:00:00.000Z"
  }
]

Create a tool

Creates a custom tool for an existing webhook or HTTP agent. Static agents do not support custom tools.

For webhook agents, the agent must have a saved serverUrl. Tool executions are delivered to that Server URL as agent:tool-call events.

For HTTP agents, each tool must include toolUrl. Tool executions call that URL with toolMethod and toolHeaders.

curl https://api.orbitali.ai/public/v1/agents/9dbf0d0b-2b55-45de-8c41-7a2d9b0ce8e9/tools \
  -X POST \
  -H "Authorization: Bearer $ORBITALI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "lookup_customer",
    "description": "Find a customer record by phone number.",
    "parameterSchema": {
      "type": "object",
      "properties": {
        "phone": { "type": "string" }
      },
      "required": ["phone"]
    },
    "responseSchema": null,
    "timeoutMs": 5000,
    "onError": "return_error",
    "enabled": true,
    "toolUrl": null,
    "toolMethod": "POST",
    "toolHeaders": {}
  }'

Response:

{
  "id": "df0ee766-7903-4c13-8547-f6bd65de392a"
}

Update a tool

Replaces an existing custom tool definition. Send the full tool object without the id field.

Static agents do not support custom tools. For HTTP agents, toolUrl is required. For webhook agents, enabling a tool requires a saved serverUrl.

curl https://api.orbitali.ai/public/v1/agents/9dbf0d0b-2b55-45de-8c41-7a2d9b0ce8e9/tools/df0ee766-7903-4c13-8547-f6bd65de392a \
  -X PUT \
  -H "Authorization: Bearer $ORBITALI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "lookup_customer",
    "description": "Find a customer record by phone number.",
    "parameterSchema": {
      "type": "object",
      "properties": {
        "phone": { "type": "string" }
      },
      "required": ["phone"]
    },
    "responseSchema": null,
    "timeoutMs": 5000,
    "onError": "return_error",
    "enabled": true,
    "toolUrl": null,
    "toolMethod": "POST",
    "toolHeaders": {}
  }'

Response:

{
  "id": "df0ee766-7903-4c13-8547-f6bd65de392a"
}

Delete a tool

Deletes an existing custom tool from an agent.

curl https://api.orbitali.ai/public/v1/agents/9dbf0d0b-2b55-45de-8c41-7a2d9b0ce8e9/tools/df0ee766-7903-4c13-8547-f6bd65de392a \
  -X DELETE \
  -H "Authorization: Bearer $ORBITALI_API_KEY"

Response:

{
  "id": "df0ee766-7903-4c13-8547-f6bd65de392a"
}

Tool request fields

FieldTypeDescription
namestringTool name exposed to the model
descriptionstringWhat the tool does and when to call it
parameterSchemaobjectJSON Schema object for tool arguments
responseSchemaobject | nullOptional JSON Schema object for the tool response
timeoutMsnumberTimeout from 1000 to 30000 milliseconds
onErrorreturn_error | return_emptyBehavior when the Server URL returns an error
enabledbooleanWhether the tool is available during calls
toolUrlstring | nullRequired for HTTP agents. Use null for webhook tools
toolMethodGET | POST | PUT | DELETE | PATCH | HEAD | OPTIONSHTTP method used with toolUrl; defaults to POST
toolHeadersobjectString headers sent to toolUrl; defaults to {}

Webhook tool executions are delivered to the agent's Server URL as agent:tool-call events. HTTP tool executions call the tool's own toolUrl.

List tools

curl https://api.orbitali.ai/public/v1/agents/9dbf0d0b-2b55-45de-8c41-7a2d9b0ce8e9/tools \
  -H "Authorization: Bearer $ORBITALI_API_KEY"

Response:

[
  {
    "id": "df0ee766-7903-4c13-8547-f6bd65de392a",
    "name": "lookup_customer",
    "description": "Find a customer record by phone number.",
    "parameterSchema": {},
    "responseSchema": null,
    "timeoutMs": 5000,
    "onError": "return_error",
    "enabled": true,
    "toolUrl": null,
    "toolMethod": "POST",
    "toolHeaders": {}
  }
]

Upload a knowledge document

Adds a document to an agent's knowledge base. The text is chunked and embedded so the agent can retrieve it during calls through the native search_knowledge tool. See the Knowledge Base guide for how retrieval works.

The endpoint accepts two content types.

JSON with text — ideal for coding agents that generate or read document text:

curl https://api.orbitali.ai/public/v1/agents/9dbf0d0b-2b55-45de-8c41-7a2d9b0ce8e9/knowledge \
  -X POST \
  -H "Authorization: Bearer $ORBITALI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Refund policy",
    "description": "How refunds are handled, including timelines and exceptions.",
    "content": "# Refund policy\n\nRefunds are processed within 5 business days..."
  }'

Multipart file upload — supports PDF in addition to text and Markdown:

curl https://api.orbitali.ai/public/v1/agents/9dbf0d0b-2b55-45de-8c41-7a2d9b0ce8e9/knowledge \
  -X POST \
  -H "Authorization: Bearer $ORBITALI_API_KEY" \
  -F "file=@refund-policy.pdf" \
  -F "name=Refund policy"

Response:

{
  "id": "b8e2c1a0-4f3d-4c7a-9e21-2f6d0a9b1c3e",
  "name": "Refund policy",
  "description": "How refunds are handled, including timelines and exceptions."
}

Knowledge request fields

FieldTypeDescription
contentstringJSON mode only. The document text or Markdown. Required when not sending a file
filefileMultipart mode only. A .txt, .md, or .pdf upload. Required when not sending content
namestringOptional display title. When omitted, a title is suggested from the document content
descriptionstring | nullOptional one-sentence summary. When omitted, a description is suggested from the document content

List knowledge documents

curl https://api.orbitali.ai/public/v1/agents/9dbf0d0b-2b55-45de-8c41-7a2d9b0ce8e9/knowledge \
  -H "Authorization: Bearer $ORBITALI_API_KEY"

Response:

[
  {
    "id": "b8e2c1a0-4f3d-4c7a-9e21-2f6d0a9b1c3e",
    "name": "Refund policy",
    "description": "How refunds are handled, including timelines and exceptions.",
    "type": "markdown",
    "sizeBytes": 1840,
    "status": "ready",
    "error": null,
    "chunkCount": 2,
    "createdAt": "2026-05-15T12:00:00.000Z"
  }
]

Delete a knowledge document

Removes a document and all of its indexed chunks from the agent.

curl https://api.orbitali.ai/public/v1/agents/9dbf0d0b-2b55-45de-8c41-7a2d9b0ce8e9/knowledge/b8e2c1a0-4f3d-4c7a-9e21-2f6d0a9b1c3e \
  -X DELETE \
  -H "Authorization: Bearer $ORBITALI_API_KEY"

Response:

{
  "id": "b8e2c1a0-4f3d-4c7a-9e21-2f6d0a9b1c3e"
}

WebSocket voice sessions

Use WebSocket sessions when a website needs to talk to an active agent directly instead of calling through a phone number. Create the session from your backend with an Orbitali API key, then pass the returned websocketUrl to browser code. Do not expose long-lived API keys in the browser.

curl https://api.orbitali.ai/public/v1/agents/9dbf0d0b-2b55-45de-8c41-7a2d9b0ce8e9/realtime-sessions \
  -X POST \
  -H "Authorization: Bearer $ORBITALI_API_KEY"

Response:

{
  "token": "eyJ...signature",
  "expiresAt": "2026-05-15T12:00:00.000Z",
  "websocketUrl": "wss://agent.orbitali.ai/ws/agents/9dbf0d0b-2b55-45de-8c41-7a2d9b0ce8e9?token=eyJ...signature",
  "protocol": {
    "inputAudio": { "encoding": "pcm16", "sampleRate": 16000 },
    "outputAudio": { "encoding": "pcm16", "sampleRate": 24000 }
  }
}

The WebSocket accepts JSON messages:

{ "type": "input_audio", "audio": "<base64 pcm16 16kHz mono audio>" }

Close the conversation with:

{ "type": "stop" }

The server sends:

{ "type": "session.started", "callId": "..." }
{ "type": "output_audio", "audio": "<base64 pcm16 24kHz mono audio>", "encoding": "pcm16", "sampleRate": 24000 }
{ "type": "transcript", "role": "assistant", "text": "..." }
{ "type": "clear" }

Session tokens expire after 60 seconds. Once connected, the WebSocket remains active until the conversation ends or the socket closes.

Errors

StatusCodeMeaning
400-Invalid request body, invalid agent ID, unsupported static-agent tool, missing webhook serverUrl, missing HTTP toolUrl, missing knowledge content or file, or text that could not be extracted
401-Invalid or missing API key
404-Agent or knowledge document not found
409AGENT_LIMIT_EXCEEDEDUpdating an agent to active would exceed the account's active-agent allowance. The response includes maxAgents
409-Agent update conflict, or agent must be active before creating a realtime session
500-Realtime WebSocket URL or token signing is not configured

On this page