The Voice Agent API includes a REST API for creating and managing reusable voice agents. An agent stores its system prompt, greeting, voice, and tools server-side, so you can deploy it across channels by referencing its id.
For a guided walkthrough, see Create an agent .
Base URL: https://agents.assemblyai.com
Authentication
Every request requires your AssemblyAI API key in the Authorization header. The raw key works directly; a Bearer prefix is accepted and stripped:
Authorization: <YOUR_API_KEY>
Response Meaning 401 {"detail": "Unauthorized"}Key missing, malformed, or not entitled for Voice Agents. 401 {"detail": "Missing authorization header"}No Authorization header sent.
Endpoints
Method Path Description Success POST/v1/agentsCreate an agent 201GET/v1/agentsList your agents 200GET/v1/agents/{id}Retrieve one agent 200PUT/v1/agents/{id}Update an agent 200DELETE/v1/agents/{id}Delete an agent 204
Create an agent
POST /v1/agents
curl -X POST https://agents.assemblyai.com/v1/agents \
-H "Authorization: $ASSEMBLYAI_API_KEY " \
-H "Content-Type: application/json" \
-d '{
"name": "Support Assistant",
"system_prompt": "You are a friendly support agent.",
"greeting": "Hi, how can I help?",
"voice": { "voice_id": "ivy" }
}'
Returns 201 with the full agent record .
List agents
GET /v1/agents returns a lightweight array of id, name, and timestamps, not full configurations.
curl https://agents.assemblyai.com/v1/agents \
-H "Authorization: $ASSEMBLYAI_API_KEY "
Retrieve an agent
GET /v1/agents/{id} returns the full agent record . Tool header values are masked as "***" (see HTTP tool config ).
Update an agent
PUT /v1/agents/{id} accepts the same body as create, but every field is optional . Send only what changes. Returns 200 with the updated record.
curl -X PUT https://agents.assemblyai.com/v1/agents/ $AGENT_ID \
-H "Authorization: $ASSEMBLYAI_API_KEY " \
-H "Content-Type: application/json" \
-d '{ "greeting": "Thanks for calling Acme. What can I do for you?" }'
Delete an agent
DELETE /v1/agents/{id} returns 204 with no body.
Request schema
Body for POST /v1/agents (and, with all fields optional, PUT /v1/agents/{id}):
Field Type Required Default Notes namestring Yes - Display name. system_promptstring Yes - The agent’s instructions. voiceVoiceConfigYes - The TTS voice. greetingstring | null No nullSpoken on connect; sent straight to TTS. Omit to listen first. inputobject No PCM 24 kHz Audio input config (see input/output ). outputobject No PCM 24 kHz, agent voice Audio output config (see input/output ). toolsTool[]No []Tools the agent can call.
VoiceConfig
voice_id must be a known voice. An invalid id returns 400 with the full list of valid voices in the message. See the voice catalog .
Default input and output when omitted:
"input" : { "type" : "audio" ,
"format" : { "encoding" : "audio/pcm" , "sample_rate" : 24000 },
"turn_detection" : null , "keyterms" : null },
"output" : { "type" : "audio" , "voice" : "ivy" ,
"format" : { "encoding" : "audio/pcm" , "sample_rate" : 24000 },
"volume" : null }
format.encoding ∈ audio/pcm, audio/pcmu, audio/pcma.
input.keyterms: up to 100 transcription-bias strings, or null.
input.turn_detection: VAD tuning, or null for adaptive defaults.
output.volume: 0 to 100, or null for native level.
These mirror the fields in Session configuration ; the same field reference applies.
Field Type Required Default Notes namestring Yes - Tool name the model calls. descriptionstring Yes - When to call it. The model’s main signal. parametersParameters No nullA JSON Schema describing the tool’s arguments. httpHttpToolConfigNo nullThe outbound request. Omit for a client-handled tool. timeout_secondsinteger No 120Range 1–300. execution_mode"interactive" | "hold"No "interactive"How the agent behaves while the tool runs. See tool calling .
Parameters (JSON Schema)
parameters is a standard JSON Schema object describing the tool’s arguments. The same shape for HTTP and client-side tools:
{
"type" : "object" ,
"properties" : {
"order_id" : {
"type" : "string" ,
"description" : "The customer's order ID." ,
"examples" : [ "AB-12345" , "ZZ-90001" ],
"pattern" : "[A-Z]{2}- \\ d{5}"
}
},
"required" : [ "order_id" ]
}
Each property accepts standard JSON-Schema keywords. Beyond type and description, these sharpen tool-calling and turn-detection accuracy:
Keyword Type Notes enumstring[] Restrict to a fixed set of allowed values. examplesarray Concrete example values. Improves recognition and turn-taking. patternstring Regex the value must match to be accepted. formatstring A named JSON-Schema format (email, date-time, …).
If you omit these, the agent infers the expected shape from each property’s description at runtime. See Parameter hints for guidance and examples.
{
"url" : "https://api.example.com/orders" ,
"http_method" : "POST" ,
"headers" : { "Authorization" : "Bearer xyz" }
}
Field Type Required Default Notes urlstring Yes - Must be https and a public host. Max 2048 chars. http_methodHTTP method No "POST"GET, POST, PUT, PATCH, or DELETE.headersobject | null No nullSent on every call. Values are encrypted at rest and write-only .
How arguments are sent: GET/DELETE → query string (stringified, null dropped); POST/PUT/PATCH → JSON body. Query params already in url are merged with the model’s arguments.
Headers are write-only. Values you send are envelope-encrypted before storage. In any response, header names are returned but values are masked as "***". To rotate a secret, send a new headers object in an update.
Server-side execution constraints. AssemblyAI makes the request on your behalf and enforces: https only; public hosts only (private/loopback/link-local/CGNAT IPs blocked, including obfuscated literals); redirects not followed (a 3xx is returned to the model as an error); response body capped at 8 KiB before being fed to the model; per-call timeout from timeout_seconds.
Agent object
The full record returned by create, get, and update:
{
"id" : "7ad24396-b822-4dca-871a-be9cc4781cf9" ,
"name" : "Weather Buddy" ,
"system_prompt" : "You are Weather Buddy..." ,
"greeting" : "Hey there, which city would you like the weather for?" ,
"tools" : [
{
"id" : "f29a0fd4-6f8b-4acb-8a74-e60f417f6dbb" ,
"name" : "get_weather" ,
"description" : "Fetch current weather for a geographic point..." ,
"http" : {
"url" : "https://api.open-meteo.com/v1/forecast?current=temperature_2m&temperature_unit=fahrenheit" ,
"http_method" : "GET" ,
"headers" : {}
},
"parameters" : {
"type" : "object" ,
"properties" : {
"latitude" : { "type" : "number" , "description" : "Latitude in decimal degrees." },
"longitude" : { "type" : "number" , "description" : "Longitude in decimal degrees." }
},
"required" : [ "latitude" , "longitude" ]
},
"timeout_seconds" : 30 ,
"execution_mode" : "interactive"
}
],
"voice" : { "voice_id" : "ivy" },
"input" : { "type" : "audio" , "format" : { "encoding" : "audio/pcm" , "sample_rate" : 24000 }, "keyterms" : null , "turn_detection" : null },
"output" : { "type" : "audio" , "voice" : "ivy" , "format" : { "encoding" : "audio/pcm" , "sample_rate" : 24000 }, "volume" : null },
"created_at" : "2026-06-08T12:04:27.607110Z" ,
"updated_at" : "2026-06-08T12:04:27.607113Z"
}
See all 33 lines
Tools gain a generated id. Header values are masked as "***" (here the tool has no headers, so headers is {}).
Validation errors
Status When Example 400A field fails a domain rule Invalid voice 'xyz'. Must be one of: ..., tools[0].http.url: webhook URL must use https://, 'tools[0].timeout_seconds' must be between 1s and 300s401Auth failed {"detail": "Unauthorized"}422Malformed JSON or wrong types Standard schema-validation body naming the offending field.
Deploy a stored agent
Once created, connect by agent_id. Over the WebSocket, bind to the agent in your first session.update:
{
"type" : "session.update" ,
"session" : { "agent_id" : "7ad24396-b822-4dca-871a-be9cc4781cf9" }
}
agent_id is mutually exclusive with inline session fields (system_prompt, greeting, tools, input, output). See Deploy your agent .