Error Handling

API Errors

All Inflow API errors return a consistent JSON structure:

{
  "statusCode": 400,
  "message": "Validation failed",
  "error": "Bad Request"
}

HTTP Status Codes

CodeMeaningWhat to Do
400Bad RequestCheck your request body for missing or invalid fields
401UnauthorizedVerify your API key is correct and included in the X-Inflow-Api-Key header
404Not FoundThe resource (payment, subscription, link) doesn't exist
429Too Many RequestsYou hit a rate limit. Back off and retry
500Internal Server ErrorRetry the request. If persistent, contact support

Validation Errors

When request validation fails, the message field contains an array of error descriptions:

{
  "statusCode": 400,
  "message": [
    "currency must be one of the following values: EUR, USD",
    "products should not be empty",
    "customerEmail must be an email"
  ],
  "error": "Bad Request"
}

Payment Error Codes

When a payment fails (e.g., card declined), the error details are available in the payment object's lastDepositAttempt.error field.

Where to Find Payment Errors

ChannelHow to Access
APIGET /api/payment/{id}lastDepositAttempt.error field
DashboardPayment details page shows the error code and description
WebhooksThe payment.failed event payload includes the full payment object with error info
SDKonComplete callback → result.error.message (customer-friendly message)

Last Deposit Attempt Object

{
  "lastDepositAttempt": {
    "status": "failed",
    "amount": 4999,
    "paymentMethod": "CARD",
    "error": "card_declined",
    "attemptedAt": "2025-01-15T10:30:00.000Z"
  }
}

Common Payment Error Codes

Error CodeDescriptionCustomer Can Retry?
card_declinedCard was declined by the issuing bankYes
insufficient_fundsNot enough funds on the cardYes
expired_cardCard has expiredNo
incorrect_cvcWrong CVC/CVV code enteredYes
incorrect_numberInvalid card numberYes
invalid_cvcCVC format is invalidYes
invalid_expiry_monthInvalid expiration monthYes
invalid_expiry_yearInvalid expiration yearYes
invalid_numberCard number format is invalidYes
processing_errorTemporary processing issueYes
generic_declineDeclined without specific reasonYes
do_not_honorBank refused the transactionDepends
lost_cardCard reported as lostNo
stolen_cardCard reported as stolenNo
restricted_cardCard has restrictionsNo
authentication_required3DS authentication neededYes
withdrawal_count_limit_exceededTransaction limit reachedLater

SDK Error Handling (Customer-Facing)

The SDK's onComplete callback provides customer-friendly error messages:

onComplete: (result) => {
  if (result.error) {
    // result.error.message — Safe to display to the customer
    // result.error.retryable — Whether the customer can try again
    showError(result.error.message);
  }
}

These errors are designed for the end customer's checkout experience — they use clear, non-technical language.

Merchant Error Monitoring (API & Webhooks)

For merchant-side monitoring, use:

  1. API polling: Query GET /api/payment/{id} and check lastDepositAttempt.error.
  2. Webhooks: Listen for payment.failed events — the payload includes the full payment object with error details (see event types).
  3. Dashboard: The Payments page shows error codes for failed transactions.

Best Practices

  • Always check the HTTP status code before parsing the response body.
  • Handle 401 errors by verifying your API key configuration.
  • For 429 errors, back off and retry — see Rate Limits.
  • For 500 errors, implement retry logic with exponential backoff.
  • Monitor payment failures via webhooks rather than polling the API.
  • Display SDK errors (result.error.message) directly to customers — they are already user-friendly.
  • Log the raw error code (lastDepositAttempt.error) for your internal monitoring.

Did this page help you?