Skip to main content
ShadhinPay Docs

Errors

The error response envelope, the full catalogue of error codes, and how they map to HTTP status codes.

When a request fails, ShadhinPay returns a consistent error envelope with a stable, machine-readable errorType. Branch on errorType in your code — never on the human-readable message, which may change.

Error envelope

{
  "status": "error",
  "errorType": "VALIDATION_ERROR",
  "message": "Invalid payment request",
  "data": {
    "amount": "Amount must be between 10.00 and 200000.00",
    "callbackUrl": "Invalid URL format"
  }
}

On validation errors, data maps each offending field to a message. For other errors data may be null or carry extra context (e.g. unlockAt for a locked account).

HTTP status mapping

HTTPWhenTypical errorType
400Malformed or invalid requestVALIDATION_ERROR, MISSING_REQUIRED_FIELD, INVALID_FORMAT, INVALID_AMOUNT
401Authentication failedAUTHENTICATION_ERROR, INVALID_API_KEY, SESSION_EXPIRED
403Authenticated but not allowedAUTHORIZATION_ERROR, MFA_REQUIRED
404Resource doesn't existRESOURCE_NOT_FOUND
409Conflict with current stateDUPLICATE_RESOURCE, INVALID_STATUS_TRANSITION, IDEMPOTENCY_CONFLICT
422Request valid but breaks a ruleBUSINESS_RULE_VIOLATION, REFUND_NOT_ALLOWED, PAYMENT_EXPIRED, VENDOR_UNAVAILABLE
423Account lockedACCOUNT_LOCKED
429Rate limit exceededRATE_LIMIT_EXCEEDED
500Server errorINTERNAL_SERVER_ERROR, DATABASE_ERROR
502Provider returned an errorVENDOR_ERROR, MFS_ADAPTER_FAILURE
503Provider/service unavailableEXTERNAL_SERVICE_ERROR, VENDOR_TIMEOUT

Error code catalogue

Authentication & authorization

errorTypeMeaning
AUTHENTICATION_ERRORCredentials couldn't be verified
AUTHORIZATION_ERRORNot permitted to perform this action
INVALID_API_KEYMissing, wrong, revoked, or mismatched API key
SESSION_EXPIREDSession/token no longer valid (dashboard)
MFA_REQUIREDA fresh two-factor check is required
OTP_INVALIDWrong one-time code
OTP_EXPIREDOne-time code expired
OTP_ATTEMPTS_EXCEEDEDToo many wrong codes for this reference
ACCOUNT_LOCKEDLocked after repeated failures; data.unlockAt shows when it lifts

Validation

errorTypeMeaning
VALIDATION_ERROROne or more fields failed validation
MISSING_REQUIRED_FIELDA required field was absent
INVALID_FORMATA field's format was wrong
INVALID_AMOUNTAmount out of range or otherwise invalid

Resources & lifecycle

errorTypeMeaning
RESOURCE_NOT_FOUNDThe referenced resource doesn't exist
DUPLICATE_RESOURCEA resource with this identity already exists
INVALID_STATUS_TRANSITIONThe action isn't valid for the resource's current state
BUSINESS_RULE_VIOLATIONThe request breaks a business rule
IDEMPOTENCY_CONFLICTIdempotency key reused with a different body — see Idempotency

Payments & providers

errorTypeMeaning
PAYMENT_EXPIREDThe payment's checkout window has lapsed
PAYMENT_ALREADY_COMPLETEDThe payment is already settled
REFUND_NOT_ALLOWEDThe payment can't be refunded (state or amount)
INSUFFICIENT_FUNDSNot enough funds for the operation
VENDOR_ERRORThe provider returned an error
VENDOR_TIMEOUTThe provider didn't respond in time
VENDOR_UNAVAILABLEThe provider is currently unavailable
MFS_ADAPTER_FAILUREThe provider integration failed
WEBHOOK_DELIVERY_FAILEDA webhook couldn't be delivered

Quota, balance & system

errorTypeMeaning
QUOTA_EXCEEDEDFree tier used up — informational; the payment still succeeds as billable
INSUFFICIENT_BALANCENot enough settled balance (e.g. for a payout)
RATE_LIMIT_EXCEEDEDToo many requests; honour Retry-After
INTERNAL_SERVER_ERRORUnexpected server error
DATABASE_ERRORStorage-layer error
EXTERNAL_SERVICE_ERRORA dependency was unavailable

Handling guidance

  • 4xx errors are about your request — fix the input; retrying unchanged won't help (except 429, which you should retry after Retry-After).
  • 5xx errors and VENDOR_TIMEOUT are transient — retry with backoff, reusing the same idempotency key so you don't double-charge.
  • New errorType values can be added over time. Treat unknown codes as a generic failure rather than crashing.

Next steps

On this page