API

Agents API

Create, manage, and call AI voice agents via the REST API.

Voice AI agents are persistent, reusable configurations for AI-powered phone calls. Instead of passing a systemPrompt on every call, create an agent once and place calls through it.

Agents are backed by Ultravox. Each agent maps to an Ultravox agent resource with its own prompt, voice, tools, and knowledge bases.

Create agent

POST /api/voice/agents

Create a new AI voice agent with a system prompt, optional voice, tools, and knowledge bases.

Request body

FieldTypeRequiredDescription
namestringYesAgent name
promptstringYesSystem prompt that defines agent behavior
voicestringNoVoice ID for TTS (e.g. "Mark")
first_messagestringNoInitial message spoken when the call starts
languagestringNoLanguage code (default: "en")
tool_idsarray[string]NoTool IDs to attach to the agent
knowledge_idsarray[string]NoKnowledge base IDs for RAG
max_durationnumberNoMax call duration in seconds (default: 300)
curl -X POST https://api.trunx.io/api/voice/agents \
  -H "Authorization: Bearer tk_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Appointment Confirmer",
    "prompt": "You are a friendly dental office assistant confirming appointments. Verify the patient name, date, and time. If they need to reschedule, collect their preferred date.",
    "voice": "Mark",
    "first_message": "Hi, this is Sarah from Downtown Dental. I am calling to confirm your upcoming appointment.",
    "language": "en",
    "max_duration": 300
  }'
const res = await fetch("https://api.trunx.io/api/voice/agents", {
  method: "POST",
  headers: {
    "Authorization": "Bearer tk_live_...",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    name: "Appointment Confirmer",
    prompt:
      "You are a friendly dental office assistant confirming appointments. Verify the patient name, date, and time. If they need to reschedule, collect their preferred date.",
    voice: "Mark",
    first_message:
      "Hi, this is Sarah from Downtown Dental. I am calling to confirm your upcoming appointment.",
    language: "en",
    max_duration: 300,
  }),
});
const data = await res.json();
import requests

res = requests.post(
    "https://api.trunx.io/api/voice/agents",
    headers={"Authorization": "Bearer tk_live_..."},
    json={
        "name": "Appointment Confirmer",
        "prompt": "You are a friendly dental office assistant confirming appointments. Verify the patient name, date, and time. If they need to reschedule, collect their preferred date.",
        "voice": "Mark",
        "first_message": "Hi, this is Sarah from Downtown Dental. I am calling to confirm your upcoming appointment.",
        "language": "en",
        "max_duration": 300,
    },
)
data = res.json()

Response

{
  "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "name": "Appointment Confirmer",
  "ultravoxId": "uv_agent_xxxxxxxxxxxxxxxx"
}

Get agent

GET /api/voice/agents/{id}

Retrieve agent details including the live Ultravox status.

Response

{
  "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "name": "Appointment Confirmer",
  "ultravoxId": "uv_agent_xxxxxxxxxxxxxxxx",
  "prompt": "You are a friendly dental office assistant...",
  "voice": "Mark",
  "first_message": "Hi, this is Sarah from Downtown Dental...",
  "language": "en",
  "max_duration": 300,
  "tool_ids": [],
  "knowledge_ids": [],
  "createdAt": "2026-03-09T15:30:00.000Z"
}

Returns 404 if the agent ID does not exist.


List agents

GET /api/voice/agents

Retrieve all agents for your account.

Query parameters

ParameterTypeRequiredDescription
limitnumberNoMax agents to return (default: 50)

Response

{
  "agents": [
    {
      "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
      "name": "Appointment Confirmer",
      "ultravoxId": "uv_agent_xxxxxxxxxxxxxxxx",
      "createdAt": "2026-03-09T15:30:00.000Z"
    }
  ],
  "count": 1
}

Update agent

PATCH /api/voice/agents/{id}

Update an existing agent. All fields are optional — only provided fields are changed.

Request body

FieldTypeRequiredDescription
namestringNoAgent name
promptstringNoSystem prompt
voicestringNoVoice ID
first_messagestringNoInitial message when call starts
languagestringNoLanguage code
tool_idsarray[string]NoTool IDs to attach
knowledge_idsarray[string]NoKnowledge base IDs for RAG
max_durationnumberNoMax call duration in seconds

Response

Returns the updated agent object. Returns 404 if the agent ID does not exist.


Delete agent

DELETE /api/voice/agents/{id}

Delete an agent. This also removes the corresponding Ultravox agent resource.

Response

{
  "deleted": true,
  "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}

Returns 404 if the agent ID does not exist.


Create agent call

POST /api/voice/agents/{id}/call

Place an outbound call using this agent's configuration. The agent's prompt, voice, tools, and knowledge bases are used automatically.

Request body

FieldTypeRequiredDescription
tostringYesDestination phone number in E.164 format
fromstringNoCaller ID in E.164 format. Auto-selected if omitted.
curl -X POST https://api.trunx.io/api/voice/agents/a1b2c3d4-e5f6-7890-abcd-ef1234567890/call \
  -H "Authorization: Bearer tk_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "to": "+14155551234"
  }'
const agentId = "a1b2c3d4-e5f6-7890-abcd-ef1234567890";
const res = await fetch(
  `https://api.trunx.io/api/voice/agents/${agentId}/call`,
  {
    method: "POST",
    headers: {
      "Authorization": "Bearer tk_live_...",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      to: "+14155551234",
    }),
  }
);
const data = await res.json();
import requests

agent_id = "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
res = requests.post(
    f"https://api.trunx.io/api/voice/agents/{agent_id}/call",
    headers={"Authorization": "Bearer tk_live_..."},
    json={
        "to": "+14155551234",
    },
)
data = res.json()

Response

{
  "id": "f1e2d3c4-b5a6-7890-abcd-ef1234567890",
  "callId": "CAxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
  "status": "initiated",
  "agentId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}

Returns 404 if the agent ID does not exist.

When from is omitted, the system automatically selects the best available DID based on health score and local presence to the destination number.

On this page