Error Handling
Saturday uses a consistent error format across all endpoints, modeled on Stripe’s error structure. Errors are predictable, machine-readable, and include enough context to diagnose the issue without consulting logs.Error format
Every error response follows this structure:| Field | Always present | Description |
|---|---|---|
type | Yes | Category of error |
code | Yes | Specific error code (machine-readable) |
message | Yes | Human-readable explanation |
param | No | The request parameter that caused the error |
documentation_url | Yes | Direct link to docs for this error |
request_id | Yes | Unique identifier for this request — include in support tickets |
Error types
| Type | HTTP Status | Description |
|---|---|---|
authentication_error | 401 | Invalid, expired, or missing API key |
authorization_error | 403 | Valid key but insufficient permissions |
invalid_request | 400 | Request is malformed or missing required fields |
resource_not_found | 404 | The requested resource doesn’t exist |
conflict | 409 | Request conflicts with current state |
rate_limit_exceeded | 429 | Too many requests |
safety_limit | 422 | Calculation would violate safety guardrails |
api_error | 500 | Something went wrong on Saturday’s end |
Retry logic
| Error type | Retry? | Strategy |
|---|---|---|
authentication_error | No | Fix credentials |
authorization_error | No | Fix permissions |
invalid_request | No | Fix the request |
resource_not_found | No | Fix the resource ID |
rate_limit_exceeded | Yes | Wait for Retry-After header |
safety_limit | No | Review and adjust parameters |
api_error | Yes | Exponential backoff |
Exponential backoff implementation
Request IDs
Every response includes arequest_id in both the response body and the X-Request-Id header. Always include this when reporting issues — it lets us trace the exact request through our systems.