Errors
Response shape
Every error response has the same minimal shape — both validation failures (400) and authorisation failures (401, 429). Internal errors (5xx) are never exposed with stack traces.
// Single-message variant
{ "statusCode": 401, "message": "Invalid credentials" }
// Validation variant (class-validator)
{
"statusCode": 400,
"message": [
"email must be an email",
"property foo should not exist"
]
}Status codes you can encounter
400 Bad Request— body validation failed. Inspect the returnedmessage[].401 Unauthorized— see Authentication. Always generic.402 Payment Required—{"error":"quota_exceeded", ...}from/v1/messageswhen the monthly quota is exhausted.404 Not Found— unknown endpoint, or/v1/messages/:idfor a non-existent message:{"statusCode":404,"message":"Message not found"}.410 Gone— full-account confirmation/agreement link expired, or registration was rejected.413 Payload Too Large— request body exceeds endpoint cap (64 KB on/v1/signup, 1 MB elsewhere). Returned by nginx as plain HTML, not the JSON shape above.429 Too Many Requests— rate limit hit; see Limits & Restrictions.
What we deliberately do NOT return
- Distinct error messages for missing vs invalid vs revoked bearer (anti-enumeration).
X-RateLimit-*headers (anti-calibration).- Stack traces or internal field names from validation libraries beyond the message string.
Server: nginx/<version>—server_tokens offon all public endpoints.