Error Handling

Every error, on every endpoint, has the same shape:

{
  "success": false,
  "error": {
    "code": "INVALID_CALLBACK_URL",
    "message": "The callback URL is not registered for this application.",
    "details": { "callback_url": ["…"] }
  }
}

Successful responses always have "success": true and a data object.

Error codes

Code HTTP Retry? Meaning
UNAUTHENTICATED 401 no Authorization header missing
INVALID_TOKEN 401 no Token unknown, revoked or expired
APPLICATION_DISABLED 403 no Application disabled by an admin
FORBIDDEN 403 no Not allowed (e.g. admin IP allowlist)
RATE_LIMITED 429 after details.retry_after Request budget exceeded
VALIDATION_ERROR 422 no Generic validation failure; see details
INVALID_AMOUNT 422 no Amount not an integer within limits
INVALID_CURRENCY 422 no Unsupported currency
INVALID_CALLBACK_URL 422 no Not registered, or not https
INVALID_IDEMPOTENCY_KEY 422 no Malformed header
IDEMPOTENCY_CONFLICT 409 no Key reused with a different body
PAYMENT_NOT_FOUND 404 no Unknown or other application's payment
PAYMENT_ALREADY_PAID 409 no Operation not applicable to a paid payment
PAYMENT_EXPIRED 409 no Payment expired
PAYMENT_NOT_VERIFIABLE 409 shortly Never registered at a gateway, or verification in progress
INVALID_STATUS_TRANSITION 409 no Internal state guard
GATEWAY_NOT_CONFIGURED 502 no Application has no usable gateway (admin action needed)
GATEWAY_DISABLED 502 no Configured gateway is disabled
GATEWAY_ERROR 502 no Gateway rejected the operation
GATEWAY_UNAVAILABLE 503 yes Gateway unreachable / 5xx — retry with the same idempotency key
VERIFICATION_FAILED 502 no Gateway refused verification
UNSUPPORTED_OPERATION 422 no Gateway lacks the feature
NOT_FOUND 404 no Unknown route/resource
METHOD_NOT_ALLOWED 405 no Wrong HTTP method
INTERNAL_ERROR 500 later Unexpected failure on Cartino Pay; it is logged with a trace

Handling strategy

$response = Http::withToken($token)->post("$base/api/v1/payments", $payload);
$json = $response->json();

if ($json['success'] ?? false) {
    return $json['data'];
}

match ($json['error']['code'] ?? 'INTERNAL_ERROR') {
    'GATEWAY_UNAVAILABLE', 'RATE_LIMITED' => retryLater(),
    'INVALID_CALLBACK_URL', 'GATEWAY_NOT_CONFIGURED' => alertOps(),   // configuration problem
    'IDEMPOTENCY_CONFLICT' => useNewKey(),
    default => showGenericPaymentError(),
};

Gateway-specific error messages are recorded in Cartino Pay's per-payment trace for admins; only a normalised message reaches your application.