zoxaAI
Homepage
API ReferenceExamples

Quickstart

From zero to a placed call in 5 minutes. Auth, create an agent, place a call, fetch the transcript.

This is the shortest possible path from zero to a real voice call. We'll:

  1. Get an API key
  2. Create an agent
  3. Place an outbound call to your own phone
  4. Fetch the transcript when it ends

You need: a phone, a Twilio account with one phone number and the AccountSid + AuthToken handy.

Get an API key

Dashboard → API Keys → Create API Key. The full zsk_... value is never displayed — use the copy button, now or anytime later from the API Keys page.

X-API-Key: zsk_...

Create an agent

The minimum useful agent: a system prompt, the LLM, voice, and STT.

AGENT_UUID=$(curl -s -X POST https://dashboard.zoxa.ai/api/v1/agents \
  -H "X-API-Key: zsk_..." \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Hello-world bot",
    "systemPrompt": "You are a friendly voice agent. Ask the caller how their day is going. Keep replies short.",
    "greeting": { "firstMessages": ["Hi! How is your day going?"] },
    "llm": { "provider": "openai", "model": "gpt-5.4-mini" },
    "tts": { "provider": "elevenlabs", "voice": "7qBNUtXRGP0jPi0H4r8k" },
    "stt": { "provider": "soniox" }
  }' | jq -r .uuid)

echo "Agent: $AGENT_UUID"
const res = await fetch("https://dashboard.zoxa.ai/api/v1/agents", {
  method: "POST",
  headers: { "X-API-Key": "zsk_...", "Content-Type": "application/json" },
  body: JSON.stringify({
    name: "Hello-world bot",
    systemPrompt: "You are a friendly voice agent. Ask the caller how their day is going. Keep replies short.",
    greeting: { firstMessages: ["Hi! How is your day going?"] },
    llm: { provider: "openai", model: "gpt-5.4-mini" },
    tts: { provider: "elevenlabs", voice: "7qBNUtXRGP0jPi0H4r8k" },
    stt: { provider: "soniox" },
  }),
});
const agent = await res.json();
console.log("Agent:", agent.uuid);
import httpx
agent = httpx.post(
    "https://dashboard.zoxa.ai/api/v1/agents",
    headers={"X-API-Key": "zsk_..."},
    json={
        "name": "Hello-world bot",
        "systemPrompt": "You are a friendly voice agent. Ask the caller how their day is going. Keep replies short.",
        "greeting": { "firstMessages": ["Hi! How is your day going?"] },
            "llm": {"provider": "openai", "model": "gpt-5.4-mini"},
        "tts": {"provider": "elevenlabs", "voice": "7qBNUtXRGP0jPi0H4r8k"},
        "stt": {"provider": "soniox"},
    },
).json()
print("Agent:", agent["uuid"])

The response includes uuid (you'll pass this as agentId next) and id (used by GET/PUT/DELETE /agents/{id}).

Place a call to your phone

API-first outbound — Twilio creds inline, the agent we just created, your phone number as the dialed target.

CALL_ID=$(curl -s -X POST https://dashboard.zoxa.ai/api/v1/call \
  -H "X-API-Key: zsk_..." \
  -H "Content-Type: application/json" \
  -d "{
    \"type\": \"outbound\",
    \"callConfig\": {
      \"provider\": \"twilio\",
      \"phoneNumber\": \"+1...your twilio number\",
      \"auth\": { \"accountSid\": \"AC...\", \"authToken\": \"...\" }
    },
    \"toNumber\": \"+1...your personal phone\",
    \"agentId\": \"$AGENT_UUID\"
  }" | jq -r .callId)

echo "Call: $CALL_ID"
const call = await fetch("https://dashboard.zoxa.ai/api/v1/call", {
  method: "POST",
  headers: { "X-API-Key": "zsk_...", "Content-Type": "application/json" },
  body: JSON.stringify({
    type: "outbound",
    callConfig: {
      provider: "twilio",
      phoneNumber: "+1...your twilio number",
      auth: { accountSid: "AC...", authToken: "..." },
    },
    toNumber: "+1...your personal phone",
    agentId: agent.uuid,
  }),
}).then((r) => r.json());

console.log("Call:", call.callId);
call = httpx.post(
    "https://dashboard.zoxa.ai/api/v1/call",
    headers={"X-API-Key": "zsk_..."},
    json={
        "type": "outbound",
        "callConfig": {
            "provider": "twilio",
            "phoneNumber": "+1...your twilio number",
            "auth": {"accountSid": "AC...", "authToken": "..."},
        },
        "toNumber": "+1...your personal phone",
        "agentId": agent["uuid"],
    },
).json()
print("Call:", call["callId"])

Your phone should ring within a few seconds. The agent will speak first.

Fetch the transcript after you hang up

Either poll, or set agent.webhook and react when the call.ended event arrives.

curl https://dashboard.zoxa.ai/api/v1/calls/$CALL_ID \
  -H "X-API-Key: zsk_..." | jq '{
    status,
    connectionStatus,
    endedReason,
    durationSeconds,
    cost,
    transcript: .transcript.url,
    recording: .recordings[0].url
  }'

Once status is "completed", transcript.url and recordings[].url are signed URLs (valid ~1 hour) you can download.

What you just built

A complete outbound voice agent pipeline:

  • One agent stored in your org — reusable across thousands of calls
  • One API call to dial — credentials are passed inline, never stored after the call ends
  • Full call history — transcript, recording, cost, latency, per-turn breakdown, all at GET /calls/{callId}

Next steps

GoalRead
Add tools (HTTP calls, end call, transfer, KB)Tool types
Receive inbound calls instead of dialing outInbound flow
Run the agent in a browser (no phone)Browser flow
Bulk-dial a list of contactsCampaigns overview
Get webhook events instead of pollingWebhook events
Decide between WebSocket / WebRTC / phoneChoosing a transport

On this page