Who this is for. Anyone writing the part of a client that reads responses. The full table is on Requests and responses; this page is about acting on it.
The envelope
A JSON answer has result, success or error. A success carries data, shaped by your selector, and a list adds totalCount. A write adds a message such as “The Page has been saved successfully.”. An error carries a message, and a failed validation also validationErrors.
Branch on the HTTP status first and on result second. A handful of routes answer outside the envelope and say so on their reference page: a file upload, the country lookups, a form submission's status, a web event (whose body is whatever its job returns).
What each status tells a client to do
| Status | Means | Do |
|---|---|---|
| 200 | Done. Writes answer 200 too, never 201 (registering a member is the one exception) | Read data; on a read of a list, check it against what you filtered for (Confirming a request did what you asked) |
| 400 | A parameter is malformed, such as a limit that is not a number | Fix the request; do not retry it as it is |
| 401 | No credentials. The body is empty; a header x-reason: not logged in says why | Authenticate. Do not try to parse the body |
| 403 | A credential was refused: an access token that has expired or been revoked (“Token doesn't exist or is not valid”), or a cookie session's write without its CSRF token | On the token message, refresh the token once and retry; otherwise fix the request |
| 404 | No such route or no such record: both say “Page or record not found”. By default it is also the answer to a caller who may not do this, such as a site member on an admin route; a site setting, Access Denied (Authenticated), can make that a 403 | Check the path against the reference, then the caller's permissions |
| 409 | A conflict, such as continuing a form submission that is already complete | Start again from fresh data |
| 422 | Validation failed: nothing was saved | Show validationErrors beside the fields (below) |
| 500 | The server could not complete the request | Log it with the request; retry only a read |
Form submissions add 202 (a payment is pending) and 207 (stored, but some answers failed the form's rules, so the submission is not complete; it carries validationErrors like a 422); Submitting a form through the API covers them.
The expired token is a 403, not a 401. A client that refreshes only on 401 will treat an expired token as a permission problem and give up. Match the message, refresh once, and stop if the retry fails the same way. And a 404 on a record you know exists usually means the caller may not see it, not that it is gone.
Ask for JSON
Send Accept: application/json on every request. With it, errors come back as JSON: a malformed parameter, for example, is a 400 that names the parameter.
Putting a validation error beside its field
The error integrators meet most is a 422 with validationErrors, keyed by the name of the field you sent. Each value is a list, because a field can fail more than one rule.