Error Reference

HTTP status codes, error response format, and per-endpoint error details.

Error Response Format

All error responses follow a consistent JSON structure:

{
  "detail": "Human-readable error message",
  "status_code": 400
}

The status_code field is always present in the response body, matching the HTTP status code. This is enforced by a custom exception handler.

Validation Error Format

Field-level validation errors return a nested object under detail:

{
  "detail": {
    "gateway_id": "gateway_id is required when campaign_id is not provided.",
    "amount": "amount is required when campaign_id is not provided.",
    "currency": "currency is required when campaign_id is not provided.",
    "billing_type": "billing_type is required when campaign_id is not provided."
  },
  "status_code": 400
}

HTTP Status Codes

Success Codes

Code Used By Description
200 OK Retrieve session, cancel session, submit payment, verify mandate, validate IBAN, reconciliation endpoints Successful operation.
201 Created Create session Session created successfully.

Client Error Codes

Code Exception Class Description
400 Bad Request ValidationError Missing or invalid fields. Includes per-field details.
401 Unauthorized AuthenticationFailed Invalid, revoked, or missing API key.
404 Not Found Session token not found.
409 Conflict ConflictError Resource state conflict (e.g., lead already has active session, session not in expected state).
410 Gone SessionExpiredError Session has expired or is in a terminal state.
429 Too Many Requests Throttled Rate limit exceeded. See Rate Limits.

Server Error Codes

Code Description
500 Internal Server Error Unexpected error during payment processing or mandate verification.

Per-Endpoint Errors

POST /api/v1/payment-sessions/

Code Condition
400 Missing required fields (direct mode without gateway_id, amount, currency, billing_type). Invalid campaign_id, offer, or gateway.
401 Invalid or revoked API key.
409 Lead already has an active payment session.
429 Rate limit exceeded (50/second per API key).

GET /api/v1/payment-sessions/{token}/

Code Condition
404 Session token not found in any tenant.
429 Rate limit exceeded (1/second per IP).

POST /api/v1/payment-sessions/{token}/cancel/

Code Condition
401 Invalid or revoked API key.
404 Session token not found.
409 Session is not in PENDING status.
410 Session has expired or completed.
429 Rate limit exceeded (50/second per API key).

POST /api/v1/payment-sessions/{token}/pay/

Code Condition
400 Missing iban or iban_holder_name. Invalid IBAN format.
404 Session token not found.
409 Session not in payable state (concurrent payment attempt).
410 Session expired or completed.
429 Rate limit exceeded (1/second per IP).
500 Unexpected gateway error.

POST /api/v1/payment-sessions/{token}/verify/

Code Condition
404 Session token not found.
409 Session not in AWAITING_VERIFICATION state.
410 Session expired or completed.
429 Rate limit exceeded (1/second per IP).
500 Unexpected verification error.

POST /api/v1/iban-validate/

Code Condition
200 IBAN provided but invalid. Returns {"valid": false, "error": "..."}.
400 Missing iban field. Returns {"valid": false, "error": "IBAN is required"}. Note: this response does not include the status_code field.
401 Authentication required (no API key or session token).
429 Rate limit exceeded (50/second per API key).

GET /api/v1/reconciliation/transactions/

Code Condition
400 Missing start_date. Invalid date format. Date range exceeds 90 days.
401 Invalid or revoked API key.
429 Rate limit exceeded (50/second per API key).

GET /api/v1/reconciliation/chargebacks/

Code Condition
400 Missing start_date. Invalid date format. Date range exceeds 90 days.
401 Invalid or revoked API key.
429 Rate limit exceeded (50/second per API key).

GET /api/v1/reconciliation/subscriptions/

Code Condition
400 Missing start_date. Invalid date format. Date range exceeds 90 days.
401 Invalid or revoked API key.
429 Rate limit exceeded (50/second per API key).

Custom Exception Classes

Class Code Default Detail
ConflictError 409 Conflict
SessionExpiredError 410 Session expired or completed

Payment Decline Codes (error_details.code)

Distinct from HTTP-level errors: a gateway-declined payment returns 200 OK with status: "declined" (retryable) or status: "failed" (terminal), carrying a normalized error_details.code alongside the raw gateway values. Branch on the normalized code rather than string-matching error_details.gateway_message.

Code Meaning
insufficient_funds Account has insufficient balance to cover the transaction.
invalid_iban IBAN is malformed, unknown, or rejected at submission.
mandate_rejected SEPA mandate missing, rejected, or unauthorized.
account_closed Account is closed or blocked at the bank.
do_not_honor Generic bank refusal without a specific reason code.
gateway_unavailable Upstream gateway timeout or service outage.
unknown No matching pattern — raw gateway message preserved in error_details.gateway_message.

The taxonomy is stable. New codes will only be added, never renamed. See Submit Payment for sample payloads.

Authentication Error Details

Scenario Response
No Authorization header {"detail": "Authentication credentials were not provided", "status_code": 401}
Invalid API key hash {"detail": "Invalid or revoked API key", "status_code": 401}
Invalid session token {"detail": "Invalid or expired session token", "status_code": 401}