Errors

Every error has the same JSON shape. Switch on the code, not the HTTP status or the message.

The error body

{
  "error": {
    "code": "rate_limited",
    "message": "This account has sent its 500 messages for today.",
    "details": { "limit": "messages_per_day", "max": 500, "resetAt": "2026-11-09T00:00:00.000Z" }
  }
}
FieldDescription
errorrequired
object
What went wrong.
↳ coderequired
invalid_request | pairing_invalid | pairing_expired | unauthorized | forbidden | not_found | payload_too_large | rate_limited | internal | conflict | string
Machine-readable error code. Clients switch on this, not on the HTTP status. Open enum: new codes may be added without a protocol bump; treat an unknown code by its HTTP status.
↳ messagerequired
string
Human-readable, English, for logs and developers, not for end users.
↳ details
any
Code-specific. unauthorized carries { "reason": "revoked" } when the device credential was revoked. forbidden may carry { "reason": "account_suspended" } (the account behind the credential is suspended) or a host-defined reason such as device_limit, topic_limit or images_not_enabled, often with max; rate_limited may carry { "limit", "max", "resetAt" }.

New codes may be added. Treat a code you don't know by its HTTP status.

Codes

CodeWhenWhat to do
invalid_request
400
A field is missing, too long or of the wrong type, or a header has a value it does not accept.Read message for the field and fix the request. Retrying unchanged fails again.
pairing_invalid
400
Only returned when pairing a phone, never to app tokens.Ask for a new pairing code on the dashboard.
pairing_expired
400
Only returned when pairing a phone, never to app tokens.Ask for a new pairing code on the dashboard.
unauthorized
401
The Authorization header is missing, or the token is not valid or has been revoked.Check the token. A revoked token stays revoked; create a new one on the dashboard.
forbidden
403
The token may not send to this topic, or the account does not allow what was asked. details.reason says which: topic_limit, images_not_enabled or account_suspended.Use a topic the token may send to, or change the request.
not_found
404
No such endpoint. Usually a typo in the path or the wrong base URL.Check the URL against the reference.
payload_too_large
413
The request body is over 16 KB.Send less. The message body itself is limited to 2048 characters.
rate_limited
429
The account reached its daily limit, or the token sent too fast.Wait Retry-After seconds. See Limits and usage.
internal
500
Something went wrong on our side.Retry with backoff. If it keeps happening, tell us.
conflict
409
The Idempotency-Key was already used with a different request, or the first send with it has not finished.Use a new key for a new message. For a repeat of a running send, wait a moment and retry with the same key.