Get started

Errors

Use HTTP status codes for control flow, and keep all write operations idempotent.

HTTP status patterns

  • 2xx: request accepted/succeeded.
  • 4xx: request invalid, unauthorized, or not allowed.
  • 5xx: transient server failure; retry with backoff.

Typical error body

Error bodies include machine-readable fields and a human-readable message. Log both.

{
  "error": {
    "code": "VALIDATION_FAILED",
    "message": "Validation failed",
    "type": "validation_error"
  }
}

Idempotency for writes

For supported create/side-effect endpoints such as payment intent and payout creation, send a stable Idempotency-Key per business action.

curl "$XPEND_BASE_URL/v1/payment-intents" \
  -H "Authorization: Bearer $XPEND_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: order_8421" \
  -d '{
    "amount": "150.00",
    "chain": "ethereum",
    "token": "USDC"
  }'

Retry strategy

Retry only transient failures and timeouts. Do not blind-retry malformed or unauthorized requests.

See /business/docs/idempotency for the exact routes that support API idempotency.

Payment intent codes

  • IDENTITY_BASED_CUSTOMER_ID_REQUIRED (400) — customer_id omitted while merchant deposit_identity_mode is IDENTITY_BASED.

See /business/docs/payment-intents for customer_id and Tron persistent deposit addresses.

Security-related codes

  • API_KEY_IP_NOT_ALLOWED (403) — API key used from an IP not on the key allowlist.
  • OTP_REQUIRED, OTP_INVALID, OTP_RATE_LIMITED — payout or email OTP verification.
  • OTP_SETUP_REQUIRED — payout attempted without authenticator enrollment.
  • MERCHANT_SCOPE_DENIED (403) — principal lacks required API scope.

See /business/docs/security for when each applies and how to recover.

Webhook-specific behavior

  • Returning non-2xx from your endpoint marks delivery as failed.
  • Xpend retries with backoff; handle duplicates safely.
  • Use webhook delivery listing endpoints for debugging failed attempts.