REST API
Errors
Status codes and error bodies of the REST API, and the validation messages you can get back.
Errors are JSON with a message. Validation errors add an errors object keyed by field.
Status codes
| Status | When |
|---|---|
200 |
The call was handled. Check status and sent in the body. See Send notification. |
202 |
A segment or tag send was accepted with status: "queued". Xulo sends it in the background. See Send notification. |
401 |
No key, a wrong key, a revoked key, a key in the query string, or an organization perk_ key. |
402 |
Delivery is paused because the app has an invoice past its due date. Nothing is recorded or sent. |
403 |
The key's IP lock refused the calling address. |
404 |
app_id or bundle_id is not the key's app, or the send id does not exist on this app. |
409 |
A call with the same idempotency key is still being handled. The response has Retry-After: 1. See Idempotency. |
422 |
The body did not pass validation. |
429 |
Too many requests. See Rate limits. |
A replayed call returns the status of the first call, with the header Idempotent-Replay: true.
Bodies
JSON
{ "message": "Invalid REST API key." }
JSON
{ "message": "This REST key is locked to other IP addresses." }
JSON
{ "message": "Delivery is paused until the invoice for this app is paid." }
JSON
{ "message": "A request with this idempotency key is still in progress. Retry in a moment." }
JSON
{ "message": "Too many requests. Retry after 1 second." }
A 404 has an empty message:
JSON
{ "message": "" }
A 422 names the field:
JSON
{
"message": "The push needs a message.",
"errors": {
"contents": ["The push needs a message."]
}
}
Validation messages
| Field | Message |
|---|---|
app_id |
Name the app with its app id. |
contents |
The push needs a message. |
contents |
Keep the message to 2000 characters. |
contents |
This notification is larger than 4KB. |
contents, headings |
Send languages as an object, such as {"en": "Hello"}. |
contents, headings |
Use a language code such as en or tr. |
headings |
Keep the title to 120 characters. |
included_segments |
Name one segment, or a tag, or the subscriptions, or the external ids. Do not mix them. |
included_segments |
Send to one segment. |
included_segments |
That segment is not on this app. |
included_segments, tag |
This send reaches 1,200,000 devices. One send reaches at most 1,000,000. |
included_segments, include_subscription_ids, include_external_ids |
Send a list. |
tag |
tag is an object with key and value. |
tag |
tag needs a key and a value. |
tag |
include_missing is true or false. |
include_subscription_ids |
Send to 500 subscriptions or fewer. |
include_subscription_ids |
A subscription id is a UUID. |
include_external_ids |
Send to 500 external ids or fewer. |
include_external_ids |
An external id is too long. |
send_after |
send_after needs a time. |
send_after |
That time has already passed. |
delayed_option |
delayed_option is timezone, or leave it out. |
throttle_rate_per_minute |
throttle_rate_per_minute is a whole number from 1 to 100000. |
url |
Use an https address or an app address such as tips://match/1. |
url |
Send one address. url and app_url differ. |
url |
Keep the address to 500 characters. |
image |
The image needs an https address. |
data |
data is a dictionary of strings. |
data |
data keys are strings. |
data |
data values are strings. |
buttons |
buttons is a list of one button. |
buttons |
Send one button. |
buttons |
A button has an id and a text. |
Idempotency-Key, idempotency_key |
Use a short idempotency key: letters, numbers, dot, or dash. |
idempotency_key |
idempotency_key is a string. |
idempotency_key |
The Idempotency-Key header and idempotency_key differ. Send one key. |
idempotency_key |
This idempotency key was already used with a different request. |
The image message also covers big_picture and ios_attachments. The device cap message names the field you sent, tag or included_segments, and the real device count.
Retrying
- Do not retry
401,403,404or422without changing the request. - After a
402, nothing goes out until the invoice is paid. - After a
409, wait forRetry-Afterand retry with the same idempotency key. - After a
429, wait forRetry-After. - After a timeout or a
5xx, retry with the same Idempotency-Key.