Skip to content

Results and limits / Errors

Errors

One error shape for every endpoint, every code with its HTTP status, and when to retry.

Error format#

Every error has the same JSON shape: an error object with a stable code, a human-readable message, the requestId and, for validation problems, a details list. Branch on code, never on message.

⫻

422 Unprocessable Entity

HTTP/1.1 422 Unprocessable EntityContent-Type: application/jsonX-Request-Id: req_0199b1c27a4e7c3d9f1e2b6a8d4c5e11
{  "error": {    "code": "INVALID_RECIPIENT",    "message": "Recipient \"ops\" has no connected browsers",    "requestId": "req_0199b1c27a4e7c3d9f1e2b6a8d4c5e11"  }}
  • Every response, success or error, carries an X-Request-Id header with the same id. Include it when you ask for help.
  • Responses allow any origin and expose the X-Request-Id and Retry-After headers to browser code.
  • Responses are sent with Cache-Control: no-store.

Error codes#

CodeHTTPWhen
VALIDATION_ERROR400The body breaks a rule (a connect request reports INVALID_SUBSCRIPTION instead) or is not valid JSON; the body is over 16,384 bytes (by Content-Length or actual size); the encoded notification is over 3,000 bytes; Idempotency-Key is not 1–255 characters; or an action event has no action id.
UNAUTHORIZED401The API key is missing, malformed, unknown or revoked, or a browser event token is invalid.
QUOTA_EXCEEDED402The free monthly allowance is used up and the credit balance cannot cover this send's attempts. Nothing is stored, sent or charged.
FORBIDDEN403A live key was used from a browser (the request carries an Origin header); call the API from your server or use a test key. Also returned when connecting a browser would go over 20 connected browsers per recipient or 100 per account.
PROJECT_SUSPENDED403The API key's project is suspended. Contact support.
NOT_FOUND404The notification is not in the key's project, or its id is not a UUID; the connect link is unknown, expired, revoked, used up or its project is suspended; the attempt of a browser event does not exist; the browser to disconnect does not exist; or the route or method does not exist (there is no 405).
IDEMPOTENCY_CONFLICT409The Idempotency-Key was already used with a different body. A concurrent request with the same key and body waits for the first and gets its replay instead.
INVALID_RECIPIENT422No recipient with that name exists in the key's project, or it has no connected browsers. Nothing is stored or charged.
INVALID_SUBSCRIPTION422The connect request's subscription is invalid, or its endpoint is not a supported browser push service.
RATE_LIMITED429Too many requests. The Retry-After header says how many seconds to wait. See rate limits.
INTERNAL_ERROR500Something failed on our side. The message is Something went wrong. Try again with the same Idempotency-Key.

Validation details#

A VALIDATION_ERROR about the body lists every problem in details. Each entry has the field path (dots for nesting, such as actions.0.title) and a message. An empty path means the top level of the body, for example an unknown field.

⫻

400 VALIDATION_ERROR

{  "error": {    "code": "VALIDATION_ERROR",    "message": "Request body is invalid",    "requestId": "req_0199b1c27a4e7c3d9f1e2b6a8d4c5e11",    "details": [      {        "path": "title",        "message": "Too big: expected string to have <=120 characters"      },      {        "path": "",        "message": "Unrecognized key: \"colour\""      }    ]  }}
NoteUnknown fields are rejected rather than ignored, so a typo fails loudly. Every field and its limits are in message options.

When to retry#

  • 429 RATE_LIMITED: wait for the Retry-After seconds, then retry.
  • 500 INTERNAL_ERROR and network errors or timeouts: retry with backoff and the same Idempotency-Key, so the notification is sent at most once. See idempotency.
  • 409 IDEMPOTENCY_CONFLICT: the key was used with a different body. Do not retry; send the original body or use a new key for a new event.
  • Any other 4xx: fix the request first. Retrying it unchanged gets the same error.
WarningWithout an Idempotency-Key, retrying after a timeout can send the notification twice, because the first request may have succeeded.