Error codes
All API errors use a consistent envelope inspired by Stripe. Check type, code, and param for programmatic handling.
Response envelope
Success
json
{
"success": true,
"data": { }
}Error
json
{
"success": false,
"error": {
"type": "validation_error",
"message": "Human readable",
"code": "invalid_amount",
"param": "amount_minor",
"details": []
}
}HTTP status codes
200 OK · 201 Created · 204 No Content · 400 Bad Request · 401 Unauthorized · 403 Forbidden · 404 Not Found · 409 Conflict · 422 Unprocessable · 429 Rate Limited · 500 Server Error
Error reference
| Code | HTTP | Type | Meaning |
|---|---|---|---|
| unauthorized | 401 | authentication_error | Missing or invalid API key / session |
| forbidden | 403 | authorization_error | Valid auth but insufficient permission |
| merchant_not_verified | 403 | authorization_error | Complete verification before payment writes |
| project_not_found | 403 | authorization_error | Project id invalid or not owned |
| project_mismatch | 403 | authorization_error | URL project ≠ API key project |
| project_environment_mismatch | 400 | validation_error | tp_test_ key on LIVE project (or vice versa) |
| project_required | 400 | validation_error | Missing project context |
| resource_not_found | 404 | not_found_error | Order, webhook, or resource missing |
| resource_conflict | 409 | conflict_error | State conflict (e.g. order already paid) |
| invalid_json | 400 | validation_error | Request body is not valid JSON |
| invalid_request | 400 | validation_error | Schema validation failed |
| invalid_amount | 400 | validation_error | amountMinor not a positive integer |
| unprocessable | 422 | validation_error | Domain rule violation |
| idempotency_key_in_use | 409 | conflict_error | Same key, different request body in flight |
| rate_limit_exceeded | 429 | rate_limit_error | Too many requests |
| test_mode_required | 403 | authorization_error | Action only in TEST (e.g. simulate payment) |
| internal_error | 500 | api_error | Unexpected server error |
Idempotency
When a cached idempotent response is replayed, the response includes
Idempotent-Replayed: true. Rate limit responses include X-RateLimit-Remaining and X-RateLimit-Reset.