Errors
When Kashu cannot carry out a request, it answers with an HTTP status of 400 or more and one error object. Every error the API can return is in the table at the end of this page, and every error's doc_url links to its row.
{
"error": {
"type": "invalid_request_error",
"code": "parameter_invalid",
"message": "A parameter has an invalid value.",
"param": "amount",
"request_id": "req_...",
"doc_url": "https://docs.kashupay.com/api/errors#parameter_invalid"
}
}
Read the error
codesays what went wrong. Branch oncode: it stays the same for a given error.messageexplains the error to a person. Its wording may change, so do not match on it.typegroups codes: a bad request, a key problem, a permission, idempotency, a rate limit, or a problem on Kashu's side.paramnames the parameter at fault, when there is one. A nested parameter is written in brackets, such asaddress[country].request_idnames the request. Include it when you write to help@kashupay.com about a request.doc_urllinks to the code's row on this page.
Every response carries the same id in its Request-Id header, errors included.
A declined card is not an error
When a card is declined, the payment is still made, with status failed, and the request answers 201. The payment's failure_code and decline_code say why. Payments explains what to do next.
Decide whether to retry
- A 500
api_error: retry with the sameIdempotency-Key. - A 409: wait a moment, then retry with the same key.
- A 429
rate_limited: wait the number of seconds inRetry-After, then retry. - Any other error: sending the same request again gets the same answer. Fix the request first.
Stay under the rate limits
Writes are limited for each account and mode, a minute at a time:
| Requests | A minute, per account and mode |
|---|---|
Writes that move money (an Idempotency-Key is required) | 60 |
| Other writes | 30 |
Every write answers with a RateLimit-Policy header that names its limit. A request over the limit answers 429 rate_limited, with Retry-After in seconds and a RateLimit header. Reads are limited too, and answer the same way.
Every error code
| Code | Status | Type | Message |
|---|---|---|---|
api_key_missing | 401 | authentication_error | No API key was provided. Send it as a Bearer token in the Authorization header. |
api_key_invalid | 401 | authentication_error | The API key provided is not valid. |
api_key_expired | 401 | authentication_error | The API key provided has been revoked or has expired. |
livemode_unavailable | 403 | permission_error | Live mode is not available yet. Use a test key. |
insufficient_scope | 403 | permission_error | The API key does not have the access this request needs. |
publishable_key_not_allowed | 403 | permission_error | A publishable key cannot make this request. Use a secret or restricted key. |
route_not_found | 404 | invalid_request_error | There is no endpoint at this path. |
method_not_allowed | 405 | invalid_request_error | This endpoint does not accept that HTTP method. |
resource_missing | 404 | invalid_request_error | No such object. |
invalid_json | 400 | invalid_request_error | The request body must be a JSON object. |
parameter_missing | 400 | invalid_request_error | A required parameter is missing. |
parameter_invalid | 400 | invalid_request_error | A parameter has an invalid value. |
parameter_unknown | 400 | invalid_request_error | The request has a parameter this endpoint does not accept. |
cursor_invalid | 400 | invalid_request_error | The cursor is not valid for this list. Pass back next_cursor unchanged, with the same filters and limit. |
cursor_expired | 400 | invalid_request_error | The cursor has expired. Start the list again. |
api_version_invalid | 400 | invalid_request_error | The Kashu-Version header names no known API version. |
idempotency_key_missing | 400 | idempotency_error | This endpoint moves money, so it needs an Idempotency-Key header. |
idempotency_key_invalid | 400 | idempotency_error | The Idempotency-Key header must be 1 to 255 printable ASCII characters. |
idempotency_key_reused | 400 | idempotency_error | This Idempotency-Key was already used with a different endpoint or different parameters. |
idempotency_key_in_use | 409 | idempotency_error | A request with this Idempotency-Key is still running. Retry once it has finished. |
payment_unexpected_state | 400 | invalid_request_error | The payment's status does not allow this request. |
amount_too_large | 400 | invalid_request_error | The amount is more than the payment has left to capture or refund. |
operation_in_progress | 409 | invalid_request_error | Another request is changing this object. Retry once it has finished. |
payments_not_enabled | 403 | permission_error | This account cannot take payments yet. |
subscription_unexpected_state | 400 | invalid_request_error | The subscription's status does not allow this request. |
feature_unavailable | 403 | permission_error | This feature is not available for this account yet. |
token_already_used | 400 | invalid_request_error | This card token has already been used. Collect the card again for a new token. |
token_expired | 400 | invalid_request_error | This card token has expired. Collect the card again for a new token. |
checkout_session_unexpected_state | 400 | invalid_request_error | The checkout session's status does not allow this request: it is complete, expired, or its payment is still processing. |
webhook_endpoint_limit | 400 | invalid_request_error | This mode already has the most webhook endpoints it may have. Delete one first. |
rate_limited | 429 | rate_limit_error | Too many requests. Retry after the time in the Retry-After header. |
api_error | 500 | api_error | Something went wrong on Kashu's side. Retry with the same Idempotency-Key. |