# Rails

The rails Enruta executes on, what the mandate becomes on each, what each needs from you, and what a rail adapter must do.

Status: Live · Updated: 2026-09-14
Source: https://enruta.ai/docs/rails

Enruta connects to the accounts you already have with credentials your administrator scopes on the rail’s side. It never holds the funds, never sees a card number and, on crypto rails, never holds a key.

| Rail | Form | Status |
|---|---|---|
| Sandbox | Answers from Enruta’s database; capture on fulfillment or two minutes after authorization; refunds answered at once. `execution: self_asserted`. | Live; every organization’s first default |
| Stripe Issuing | Single-use virtual cards on the Stripe Issuing account you connect; real-time authorization answered against the mandate; refunds and authorization reversals driven through Stripe’s test helpers on sandbox keys, observed on live keys. `execution: customer_attested`. | Live; production default since 2026-09-10 |
| Mercury (`mercury`) | A card or payment limited to the mandate, with the mandate id in the note; transactions read back into the outcome. | Code complete; needs your Mercury account with API access |
| Ramp (`ramp`) | A virtual card with a total spend limit equal to the mandate and the mandate id in its name; the posted transaction matched back to the mandate. | Code complete; needs your Ramp account with API access |
| Bill.com (`billcom`) | A read-only evidence source (bills, approvals, payments), and approval of a single bill when a trusted session is configured; without one, the decision hands off to a person. | Code complete; needs your Bill.com account |
| Stripe Shared Payment Token (`stripe_spt`) | A token for the named seller whose usage limits (currency, maximum amount, expiry) come from the mandate. | Code complete; needs Stripe’s agent access on your Stripe account |
| Link (`link`) | A Link spend request for the mandate. | Code complete; needs Stripe’s agent access for Link |
| x402 (`x402`) | Pays an HTTP 402 resource with the `exact` scheme in USDC on Base or Base Sepolia; your own signer signs, and the payment response is sealed; the agent asks for it with `pay_http_resource`. `finality_class: irreversible`. | Live; runs with your own signer |
| MPP (`mpp`) | A session and a receipt per the public Machine Payments Protocol specification; the receipt is sealed. Resources are paid with `pay_http_resource`, and an open payment channel keeps paying its vouchers. | Live |

## Stripe Issuing

1. Your administrator creates a restricted key on your Stripe account with Issuing write and webhook read, and enters it in the console.
2. On `allow`, Enruta creates a single-use virtual card: amount equal to the mandate, the payee’s categories as allowed MCCs, expiry equal to the mandate’s, `cancel_after.payment_count = 1`.
3. Stripe sends `issuing_authorization.request` to Enruta; Enruta answers inside the two-second window by checking the authorization against the mandate and the card controls. The answer is recorded with the time it took (44 ms in production).
4. `issuing_transaction.created` of type `capture` moves the [settlement record](https://enruta.ai/docs/settlement) to `captured` and, since Issuing posts once, `settled`; type `refund` completes or creates a [reversal](https://enruta.ai/docs/reversal). `issuing_authorization.updated` with status `reversed` completes a void.

The card token or the network token is what reaches the payee; the card number is never returned to the agent and never stored by Enruta.

## x402

The x402 adapter pays a resource that answers HTTP 402. Enruta builds the EIP-3009 authorization for the `exact` scheme with the value, the recipient and the deadline (`validBefore`) taken from the mandate, and asks your signer to sign it: `signer_url`, called with a bearer secret you set. Enruta never holds the key. The resource’s `PAYMENT-RESPONSE` is sealed as the receipt. The payment cannot be reversed, so the policy’s lower cap for irreversible rails applies and a reversal can only be a credit. A policy can also require [collateral](https://enruta.ai/docs/identity-anchors) for x402 payments. The agent names the resource with `POST /v0/payment-requests/{id}/pay-resource` (MCP `pay_http_resource`, CLI `enruta pay-resource`): the URL on the payee’s domain, and the answer carries the resource’s status, headers, body and the receipt ([API](https://enruta.ai/docs/api)).

## Protocol checkouts

For UCP and AP2 checkouts, Enruta supplies the `ap2.checkout_mandate` proof the merchant requires and keeps the merchant’s consent object by digest. The merchant’s order webhook (`order_placed`, `order_updated`, `order_shipped`) fills the receipt, the adjustments and the fulfillment. For x402 and MPP, the adapters pay and seal the receipts while the money moves in the customer’s own wallet or account.

## When a rail cannot issue

A rail may be unable to carry a payment the policy allowed: Link above 500 USD, a read-only Bill.com connection, a payee Mercury has no recipient for, or a rail that fails while it issues. Then no mandate exists and the request moves to `handed_off`: `handoff` and the sealed `outcome` name the `rail`, its `reason`, its `message` and the `next_step` for a person, and `continue_url` is the rail’s own page when the rail named one, otherwise the payment’s page in the console. Nothing was paid, the budget reservation is released, and `payment_request.handed_off` is sent. The [API page](https://enruta.ai/docs/api) lists the reasons. Two apply to every rail: `rail_unavailable` (the rail answered 5xx, 408, 425 or 429, timed out, or could not be reached) and `rail_error` (any other failure, such as a 4xx refusal for bad credentials). A payment handed off for either does not count as a duplicate, so it can be requested again once the rail answers or the connection is fixed.

## What an adapter does

Each rail is a thin adapter with a fixed interface: `describe`, `issueCredential` (the mandate compiled into the rail’s control), `decide` (a pure function answering the rail’s authorization), `present`, `onMandateExpired`, and since this release `reverseAuthorization`, `refund`, `capture` and `settlementDefaults()` (`finality_class`, expected settlement days: Stripe Issuing reversible, 2; sandbox reversible, 0). The x402 and MPP adapters also have `payResource`. When `issueCredential` answers `unsupported`, or fails on the rail, the payment is handed to a person as above. Adapters, chosen per rail type through one registry, are the only rail-specific code; the policy engine and the record never change. One organization has one default rail; `Make default` in the console switches it.
