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
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_status_updated 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_status_updated events — the payload includes the full payment object with error details.
  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 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.