All errors follow RFC 7807. Body is application/problem+json with fields type, title, status, detail, request_id and optionally reason or errors[].
{
"type": "https://www.kernelhost.com/en/reseller-api/errors/payment_required",
"title": "Payment required",
"status": 402,
"detail": "The order could not be paid.",
"request_id": "01HX7Z3K8Q...",
"reason": "insufficient_credit_and_no_card"
}
| HTTP | type | Meaning |
|---|---|---|
| 400 | validation_failed | Input validation failed. See errors[] for per-field detail. |
| 401 | auth_failed | Authentication failed. reason indicates why: missing_headers, bad_key, bad_timestamp, timestamp_out_of_window, bad_nonce, bad_signature, signature_mismatch, replay_detected, unknown_or_locked_key, ip_not_allowed. |
| 402 | payment_required | Payment required. reason see below. |
| 403 | forbidden_scope | Permission missing. reason: missing_scope. |
| 404 | not_found | Resource does not exist or is not visible to this key (prevents tenant enumeration). |
| 409 | idempotency_conflict | Idempotency-Key already used with a different body. |
| 429 | rate_limited | Rate limit exceeded. Honor the Retry-After header. |
| 500 | internal_error | Internal server error. Provide request_id for correlation with the audit log when contacting support. |
Payment-required reasons (HTTP 402)
When the order cannot be paid, the API returns HTTP 402 with a machine-readable reason in the JSON body.
insufficient_credit_and_no_card(Credit insufficient and no card on file. Solution: top up credit or add a card in the customer portal.)card_declined(Card was declined by the bank/gateway. Solution: try a different card or contact your bank.)card_expired(Card expired. Solution: add a new card in the customer portal.)client_not_found(Account id not found (should practically never happen, contact support).)

