Error Codes
Standard error format for all failed responses:
{
"error": "human readable message",
"code": "machine_readable_code"
}
4xx — Client Errors
400 Bad Request
| Code | Description | Action |
|---|---|---|
invalid_cursor | Pagination cursor is invalid or expired | Start from the first page (no cursor) |
invalid_bank_code | bank_code is not in the reference list | Check the valid bank code with the Kesles team |
invalid_timestamp_format | X-Timestamp is not in unix seconds | Use an int64 unix timestamp |
missing_required_param | A required query param was not provided | Check the endpoint documentation |
401 Unauthorized
| Code | Description | Action |
|---|---|---|
invalid_signature | HMAC signature does not match | Re-check the string-to-sign and the secret |
timestamp_expired | X-Timestamp is more than ±300 seconds from server time | Sync your clock via NTP, regenerate the timestamp |
api_key_not_found | X-API-Key-ID is unknown | Contact the Kesles team |
api_key_revoked | Key has been revoked | Contact the Kesles team for a new key |
api_key_expired | Key has passed expires_at | Perform a key rotation |
403 Forbidden
| Code | Description | Action |
|---|---|---|
ip_not_allowed | Caller IP is not in the allowlist | Contact the Kesles team to update the IP allowlist |
tier_internal_required | Endpoint is not available to PSPs | Do not call this endpoint |
404 Not Found
| Code | Description | Action |
|---|---|---|
merchant_not_found | Merchant does not exist, is inactive, has no NMID, or belongs to another bank | Verify the NMID; merchant may not be active or may not belong to your bank |
429 Too Many Requests
| Code | Description | Action |
|---|---|---|
rate_limit_exceeded | Exceeded rate limit per API key | Wait for the Retry-After header (in seconds), then retry |
Headers included on 429:
Retry-After: 30
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1716453000
5xx — Server Errors
| HTTP | Code | Description | Action |
|---|---|---|---|
| 500 | internal_server_error | Unexpected error on the Kesles side | Retry with backoff; if persistent, contact the Kesles team with X-Request-ID |
| 502 | upstream_error | Internal Kesles dependency did not respond | Retry with backoff |
| 503 | service_unavailable | Maintenance or overload | Wait for Retry-After if present, then retry |
Retry Policy for 5xx
Implement exponential backoff for all 5xx errors:
- Retry immediately
- 1 second
- 5 seconds
- 30 seconds
- 2 minutes (stop after this, alert)
Do not retry 4xx (except 429 with Retry-After).
Tracing & Debugging
Always include X-Request-ID (uuid v4) on every request. When reporting an error to the Kesles team, include:
X-Request-IDfrom the failed request- Request timestamp
- HTTP status code and error
codereceived - Your bank code and API Key ID