Errors
Updated 9/17/2026Errors
LetterAPI uses standard HTTP status codes. Error responses are JSON.
Shape
Most errors:
json{ "error": "Human-readable message" }
Validation errors (Zod) return the flattened field errors instead of a plain string:
json{"error": {"formErrors": [],"fieldErrors": {"filePageCount": ["Expected number, received string"],"recipientAddress": ["Required"]}}}
When an order fails a check (credits, addresses, pricing) the response also carries an
errors list, one entry per problem, so you can fix them all at once. Address errors say which address (to or from) and which field:json{"error": "Enter a valid UK postcode, for example SW1A 1AA.","errors": [{ "code": "address_invalid", "address": "to", "field": "postcode", "message": "Enter a valid UK postcode, for example SW1A 1AA." }]}
Codes:
shop_unavailable, post_not_offered, pricing_unavailable, insufficient_credits, file_unavailable (the PDF at filePath is not publicly accessible, so the shop could not print it), address_invalid. Run POST /api/v1/orders/quote first to see them without creating anything.Insufficient-credit errors include the balances involved (see Creating orders):
json{ "error": "Insufficient credit balance", "balancePence": 50, "requiredPence": 186 }
Status codes
| Status | Meaning | Typical cause |
|---|---|---|
400 Bad Request | Malformed or invalid request body. | Missing required field, wrong type/enum value. |
401 Unauthorized | Not authenticated. | Missing, malformed, or revoked API key. |
402 Payment Required | Order blocked on funds. | Credit balance below the order's price. |
403 Forbidden | Authenticated, but not allowed. | Accessing another account's order/shop, or using a test key against a live-mode resource (and vice versa). |
404 Not Found | Resource doesn't exist. | Bad id, or an order/key that was deleted. |
413, 415, 422 | File upload rejected. | PDF over 25 MB, not actually a PDF, or corrupted/password-protected. |
409 Conflict | Valid request, wrong state. | Paying an order that isn't pending_payment; an invalid status transition. |
500 Internal Server Error | Something broke on our end. | Retry with backoff; contact support if persistent. |
Idempotency
Order creation is not currently idempotent — retrying a timed-out
POST /api/v1/orders request can create a duplicate order. Check GET /api/v1/orders for an existing matching order before retrying, or add client-side de-duplication (e.g. don't retry automatically on ambiguous network errors).LetterAPIPrint and post letters in the UK, from one letter to thousands.
© 2026 LetterAPI. All rights reserved.