Prompt

How do I set up a payment routing API for failover when an acquirer times out or declines?

Latest observation

Jul 17, 2026 · OpenAI APIWeb search: off

To set up a payment routing API with failover, design it so a payment attempt can be retried through alternate acquirers based on clear rules, while avoiding duplicate charges and respecting card/network constraints.

1) Define your routing policy

Create rules for when to fail over, for example:

  • Timeouts / no response from acquirer
  • Soft declines only, such as:
    • insufficient funds
    • do not honor
    • issuer unavailable
    • suspected fraud if your policy allows reroute
  • Do not retry on hard declines:
    • lost/stolen card
    • invalid card
    • expired card
    • suspected chargeback/fraud blocks
  • Stop retrying after a max number of attempts or total latency budget

A good pattern is:

  • Timeout → retry on a different acquirer
  • Soft decline → retry on another acquirer if allowed
  • Hard decline → stop

2) Maintain acquirer metadata

Store per-acquirer config in your routing service:

  • acquirer ID/name
  • supported countries/currencies
  • card brands supported
  • payment method support
  • priority score / cost
  • latency history / uptime
  • failover cooldown / circuit breaker status
  • credentials / endpoint / API version

This lets you choose the “best next” acquirer dynamically.

3) Use idempotency everywhere

This is critical.

For the client → your API

Require an idempotency key on payment create requests.

For your API → acquirer

Use:

  • a merchant reference / order ID
  • your own attempt ID
  • if the acquirer supports it, an idempotency key or equivalent

This prevents double captures if the original request actually succeeded but your timeout hid the success response.

4) Separate authorization from capture

If your flow allows it:

  1. Authorize
  2. If authorization succeeds, capture later

This reduces risk during failover.
For some businesses, you may need auth-and-capture immediately, but then retries must be extra careful.

5) Build a routing engine

Your API can look like:

  • POST /payments/authorize
  • POST /payments/capture
  • POST /payments/refund
  • GET /payments/{payment_id}

Inside authorize:

  1. Validate request
  2. Create payment record with status pending
  3. Select acquirer using routing rules
  4. Send auth request
  5. If timeout or retryable decline:
    • mark attempt failed
    • pick next eligible acquirer
    • retry
  6. If success:
    • mark payment authorized
  7. Return final result

6) Implement a circuit breaker per acquirer

If an acquirer starts timing out or failing a lot, stop sending traffic to it temporarily.

Typical states:

  • Closed: normal
  • Open: temporarily disabled
  • Half-open: test a few requests before restoring

This prevents repeated failures and improves latency.

7) Set retry limits and budgets

Avoid endless failover.

Example:

  • max 2–3 acquirer attempts per payment
  • max total processing time: 2–5 seconds for synchronous APIs
  • only retry on explicitly retryable errors

If the budget is exhausted:

  • return pending_review, failed, or try_again_later
  • optionally continue async reconciliation

8) Reconcile ambiguous outcomes

The hardest case is:

  • you timeout
  • but the acquirer may have actually approved it

To handle this:

  • after timeout, query the acquirer transaction status
  • if status is unknown, pause before failing over or fail over only if your risk model accepts duplicate exposure
  • run post-transaction reconciliation jobs
  • use settlement reports / webhooks to detect late approvals

A common safe pattern:

  • timeout → check status endpoint
  • if unknown after a short wait → either retry with another acquirer or mark as pending until reconciled

9) Standardize error classification

Map acquirer-specific responses into your own categories:

  • SUCCESS
  • RETRYABLE_TIMEOUT
  • RETRYABLE_SOFT_DECLINE
  • NON_RETRYABLE_HARD_DECLINE
  • UNKNOWN
  • SYSTEM_ERROR

This abstraction makes routing logic consistent across acquirers.

10) Track attempts and audit trail

Persist every attempt:

  • payment ID
  • attempt ID
  • acquirer used
  • request/response timestamps
  • normalized error code
  • raw response reference
  • outcome
  • latency

This helps with:

  • debugging
  • compliance
  • chargeback disputes
  • optimization of routing rules

11) Expose clear API responses

Example response on success:

{
  "payment_id": "pay_123",
  "status": "authorized",
  "acquirer": "acq_a",
  "attempts": [
    {
      "acquirer": "acq_a",
      "status": "timeout"
    },
    {
      "acquirer": "acq_b",
      "status": "authorized"
    }
  ]
}

Example on final failure:

{
  "payment_id": "pay_123",
  "status": "failed",
  "reason": "hard_decline",
  "decline_code": "card_stolen"
}

12) Add observability

Monitor:

  • success rate per acquirer
  • timeout rate
  • retry rate
  • duplicate/ambiguous auth rate
  • approval rate by BIN, country, brand
  • p95/p99 latency
  • circuit breaker events

Use this data to improve routing decisions.

13) Security and compliance

Make sure you:

  • never store raw PAN unless PCI-compliant
  • tokenize cards
  • encrypt sensitive data
  • log carefully to avoid leaking card data
  • follow PCI DSS and regional regulations
  • handle 3DS / SCA flows correctly where required

14) Recommended failover strategy

A practical starting strategy:

  1. Route to preferred acquirer based on region/brand/cost
  2. If timeout:
    • query status if available
    • if still unresolved, try next acquirer only if duplicate risk is acceptable
  3. If soft decline:
    • retry on alternate acquirer
  4. If hard decline:
    • stop
  5. Use circuit breakers and health checks to disable unhealthy acquirers automatically

15) Simple pseudo-flow

receive payment request
validate + create idempotent payment
for each eligible acquirer:
    if circuit breaker open: skip
    send authorization
    if success: return success
    if hard decline: return failure
    if timeout/soft decline: continue
return failed after exhausting routes

If you want, I can also provide:

  1. a sample API design,
  2. a database schema, or
  3. reference code in Node.js / Python / Java for payment failover routing.

Observation history

Unlock observation history

Create a free Obsurfable account to unlock historical responses, model comparisons, and deeper brand intelligence.

How did Obsurfable measure this prompt?

Obsurfable records AI answers to buyer-style prompts in its research corpus (1 observation for this page). Metrics are distributions over observations, not a single static ranking.

Which AI systems does Obsurfable collect answers from?

OpenAI, ChatGPT, Google, Gemini, Google AI Mode, Anthropic, Claude, Perplexity, Grok, DeepSeek, Mistral, Copilot, and Meta AI.