Build
Calls
A call is one conversation between an agent and a person. This page follows a call from the request that starts it to the record it leaves behind.
The life of a call
| Status | Meaning | Event sent |
|---|---|---|
created | You have started the call and the agent is on its way to the room. | call.started |
active | The agent is in the room. The caller may or may not have joined yet. | call.agent_joined, then call.user_joined |
ended | The room is closed. Duration, cost and the transcript are final. | call.ended |
You start a call with Start a call and hand the livekitUrl and token from its response to your app, which joins the room: see Web and mobile clients. The token can be used to join for an hour unless you set participant.ttlSeconds.
While a call is running
GET /v1/calls/:idRead itThe call’s status and its transcript so far.
POST /v1/calls/:id/saySpeak into itHave the agent say a line right now, in its own voice, such as news from your system that the caller is waiting on.
POST /v1/calls/:id/endEnd itClose the room. The call ends with the reason api.
curl -X POST "https://goblins-call-api.onrender.com/v1/calls/YOUR_CALL_ID/say" \
-H "Authorization: Bearer $CRACKLE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"text": "Your payment just came through. Thank you!"
}'Why a call ended
An ended call carries an endReason:
| Reason | What happened | Billed |
|---|---|---|
user-left | The caller hung up or closed the page. | Yes |
api | You ended it with End a call. | Yes |
max-duration | It reached its time limit, which is never more than 24 hours, or the balance ran out. | Yes |
socket-lost | The caller’s connection dropped and did not come back. | Yes |
agent-shutdown | The agent’s process was stopped, for example during a deploy. | Yes |
room-finished | The room was closed from outside the call. | Yes |
no-user | Nobody ever joined. | No |
dispatch-failed | The agent could not be sent to the room. The request that started the call fails too. | No |
Billing counts from the moment the caller joins, so time the agent spends waiting alone is free. An agent with the endCall built-in tool can also hang up on its own when the conversation is over.
Attaching your own data
metadata takes any JSON you like, such as your own session or order ID. It is stored on the call and sent back with every webhook for it, which is the easy way to tie a call to a record in your system.
curl -X POST "https://goblins-call-api.onrender.com/v1/calls" \
-H "Authorization: Bearer $CRACKLE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"agentId": "ua_3f9a1c2b",
"participant": {
"identity": "customer_123",
"name": "Divya"
},
"metadata": {
"orderId": "A-1042",
"source": "checkout"
}
}'A call in another language
An agent has one language, and a single call can be held in a different one. Send language when you start the call: a language’s id from the catalog, or its iso code.
curl -X POST "https://goblins-call-api.onrender.com/v1/calls" \
-H "Authorization: Bearer $CRACKLE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"agentId": "ua_3f9a1c2b",
"language": "ta",
"variables": {
"customer_name": "Divya"
}
}'That call runs as if the agent had been saved with Tamil as its language. The voice is still the agent’s own, the agent listens for Tamil as well as its own language and English, and the writing rules added to its instructions tell the model to speak Tamil on this call, even where your instructions name another language. The agent itself is not changed. A call that leaves language out, or sends the agent’s own, runs exactly as the agent is saved.
- Hindi and English need only a voice engine that speaks them. Any other language needs an agent with a
cartesiavoice andopenaitranscription, which are itsvoice.providerandstt.provider. For any other agent, and for a language the platform does not list, the request answers400 UNSUPPORTED_LANGUAGE. - Nothing you wrote is translated. A fixed greeting (
greetingModestatic) and the values you send as variables should already be in the call’s language. - Punjabi and Odia are spoken like any other language, but the transcriber does not take them as a hint, so those calls listen with Hindi and English hints.
- The writing rules are part of the agent’s instructions. A call whose
configreplacesprompt.systemhas to name the language in that prompt itself. - The response carries the language as an ISO code, and the call keeps it as
metadata.language.
Settings for one call
config changes how a single call behaves without touching the agent. Four sections may be set. Apart from the language above, everything about the voice, the model and the tools comes from the agent.
call.maxDurationSecondsintegerEnd the call after this many seconds. 0 means no limit of your own. Whatever is set here, a call ends after 24 hours at the latest.
prompt.greetingobjectThis call’s opening: mode (generate, static or none), text and instruction.
prompt.systemstringInstructions for this call, used in place of the agent’s. They are used as written: variables are not filled in and the agent’s tools are not described to the model. Variables are almost always the better way to tailor a call.
turn.minEndpointingDelayMsintegerHow long a pause has to be before the agent takes the caller to have finished speaking.
turn.interruption.enabledbooleanfalse stops the caller from interrupting the agent mid-sentence.
vadobjectVoice-activity settings, for unusual audio conditions.
{
"agentId": "ua_3f9a1c2b",
"config": { "call": { "maxDurationSeconds": 300 } }
}Anything outside those four sections is refused with 403 CONFIG_FIELD_NOT_ALLOWED.
Running out of balance
A call cannot start on an empty balance: the request answers 402 INSUFFICIENT_BALANCE. A call that is running is ended at the point the balance would run out, with the reason max-duration, so a workspace never goes into debt. See Pricing and billing.