Back off exponentially on 429 and 5xx responses. Treat 4xx errors other
than 429 as terminal — retrying an invalid_request will not succeed.
Errors
Error response format, status codes, rate limits, and idempotency.
CashSDK uses conventional HTTP status codes to signal success or failure. Codes
in the 2xx range mean success, 4xx codes indicate a problem with the request
(a missing parameter, a bad key, a conflict), and 5xx codes indicate a
server-side error.
Error body#
Every error response has the same shape: a top-level error object with a
machine-readable code and a human-readable message.
{
"error": {
"code": "not_found",
"message": "No app was found with id app_missing."
}
}
Branch on code, not on message — messages may change over time.
Status codes#
| HTTP | Error code | Meaning |
|---|---|---|
400 | invalid_request | The request was malformed or a parameter was invalid. |
401 | unauthorized | Missing, malformed, or revoked API key. |
403 | forbidden | The key is valid but not permitted for this resource. |
404 | not_found | The requested resource does not exist. |
409 | conflict | The request conflicts with existing state (e.g. duplicate ID). |
422 | unprocessable | The request was well-formed but failed validation. |
429 | rate_limited | Too many requests — slow down and retry. |
500 | internal_error | Something went wrong on our end. |
Rate limiting#
Requests are rate limited per API key. When you exceed the limit you receive
429 Rate limited with a Retry-After header indicating how many seconds to
wait before retrying.
{
"error": {
"code": "rate_limited",
"message": "Too many requests. Retry after 2 seconds."
}
}
Retries and idempotency#
Reads (GET) are always safe to retry. For webhook
deliveries, CashSDK retries failed attempts with backoff, and every delivery
carries a stable event id so your handler can deduplicate — process each id
at most once. See Events for the event shape.