Errors & rate limits
Error envelope
{
"success": false,
"error": {
"code": "VALIDATION_FAILED",
"message": "human-readable explanation",
"rowErrors": [ { "index": 3, "sourceLoanNumber": "LN-…", "field": "borrower.phone", "reason": "invalid_mobile" } ]
}
}
Every response carries an X-Request-Id header — include it in support
queries and we can trace the exact request.
Codes
| HTTP | Code | Cause | Your action |
|---|---|---|---|
| 401 | UNAUTHORIZED | Unknown/revoked key, wrong environment, missing headers, IP not allowed | Check key + environment; see environments |
| 401 | SIGNATURE_INVALID | Signature mismatch | Debug it |
| 401 | TIMESTAMP_SKEW | Timestamp outside ±5 min | Sync clocks (NTP); sign at send time |
| 403 | SANDBOX_ONLY | Sandbox-only endpoint with a live key | Use test credentials |
| 403 | PAYMENT_MODE_MISMATCH | payments/confirm while not on Mode B | Confirm your configured payment mode |
| 404 | CASE_NOT_FOUND | Unknown loan for your org | Check sourceLoanNumber; was it pushed/committed? |
| 409 | DUPLICATE_CONFIRMATION | Payment reference already booked | Treat as success — the original booking is returned |
| 413 | TOO_MANY_ROWS | Batch above the row cap (default 1,000) | Split the batch |
| 422 | VALIDATION_FAILED | Envelope or per-row validation failure | Fix rows in rowErrors; others were unaffected |
| 429 | RATE_LIMITED | Per-org limits exceeded | Honour Retry-After |
| 429 | AUTH_LOCKED | Signature-failure lockout (15 min) | Stop, debug the signature, wait |
Rate limits (per organisation, adjustable)
| Limit | Default |
|---|---|
| Requests | 60 / minute |
| Case batches | 10 / hour |
| Batch size | 1,000 rows |
| Payload | 5 MB |