Routing
Candidate providers and rails are chosen per operation from your configuration and policy: cost, coverage, preference, limits.
Multi-Rail Orchestration Production
Connecting several providers and rails gives you options. It also gives you a new way to lose money: trying a second provider while the first one is still settling. Orangepill routes across providers and rails, and treats every additional attempt as a decision that depends on what the previous one did.
Problem
Teams add providers for coverage, cost and resilience. Then failover becomes a rule like "if Provider A errors, try Provider B". The rule is fine for a declined card. It is dangerous for a payout that Provider A accepted and then stopped answering about.
Principle
Failover is only safe when the previous execution state is known.
Routing answers "which provider should handle this?". The harder question is "can the last attempt still create an economic effect?". Orangepill answers the second before acting on the first. This is not smart routing; it is routing that is accountable to execution state.
How it works
Candidate providers and rails are chosen per operation from your configuration and policy: cost, coverage, preference, limits.
A provider is only a candidate if it supports the operation: the method, currency, destination and amount. Destination capabilities are checked before an attempt, not discovered from a failure.
Provider health informs which candidates are tried next. It does not rewrite the state of attempts already in flight.
Each try with a provider is a recorded attempt under the same economic intent. The runtime knows how many attempts exist and which could still complete.
Another provider is attempted only when the previous attempt is known to have failed or can no longer produce an effect. Otherwise the operation waits, or goes to Resolve.
Recovery depends on how final each attempt is. A rejected attempt can be rerouted. A pending one is observed. An unknown one is reconciled before anything else happens.
Pay-in vs payout
| Pay-in | Payout | |
|---|---|---|
| Who acts | The payer authorises; the provider collects. | Your platform instructs; the provider sends. |
| If an attempt is duplicated | The payer may be charged twice and need a refund. | Value leaves your platform twice and may not be recoverable. |
| Typical safe failover | Often possible after a clear decline, before the payer is charged. | Only after the previous attempt is known to be final and unsuccessful. |
| When the outcome is unknown | Confirm with the provider before asking the payer to try again. | Hold, reconcile, and resolve before sending again. |
Example
Provider A acknowledged the payout, then stopped responding. Provider B is healthy and eligible for the destination. A naive failover rule would send the payout to Provider B now.
Provider B is attempted only on the first branch. A timed-out payout should remain unresolved until there is enough evidence to show that another execution is safe.
Status: pay-in routing by product and priority runs in production. Automatic failover exists today for pay-in payment requests (such as Bre-B QR and key): a configuration or network error (including a timeout) moves to the next eligible provider, which is safe there because creating the QR or key collects nothing. A provider rejection or an unknown outcome stops. The payout failover shown in this example is in development.
Architecture
Providers and rails are connected behind one execution model. Your product expresses one economic intent; the attempts across processors, banks, wallets, stablecoin rails and local payment methods all belong to it.
Ledger effects follow the economic outcome, not the number of providers tried. Reconciliation compares the ledger with every provider involved, so a settlement on an unexpected rail surfaces as a divergence.
For developers
The v4 API is described by an OpenAPI contract. Start with the quickstart, then the parts that matter in production: errors, webhooks and the sandbox.
Walk us through how your stack decides to try another provider today, and we will show where execution state changes the answer.