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

StatusMeaningEvent sent
createdYou have started the call and the agent is on its way to the room.call.started
activeThe agent is in the room. The caller may or may not have joined yet.call.agent_joined, then call.user_joined
endedThe 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 it

The call’s status and its transcript so far.

POST /v1/calls/:id/saySpeak into it

Have 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 it

Close 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:

ReasonWhat happenedBilled
user-leftThe caller hung up or closed the page.Yes
apiYou ended it with End a call.Yes
max-durationIt reached its time limit, which is never more than 24 hours, or the balance ran out.Yes
socket-lostThe caller’s connection dropped and did not come back.Yes
agent-shutdownThe agent’s process was stopped, for example during a deploy.Yes
room-finishedThe room was closed from outside the call.Yes
no-userNobody ever joined.No
dispatch-failedThe 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 cartesia voice and openai transcription, which are its voice.provider and stt.provider. For any other agent, and for a language the platform does not list, the request answers 400 UNSUPPORTED_LANGUAGE.
  • Nothing you wrote is translated. A fixed greeting (greetingMode static) 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 config replaces prompt.system has 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.maxDurationSecondsinteger

End 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.greetingobject

This call’s opening: mode (generate, static or none), text and instruction.

prompt.systemstring

Instructions 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.minEndpointingDelayMsinteger

How long a pause has to be before the agent takes the caller to have finished speaking.

turn.interruption.enabledboolean

false stops the caller from interrupting the agent mid-sentence.

vadobject

Voice-activity settings, for unusual audio conditions.

A call capped at five minutes
{
  "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.