Create a dashboard test call
POST /api/v1/agents/{agent_uuid}/test-call — browser WebRTC test session for a saved agent.
POST /api/v1/agents/{agent_uuid}/test-callStart a browser test call (a SmallWebRTC webcall) against a saved agent. This is what the agent editor's "Talk to agent" button calls. It runs the same wallet + concurrency gates as POST /call, creates a pending webrtc call row, and returns the signaling offerUrl the browser connects to.
Dashboard test path, not the general API
For production traffic, use POST /call with transport=websocket or transport=webrtc. This endpoint exists for the dashboard's built-in tester.
Authentication
X-API-Key: zsk_...Path parameters
| Param | Type | Description |
|---|---|---|
agent_uuid | string (UUID) | The uuid of the agent to test. |
Request body
Optional. A bare POST with no body works. Both fields are optional:
| Field | Type | Default | Notes |
|---|---|---|---|
contextVariables | {string: string} | null | null | Seed the runner's {{var}} substitution for this test. |
telephonySim | bool | false | Test-only. When true, prepends an 8 kHz μ-law telephony simulation to the audio-in filter so the tester hears what phone callers hear. Stripped before config validation — never part of the saved AgentConfig. |
Response
{
"callId": "call_4e4e571f8c9b3cf8e99d",
"offerUrl": "/api/v1/webrtc/offer/call_4e4e571f8c9b3cf8e99d",
"status": "pending",
"agentName": "Sales bot"
}| Field | Notes |
|---|---|
callId | The call's identifier — also the history row under GET /calls. |
offerUrl | The SmallWebRTC signaling endpoint. The browser POSTs its SDP offer here; the pipeline launches when the offer arrives. |
status | Always "pending" — becomes "active" once the offer handshake completes. |
agentName | Echo of the agent's name. |
SmallWebRTC offer flow
After the 201, the browser establishes the media session: POST its SDP offer to offerUrl (/api/v1/webrtc/offer/{call_id}) and PATCH trickle-ICE candidates to the same path. The agent pipeline starts on the first offer. See Create a WebRTC call for the full handshake.
Examples
curl -X POST https://dashboard.zoxa.ai/api/v1/agents/550e8400-e29b-41d4-a716-446655440000/test-call \
-H "X-API-Key: zsk_..." \
-H "Content-Type: application/json" \
-d '{ "contextVariables": { "customerName": "Aman" } }'const res = await fetch(
`https://dashboard.zoxa.ai/api/v1/agents/${agentUuid}/test-call`,
{
method: "POST",
headers: { "X-API-Key": "zsk_...", "Content-Type": "application/json" },
body: JSON.stringify({ contextVariables: { customerName: "Aman" } }),
},
);
const { callId, offerUrl } = await res.json();
// Then POST the browser's SDP offer to offerUrl to start the media session.import httpx
resp = httpx.post(
f"https://dashboard.zoxa.ai/api/v1/agents/{agent_uuid}/test-call",
headers={"X-API-Key": "zsk_..."},
json={"contextVariables": {"customerName": "Aman"}},
)
data = resp.json()
call_id, offer_url = data["callId"], data["offerUrl"]Errors
| Status | detail | When |
|---|---|---|
400 | "No organization selected" | Auth missing org. |
402 | wallet error | Insufficient balance to start a call. |
403 | wallet error | Wallet gate rejected the call (non-balance reason). |
404 | "Agent not found" | UUID doesn't exist in your org. |
Related
POST /call— production WebSocket call pathPOST /call— production WebRTC call path (same signaling flow)