Skip to main content

Errors

Every error response has the same shape:

{
"error": {
"type": "insufficient_scope",
"message": "This key does not carry bookings:write",
"docs_url": "https://help.tatiya.space/developers/errors#insufficient_scope",
"request_id": "req_01JQ8Z…"
}
}

Branch on type. Never on message — messages are written for humans, and are expected to change without notice.

HTTPtypeMeaning
400invalid_requestThe body or query didn't validate. Carries fields[].
401unauthorizedThe key is missing, malformed, expired, or revoked.
403forbiddenValid key, not allowed to do this.
403insufficient_scopeThe key lacks the scope this route needs.
403feature_not_availableThe space's tier doesn't include this.
404not_foundNo such resource in this key's space.
409conflictA state conflict. Bookings carry a booking_failure — see Bookings.
429rate_limitedSlow down — see Retry-After in Making Requests.
500internal_errorOurs. Retry with backoff, and quote the request_id if you reach out.

Validation errors

invalid_request carries a fields[] array describing exactly what failed:

{
"error": {
"type": "invalid_request",
"message": "The request did not validate",
"fields": [
{ "path": "customer.email", "message": "Not a valid email", "code": "invalid_email" }
]
}
}

path is dotted and matches the shape of the request body, so a form can bind errors directly without a separate mapping table.

not_found means "not in your space," too

A 404 doesn't distinguish "this id doesn't exist" from "this id exists, but not in the space your key is scoped to." That's deliberate — the two cases should be indistinguishable to a caller, the same way an unfamiliar visitor to a private page shouldn't learn anything from the difference between "not found" and "not yours."