Error response shape
All API errors return a consistent JSON structure:
"type": "invalid_request_error",
"code": "validation_failed",
"message": "amount must be at least 200 cents",
"message": "must be greater than or equal to 200"
| Field | Description |
|---|
type | Error category (see below) |
code | Machine-readable code |
message | Human-readable description |
details | Array of field-level errors (validation errors only) |
HTTP status codes
| Status | Meaning |
|---|
400 | Validation error or malformed request |
401 | Missing or invalid authentication credentials |
403 | Authenticated but not permitted for this operation |
404 | Resource not found |
409 | Conflict (e.g. idempotency key reused with different params) |
500 | Internal server error |
Error types
| Type | Description |
|---|
invalid_request_error | Request is malformed or fails validation |
authentication_error | API key is missing, invalid, revoked, or expired |
permission_error | Key doesn’t have permission for this operation |
api_error | Internal server error — retry with exponential backoff |
Error code reference
| Code | HTTP | Description |
|---|
invalid_api_key_format | 401 | Key does not match expected format |
permission_denied | 403 | Key is valid but not permitted for this resource |
payment_intent_not_found | 404 | No payment intent with that ID exists |
invalid_payment_method_type | 400 | Unsupported type value in payment method create |
refund_amount_exceeds_available | 400 | Sum of refunds would exceed original payment amount |
payment_intent_not_refundable | 400 | Payment intent is not in succeeded status |
refund_failed | 400 | PSP rejected the refund |
validation_failed | 400 | One or more fields failed validation — check details |
Test helper errors
Sandbox-only endpoints (/api/v1/test_helpers/...) add these codes:
| Status | Code | Meaning |
|---|
403 | sandbox_only | The request used a live key — test helpers work only in sandbox mode |
404 | test_clock_not_found | No test clock with that ID on this account |
422 | — | Clock limits exceeded, invalid frozen_time, or an advance beyond the allowed bound (the message states the maximum) |