Error Codes
The API uses standard HTTP status codes and returns structured JSON error responses.
Error Response Format
All errors follow this structure:
{ "code": "not_found", "message": "Not Found", "request_id": "req_abc123"}| Field | Type | Description |
|---|---|---|
code | string | Machine-readable error code |
message | string | Human-readable description |
request_id | string | Unique request identifier for support |
Validation Errors
Validation errors (422) include a cause field with per-field details from schema validation:
{ "code": "validation_error", "message": "Validation error", "cause": { "items": { "0": { "gross_price": { "_errors": ["Invalid input: expected number, received string"] } }, "_errors": [] }, "_errors": [] }, "request_id": "req_abc123"}Each key in cause identifies the field path, while _errors contains the validation messages. The top-level code is the machine-readable error code; the validation message describes the expected format and, where available, the received type. Do not parse human-readable text as a stable field error code.
Error Codes Reference
| Status | Code | Description |
|---|---|---|
| 400 | bad_request | Malformed request syntax or invalid parameters |
| 401 | unauthorized | Missing or invalid API key |
| 403 | forbidden | Valid API key but insufficient permissions |
| 404 | not_found | Resource does not exist or is not accessible |
| 409 | conflict | Resource conflict (e.g., duplicate idempotency key with different payload) |
| 422 | validation_error | Request body fails schema validation |
| 429 | too_many_requests | Rate limit exceeded. Check Retry-After header |
| 500 | internal_server_error | Unexpected server error |
| 501 | not_implemented | Endpoint or feature not yet available |
| 502 | bad_gateway | Upstream service error |
| 503 | service_unavailable | Temporary outage. Check Retry-After header |
Handling Errors
try {
const invoice = await sdk.invoices.create({
items: [{ name: "Widget", quantity: 1, price: 9.99 }],
});
} catch(error) {
const apiError = error as Error & {
status?: number;
data?: { code?: string; message?: string; cause?: unknown; request_id?: string };
};
if (apiError.status === 422) {
console.log("Validation failed:", apiError.data?.cause);
} else if (apiError.status === 429) {
console.log("Rate limited; retry using your backoff policy");
} else if (apiError.status && apiError.status >= 500) {
console.log("Server error:", apiError.data?.message);
}
}Common Errors
| Scenario | Status | Fix |
|---|---|---|
Missing Authorization header | 401 | Add Authorization: Bearer sk_... header |
| Using sandbox key in production | 401 | Use the correct key for the environment |
| Creating invoice without items | 422 | Include at least one item in the items array |
| Accessing another entity’s data | 404 | Ensure the resource belongs to your entity |
| Sending too many requests | 429 | Implement exponential backoff; respect Retry-After |
| Database temporarily down | 503 | Retry after the Retry-After interval |