Error Handling
Response Format
All errors return a JSON body with a detail field:
json
{
"detail": "Human-readable error message"
}For validation errors (422), the body contains field-level errors:
json
{
"detail": [
{
"type": "value_error",
"loc": ["body", "txn_currency"],
"msg": "Currency code must be exactly 3 letters (ISO 4217)",
"input": "EURO"
}
]
}Error Codes
| HTTP | Meaning | Action |
|---|---|---|
| 400 | Invalid request (e.g. unknown BIN) | Fix the request data |
| 401 | Authentication failure | Check token — regenerate if expired |
| 422 | Validation error (missing/invalid field) | Fix the field value — see Enum Reference |
| 429 | Rate limit exceeded | Retry after Retry-After header value |
| 500 | Internal error | Retry with backoff |
| 503 | Service unavailable | Retry after Retry-After header value |
Retry Strategy
| Condition | Action |
|---|---|
400, 401, 422 | Do not retry — fix the request |
429 | Retry after Retry-After header |
500 | Retry up to 3 times: 100ms → 200ms → 500ms + jitter |
503 | Retry after Retry-After header |
| Network timeout | Retry once after 200ms, then stop |
Add random jitter (±50ms) to each delay to prevent thundering herd at high volume.
Idempotency
Sending the same txn_id multiple times is safe. The analytics pipeline uses UPSERT semantics — duplicate requests update the existing record rather than creating duplicates.
Rate Limits
Rate limits are enforced per API key at the entity level.
| Plan | Requests / second | Requests / minute |
|---|---|---|
| Starter | 10 | 500 |
| Pro | 100 | 5,000 |
| Scale | Custom | Custom |
Every response includes rate limit headers:
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 847
X-RateLimit-Reset: 1714003260Health Check
GET https://api.recivr.com/healthNo authentication required. Returns:
json
{
"status": "ok",
"service": "rts"
}Recommended polling interval: 30 seconds.
For system-wide status, subscribe to notifications at status.recivr.com.
