Agents

Create and manage voice agents over the API.

Everything the agent builder does is available here. The API manages the core, portable fields of an agent; console-only settings (such as call context) are preserved untouched when you update.

Every agent runs a flow. When you create an agent over the API, its systemPrompt is wrapped into a one-step flow, which is published straight away. Build multi-step flows in the console.

Agent shapes:

  • List (publicAgent): { id, name, voice, language, status, channel, direction }
  • Detail / write (publicAgentManaged): the list fields plus systemPrompt, workflowTemplate, vertical, policyRef, allowedTransferNumbers, extractionSchema, knowledgeBaseId, toolIds.

To place outbound calls, use an agent with status: "active", channel: "call", and direction: "outbound".


List agents

GET /v1/agents  ·  scope agents:read

{ "data": [ { "id": "agt_…", "name": "Sales", "voice": "simran", "language": "hi", "status": "active", "channel": "call", "direction": "outbound" } ] }

Returns every agent in the workspace.

Get an agent

GET /v1/agents/:id  ·  scope agents:read → { "data": publicAgentManaged }. Unknown id → 404 agent not found.


Create an agent

POST /v1/agents  ·  scope agents:write

New agents are created as status: "draft" - publish before running them.

Body

Field Type Required Default / constraints
name string yes 1–120 chars
systemPrompt string no max 16000, default ""
voice string no max 80, default ""
language enum no en, hi, bn, gu, kn, ml, mr, or, pa, ta, te - default en
workflowTemplate enum no collections, onboarding, prompt-driven - default prompt-driven
vertical enum no general, collections, lending, financial_services, debt_recovery - default general
policyRef string no compliance-pack ref (1–120), default generic-safe@1. Built-in (e.g. india-lending@1) or custom (cpk_…)
toolIds string[] no catalog tool ids (each 1–64, max 50), default []
allowedTransferNumbers string[] no warm-transfer allowlist (each 1–20, max 50), default []
extractionSchema array no fields to capture: { key, label, type: "text"|"boolean"|"number" } (max 50), default []
knowledgeBaseId string | null no a knowledge base in your workspace, default null
channel enum no call or chat - default call. Fixed once created.
direction enum no outbound or inbound - default outbound (chat agents are always inbound). Fixed once created.

Validation

  • A regulated vertical (lending, financial services, debt recovery, collections) must be paired with a valid workflowTemplate and a compliance pack that resolves, or you get a 400/422.
  • A chat agent can’t use a regulated vertical (400).
  • allowedTransferNumbers and policyRef are validated. An unknown knowledgeBaseId is 400 knowledge_base_not_found.

Response - 201

{ "data": publicAgentManaged } with status: "draft".


Update an agent

PUT /v1/agents/:id  ·  scope agents:write

A partial update: send only the fields you want to change - anything you leave out keeps its current value (same fields as create; channel and direction can’t change). Same validation as create. Unknown id → 404.

Changing systemPrompt updates the agent’s flow and republishes it, so the next call uses the new prompt. If the agent’s flow was built or edited in the console, a prompt change is refused with 409 agent_uses_flow - edit its steps with the flow endpoints instead. Other fields can still be changed.

Response 200: { "data": publicAgentManaged }.

Publish or unpublish

POST /v1/agents/:id/status  ·  scope agents:write

{ "status": "active" }   // publish;  "draft" to unpublish

Publishing re-checks the vertical guard and compliance pack against the saved config (it can fail with the same guard errors). Response 200: { "data": publicAgentManaged }.

Voices and languages

GET /v1/voices  ·  scope agents:read

The values an agent’s voice and language can take. Every voice speaks every language.

{
  "data": {
    "voices": [ { "id": "rohan", "name": "Rohan", "gender": "male" }, { "id": "priya", "name": "Priya", "gender": "female" }, … ],
    "defaultVoice": "rohan",
    "languages": [ { "code": "en", "label": "English (IN)" }, { "code": "hi", "label": "Hindi" }, … ]
  }
}

Tools

GET /v1/tools  ·  scope agents:read

The tools set up in your workspace: your webhooks, plus built-ins such as transfer to a person, end call and WhatsApp. Pass their ids as an agent’s toolIds. Tools are created and configured in the console.

{ "data": [ { "id": "tool_…", "type": "transfer_to_human", "name": null, "description": "" }, { "id": "tool_…", "type": "webhook", "name": "Look up order", "description": "…" } ] }

Call flow

An agent’s conversation is a flow: steps (nodes), each with its own prompt, joined by transitions (“when the caller agrees, go to Book”). The console’s builder edits the same flow these endpoints read and write. A flow has a draft, which you edit, and a published version, which live calls run.

Read the flow

GET /v1/agents/:id/flow  ·  scope agents:read

{
  "data": {
    "draft": { "startNodeId": "n1", "nodes": [ … ], "variables": [ … ] },
    "draftVersion": 7,
    "published": { "startNodeId": "n1", "nodes": [ … ], "variables": [ … ] },
    "issues": [ { "level": "warning", "code": "…", "message": "…", "nodeId": "n3" } ]
  }
}

issues lists what’s wrong with the draft. error issues block publishing; warning issues don’t. The easiest way to learn the graph format is to read a flow built in the console.

Save the draft

PUT /v1/agents/:id/flow  ·  scope agents:write

{ "graph": { "startNodeId": "n1", "nodes": [ … ], "variables": [ … ] }, "baseVersion": 7 }

Replaces the whole draft. A draft may be incomplete; you get its issues back along with the new draftVersion. Live calls are unaffected until you publish.

  • Pass the draftVersion you read as baseVersion. If someone changed the draft since then (in the console, the AI editor, or another client), you get 409 flow_conflict and nothing is overwritten. Read it again and retry.
  • A step’s transferNumbers must be Indian +91 numbers (400 otherwise).
  • A body that isn’t a flow graph is 400.

Publish the draft

POST /v1/agents/:id/flow/publish  ·  scope agents:write

Makes the draft the flow that live calls run. While the draft has errors (broken transitions, a missing end step, an integration it needs that isn’t connected, …), publishing is refused with 422 flow_not_ready and every issue:

{ "error": "the flow has errors - fix them and publish again", "code": "flow_not_ready", "issues": [ { "level": "error", "code": "dangling_target", … } ] }

The agent itself must also be published (above) to take calls.

Delete an agent

DELETE /v1/agents/:id  ·  scope agents:write → { "data": { "id": "agt_…", "deleted": true } }.

  • 409 agent_in_use - a campaign uses this agent. A campaign’s agent can’t be changed, so delete those campaigns first.
  • 404 agent not found

Next: Contacts →