Error codes
Successful responses are wrapped in a data object. Error responses are not wrapped.
message is always present. errors is optional, and its entry shape depends on which check failed:
All four can return 400. Parse defensively: read message first, treat errors as optional, and don’t assume every entry carries field or code. See Validation error shapes.
HTTP status reference
Validation error shapes
Several different 400 bodies exist. Branch on message before parsing errors[].
Schema validation
The request body didn’t match the endpoint’s schema.
field is a dotted JSON path; array indices appear as numeric segments (recipients.0).
Recipient validation
The body was well-formed, but one or more recipients were rejected. Note the top-level summary and the six-field error entries - nothing is sent when this fires.
Use POST /broadcasts/validate to check a list against these rules before committing to a broadcast.
Template-variable mismatch
The recipients were fine, but the values supplied don’t satisfy the variables the template declares. An empty string or whitespace counts as missing. Nothing is sent and no credit is reserved.
In dynamic mode the offending rows are listed - capped at the first 10, even when more fail:
In standard mode there is no array - the message names what’s missing:
The SMS equivalent reports field instead of row, with message = Dynamic SMS variables do not match template parameters.
Rate-limit responses
Every 429 carries a Retry-After header (seconds until the limiter resets). Use it to back off rather than retrying immediately.
The message identifies which limiter fired:
Credit safety on enqueue failure
If the API has already debited credit and then the enqueue fails, Teekrr automatically releases the reserved credit and marks the messages as failed. You’ll see 500 - Failed to enqueue broadcast — messages marked failed in this case. No manual ledger correction is needed on your side.