Responses and errors
The envelope
Section titled “The envelope”Every response is a JSON object with the same four fields, followed by the endpoint’s own data at the top level:
{ "restaurant_timezone": "America/New_York", "fingerprint": "b82418952c", "success": true, "response_at": "11/06/2026 02:15pm", "item": { "_id": "6650f0c2a1b2c3d4e5f60718", "number": "WD-100234", "balance": 0 }}| Field | Type | Meaning |
|---|---|---|
success |
boolean | true if the request did what it asked. Always check this. |
restaurant_timezone |
string or null | IANA timezone of the token’s restaurant. See Money and timezones. |
fingerprint |
string or null | Short id of the token that made the call. |
response_at |
string | Server time of the response, MM/DD/YYYY hh:mmam. Informational only. |
| …data | The endpoint’s payload, e.g. item, items, total. The API reference lists it per endpoint. |
The data is merged into the top level, not nested under a data key. Ignore fields you do not
recognise: new ones can be added at any time.
Errors come back as HTTP 200
Section titled “Errors come back as HTTP 200”Validation failures: error_code: 101
Section titled “Validation failures: error_code: 101”When the request does not pass validation (a missing field, a wrong type, a value too long), the
response carries error_code: 101 and the messages per field:
{ "success": false, "error_code": 101, "errors": { "number": ["The number field is required."], "cardholder_email": ["The cardholder email must be a valid email address."] }}errors maps each field name to a list of messages. Validation responses carry only these three
fields, without the rest of the envelope.
Business-rule failures
Section titled “Business-rule failures”When the request is valid but cannot be done (no such card, a number already in use, a units total
that would go below zero) the response is the full envelope with success: false and errors in
the same shape. Most carry no error_code:
{ "restaurant_timezone": "America/New_York", "fingerprint": "b82418952c", "success": false, "response_at": "11/06/2026 02:15pm", "errors": { "number": ["This card number is already in use."] }, "bot": "¯\\_(ツ)_/¯"}Failed responses also include a bot field. It carries no information; ignore it.
Error codes
Section titled “Error codes”error_code |
Meaning |
|---|---|
101 |
Validation failed; see errors. |
403 |
The token may not do this (HTTP 403, or HTTP 200 on restaurant-scoped routes). |
| absent | A business-rule failure; the message in errors says which. |
The messages in errors are written for people and may be translated. Branch on success,
error_code and the field name, not on message text.
Handling responses
Section titled “Handling responses”const res = await fetch(url, { headers: { 'X-KATALYST-AUTH-TOKEN': token } });const body = await res.json();
if (res.status === 401 || res.status === 403) throw new AuthError(body);if (!body.success) { // body.errors: { field: [messages] }; body.error_code === 101 for validation throw new KatalystError(body.error_code ?? null, body.errors);}return body;