Create an API key: Administration → API Key → Add Key. Copy the plain key shown in the modal — it will not be shown again.
Upload an audio asset, or use one already approved in your Audio Library.
Poll Audio Status until status is approved — required before the asset can be used in a broadcast (unless your key auto-approves).
Check your balance for the module your key is scoped to.
Send a broadcast.
Poll the broadcast's number status until it settles.
Authentication
Every request must carry an API key, created from your account's Administration → API
Key screen. The key is shown to you exactly once at creation. It can be supplied any of
the following ways — the first one found wins, checked in this order:
?api_key=cpk_xxxxxxxxxxxx_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx (query, form, or JSON body)
GET/POST equivalence
Every endpoint accepts both GET and POST for the exact same
operation — never PUT, PATCH, or DELETE.
Parameters can be sent as a GET query string, a POST form body, or a POST JSON body —
all equivalent for every endpoint that isn't a file upload.
Response envelope
Every response — success or failure, on every endpoint — has one of these three shapes.
Failure (any code other than REQ_VALIDATION_FAILED):
{
"success": false,
"message": "A short, human-readable description of what went wrong.",
"error": {"code": "SOME_ERROR_CODE", "details": null},
"request_id": "9c4a2e3e-9b7b-4a1e-8f39-2a3f6b7c9d10"
}
Failure (REQ_VALIDATION_FAILED specifically):
{
"success": false,
"message": "The given data was invalid.",
"error": {
"code": "REQ_VALIDATION_FAILED",
"fields": [
{"field": "did", "code": "REQ_FIELD_REQUIRED", "message": "The did field is required."}
]
},
"request_id": "9c4a2e3e-9b7b-4a1e-8f39-2a3f6b7c9d10"
}
Rate limits
Two limits apply, and either can produce a SYS_RATE_LIMITED response with a Retry-After header:
Per API key — your normal usage limit, applied once your key has been validated.
Per source IP, for failed authentication only — a much lower limit that bounds invalid-key attempts. It does not apply once a request authenticates successfully.
Error codes
Codes marked Reserved are defined in the catalogue
but not currently emitted by anything in this API.
AUTH_*
Code
HTTP status
Meaning
What to do
AUTH_KEY_MISSING
401
No API key was found on the request, in any of the four transports.
Check the key is actually being sent — see "Authentication".
AUTH_KEY_INVALID
401
The key doesn't match any active key. Covers both "no such key" and "key exists but the secret is wrong" — these are deliberately indistinguishable from the outside.
Check the key was copied correctly; it's shown only once at creation, so a garbled copy may need a fresh key.
AUTH_KEY_EXPIRED
401
The key has passed its expiry date, or has been revoked/regenerated.
Generate a new key from Administration → API Key.
AUTH_KEY_DISABLED
403
The key exists and hasn't expired, but is currently disabled.
Re-enable it from Administration → API Key, or generate a new one.
AUTH_IP_NOT_ALLOWED
403
The key has an IP allowlist configured, and the request's source IP isn't on it.
Add your server's IP to the key's allowlist, or clear the allowlist to permit all IPs.
AUTH_MODULE_NOT_ALLOWED
403
The key is scoped to a specific module and this endpoint belongs to a different one.
Use a key scoped to "all", or the correct module, for this endpoint.
AUTH_ACCOUNT_INACTIVE
403
The account that owns this key isn't currently active.
Contact your account administrator.
REQ_*
Code
HTTP status
Meaning
What to do
REQ_VALIDATION_FAILED
422
One or more parameters failed validation. error.fields lists each failed field with its own code and message.
Fix the named field(s) and retry.
REQ_NOT_FOUND
—
404: the URL doesn't match any endpoint in this API. 405: the URL matches an endpoint but the HTTP verb isn't GET/POST. Also the fallback for any unmatched/foreign route.
Check the URL and method against this document.
REQ_NUMBERS_LIMIT_EXCEEDED
422
Voice Broadcast's numbers array exceeds the per-request cap (1,000 by default).
Split the recipient list into multiple requests.
REQ_SCHEDULE_IN_PAST
422
schedule_at resolved to a time that's already passed by the moment the request was actually processed.
Resend with a later schedule_at, or omit it to send immediately.
REQ_SCHEDULE_INVALID_FORMAT
422
schedule_at isn't a value the date parser accepts.
Use ISO-8601, with or without a UTC offset.
REQ_AUDIO_SELECTION_INVALID
422
Neither or both of audio_uid/audio_reference were supplied where exactly one is required.
Supply exactly one of audio_uid, audio_reference.
REQ_TARGET_SELECTION_INVALID (Reserved)
—
Defined in the catalogue but not currently emitted anywhere in this API — no live endpoint has a target-selection ambiguity of this shape yet.
Not applicable today.
REQ_FIELD_REQUIRED
—
Field-level only — never a top-level error.code. Appears as one entry inside error.fields when that field was missing.
Supply the named field.
REQ_FIELD_INVALID_FORMAT
—
Field-level only. The default field-level code for any validation rule not covered by a more specific one.
Fix the named field's format.
REQ_FIELD_OUT_OF_RANGE
—
Field-level only. The field failed a min/max/between/size rule.
Adjust the named field's value/length within range.
REQ_FIELD_UNKNOWN_VALUE
—
Field-level only. The field's value isn't one of the accepted enumerated values.
Use one of the documented allowed values for that field.
REQ_FIELD_NOT_PERMITTED
—
Field-level only. The field was supplied but this endpoint doesn't accept it.
Remove the named field from your request.
REQ_IDEMPOTENCY_KEY_CONFLICT
409
Voice Broadcast only. The Idempotency-Key header you sent was already used, but with a different request body than this one.
Use a fresh Idempotency-Key for a genuinely new request, or resend the exact original body if you meant to replay it.
AUDIO_*
Code
HTTP status
Meaning
What to do
AUDIO_NOT_FOUND
404
audio_uid/reference doesn't match any of your audio assets.
Check audio_uid/reference against Audio Status.
AUDIO_NOT_APPROVED
422
The audio asset hasn't been approved, or hasn't been delivered to the operator yet.
Poll Audio Status until status is approved, then retry.
AUDIO_DISABLED
422
The audio asset has been turned off via Audio Enable/Disable.
Re-enable it, or select a different asset.
AUDIO_DELIVERY_FAILED
—
Broadcast with TTS only. Never an HTTP error: returned as error.code on Broadcast with TTS Status when the generated audio could not be delivered to the voice operator, so the broadcast was not created.
Send a new Broadcast with TTS request. If it keeps failing, contact support with the request id.
BCAST_*
Code
HTTP status
Meaning
What to do
BCAST_NOT_FOUND
404
id/reference doesn't match any of your broadcasts.
Check the id/reference against the response from Voice Broadcast.
BCAST_DID_INVALID
422
did doesn't match any of your account's active, voice.broadcast-enabled DIDs.
Check the number against your account's DID list.
BCAST_NO_VALID_NUMBERS
422
Every recipient number submitted was invalid or a duplicate.
Check error.details.rejected_numbers for the reason per number, then retry with valid ones.
BCAST_ALL_NUMBERS_INVALID
422
A more specific case of BCAST_NO_VALID_NUMBERS: every rejected number failed specifically because it could not be normalized to a valid number.
Reformat every number in the request and resend.
BCAST_ALL_NUMBERS_DUPLICATE (Reserved)
—
Provably unreachable today — numbers deduplication always keeps a number's first occurrence as valid, so a submission can never reach "all numbers rejected" with duplicate as the only reason.
Not applicable today.
TTS_*
Code
HTTP status
Meaning
What to do
TTS_AUTO_APPROVAL_REQUIRED
403
This API key does not have audio auto-approval enabled, which Broadcast with TTS needs.
Contact support to enable audio auto-approval for this key.
TTS_LANGUAGE_UNAVAILABLE
422
Text to speech is not enabled for the requested language on your account. error.details.available_languages lists the ones that are.
Send one of the available languages.
TTS_UNAVAILABLE
—
Never an HTTP error: returned as error.code on Broadcast with TTS Status when text to speech stopped being available for the language while the request was being prepared.
Send a new request later, or in another available language.
TTS_GENERATION_FAILED
—
Never an HTTP error: returned as error.code on Broadcast with TTS Status when the audio could not be generated from the text. No TTS credits are charged.
Send a new request. If it keeps failing, check the text or contact support with the request id.
TTS_TEMPLATE_NOT_FOUND
404
template_id doesn't match any template on your account.
List your templates with TTS Templates and use one of their ids.
TTS_TEMPLATE_NOT_APPROVED
422
The template is pending or rejected (error.details.status). Also returned as error.code on Broadcast with TTS Status — not an HTTP error there — when the template was edited or unapproved while the audio was being prepared.
Wait until the template is approved, then send a new request.
TTS_TEMPLATE_VARIABLE_MISSING
422
A template variable has no value (or an empty one). error.details.variables lists every variable with a problem.
Send a value for every variable the template uses (TTS Templates lists them).
TTS_TEMPLATE_VARIABLE_INVALID
422
A variable value breaks a rule: more than 30 characters, a line break or control character, or { }. error.details.variables says which and why.
Shorten or clean the value and send again.
TTS_BROADCAST_NOT_FOUND
404
id/reference doesn't match any of your Broadcast with TTS requests.
Check the id/reference against the response from Broadcast with TTS.
BILLING_*
Code
HTTP status
Meaning
What to do
BILLING_INSUFFICIENT_CREDITS
402
Your voice.broadcast wallet balance doesn't cover the estimated cost of the request.
Top up your voice.broadcast balance, or reduce the recipient count, then retry.
BILLING_NO_ACTIVE_PLAN
402
Voice Click to Call only (2026-09-14). Your account has no active Click to Call plan.
Ask your account administrator to assign a Click to Call plan, then retry.
BILLING_PLAN_QUOTA_EXHAUSTED
402
Voice Click to Call only. Your account's Click to Call plan quota is used up and the plan does not allow overdraft.
Ask your account administrator to assign a plan with a larger quota or overdraft enabled, then retry.
C2C_*
Code
HTTP status
Meaning
What to do
C2C_NOT_FOUND
404
uid/event_id/reference doesn't match any Click to Call on your account.
Check the identifier against the response from the send endpoint.
C2C_DID_INVALID
422
did_id doesn't match any of your account's active, Click to Call-eligible DIDs.
Check the DID against your account's DID list and that Click to Call is enabled on it.
C2C_NUMBER_INVALID
422
agent_number or customer_number cannot be normalized to a valid number for your account.
Send each number as 10 digits, 0 + 10 digits, or your country code + 10 digits.
C2C_LOOPBACK
422
agent_number and customer_number are the same number.
Supply two different numbers — a call to oneself is a test, not a product.
C2C_CONCURRENT_CALL
409
A Click to Call is already in flight on your account, at or above your plan's concurrency limit. The refused attempt is still recorded; its uid is in error.details.
Wait for a call in progress to finish (poll the status endpoint), then retry.
SYS_*
Code
HTTP status
Meaning
What to do
SYS_RATE_LIMITED
429
Too many requests. A Retry-After header on the response says how many seconds to wait.
Wait for the Retry-After duration, then retry.
SYS_PROVIDER_ERROR
502
The call succeeded on our side but failed talking to the underlying voice provider/operator.
Safe to retry after a short delay. If it persists, contact support with the request_id.
SYS_PROVIDER_TIMEOUT (Reserved)
—
Reserved for a possible future endpoint that calls the operator synchronously in the request/response cycle; nothing in this API does that today.
Not applicable today.
SYS_PROVIDER_REJECTED (Reserved)
—
Reserved, same reason as SYS_PROVIDER_TIMEOUT.
Not applicable today.
SYS_INTERNAL_ERROR
500
An unexpected error on our side. You will never see a stack trace or debug output here.
Contact support with the request_id.
URL_*
Code
HTTP status
Meaning
What to do
URL_LINK_NOT_FOUND
404
The URL link ID doesn't match any link owned by your account.
Verify the link ID and ensure your API key belongs to the owning account.
URL_LINK_NOT_APPROVED
422
The operation requires an approved link, but this link is currently pending, rejected, or disabled.
Wait for admin approval before performing this operation.
URL_LINK_EXPIRED
422
The link has passed its expiration date.
Renew the link via the Renew API endpoint.
URL_LINK_DISABLED
422
The link has been disabled by an administrator.
Contact account support to appeal the link status.
We are happy to help you!
Please fill in the below details for us to get in touch with you.