> ## Documentation Index
> Fetch the complete documentation index at: https://nevermined.ai/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# How the Router works

> The payment flow end to end, the two call modes, and where custody actually sits.

Every Router payment follows the same five beats, whatever protocol the merchant speaks:

<Steps>
  <Step title="Probe">
    Someone requests the paid resource without payment. The merchant answers **HTTP 402** with a payment challenge.
  </Step>

  <Step title="Detect">
    The Router reads the challenge and works out which protocol it is — an `accepts` array means x402, a `WWW-Authenticate: Payment` header means MPP.
  </Step>

  <Step title="Mint">
    The Router checks the spend against your Delegation, checks your wallet actually holds the funds, signs the payment from your custodial wallet, and reserves the amount — plus any [routing fee](#the-routing-fee) — against the cap.
  </Step>

  <Step title="Pay">
    The credential goes to the merchant as an HTTP header. The merchant verifies it, settles, and returns the resource.
  </Step>

  <Step title="Record">
    The payment lands on your [ledger](/docs/products/catalog/router/ledger) with its settlement reference.
  </Step>
</Steps>

The only thing that changes between call modes is **who performs steps 1 and 4** — you, or the Router.

## Mode B — the Router calls the merchant (recommended)

You hand the Router the request you want made. It probes, detects, mints, attaches, calls, and relays the answer. One call in, one answer out; you never see the 402 and never touch a credential.

```http theme={null}
POST /api/v1/router/route
Authorization: Bearer <your-api-key>
Content-Type: application/json

{
  "delegationId": "5e7481c3-e972-45bd-bdc5-a0b99c4de4a1",
  "url": "https://service.example/api/resource",
  "method": "GET",
  "requestId": "order-1234"
}
```

```json theme={null}
{
  "status": 200,
  "body": { "…": "the paid resource" },
  "paid": true,
  "payment": {
    "paymentId": "b1f9c2e4-…",
    "settlement": {
      "recipient": "0x209693Bc6afc0C5328bA36FaF03C514EF312287C",
      "amount": "1000",
      "asset": "USDC",
      "network": "base-sepolia",
      "approxCents": "1",
      "scheme": "exact"
    },
    "fee": {
      "bps": 0,
      "amount": "0",
      "cents": "0",
      "capChargedCents": "1"
    },
    "txHash": "0xfc8af37b…",
    "status": "Settled"
  }
}
```

`status` and `body` are the merchant's, relayed unchanged. `paid: false` means the resource was free — the Router relayed it and there is no `payment` block.

<Note>
  **`requestId` is required in mode B.** Because the Router pays automatically, a retry after a dropped connection must not buy the same thing twice. At most one payment is minted per `(caller, requestId)`; a duplicate returns **409** carrying the original `paymentId` instead of paying again. Use one stable id per logical purchase, not per HTTP attempt.
</Note>

### Streaming variant

For large or streamed responses, use `ALL /api/v1/router/proxy` instead. It's the same engine, driven by headers rather than a JSON envelope, and the merchant's response body streams straight back to you:

| Header                            | Purpose                                                 |
| --------------------------------- | ------------------------------------------------------- |
| `X-Router-Target-Url`             | Absolute upstream URL to route to. Required.            |
| `X-Router-Delegation-Id`          | The Delegation to spend against. Required.              |
| `X-Router-Request-Id`             | Idempotency key. Required.                              |
| `X-Router-Upstream-Authorization` | Optional — the merchant's own auth, forwarded upstream. |

Your method, body and headers pass through. Payment metadata comes back on the response:
`X-Router-Payment-Id`, `X-Router-Payment-Status` (`Issued` / `Settled` / `Failed`), and `X-Router-Tx-Hash`.

Use `/route` when you want one structured result; use `/proxy` when you want the bytes.

## Mode A — you call the merchant yourself

Use mode A when your agent needs to make the upstream call itself — a client you don't control, a transport the Router doesn't proxy, or a request you want to shape by hand.

<Steps>
  <Step title="Probe the merchant yourself">
    Request the resource, get the 402, and keep the challenge exactly as it arrived — the `accepts` object for x402, or the raw `WWW-Authenticate: Payment …` header value for MPP.
  </Step>

  <Step title="Ask the Router for a credential">
    ```http theme={null}
    POST /api/v1/router/payments
    Authorization: Bearer <your-api-key>
    Content-Type: application/json

    {
      "delegationId": "5e7481c3-…",
      "protocol": "x402",
      "resourceUrl": "https://service.example/api/resource",
      "requestId": "order-1234",
      "target": { "x402Version": 2, "accepts": [ … ] }
    }
    ```

    You get back a `credential` — `{ transport, name, value }` — plus a `settlement` descriptor, a [`fee`](#the-routing-fee) object, and a `paymentId`. The record is created `Issued`.
  </Step>

  <Step title="Attach it and re-request">
    Set the HTTP header named by `credential.name` to `credential.value`, and send your original request again. The merchant verifies, settles, and returns the resource.
  </Step>

  <Step title="Close the record">
    Report the settlement so the ledger entry completes:

    ```http theme={null}
    POST /api/v1/router/payments/{paymentId}/settled
    ```

    Skip this and the record stays `Issued` — a valid state meaning "paid, settlement not yet observed", not an error.
  </Step>
</Steps>

In mode A the Router only *signs*. It is not in the request path, so it cannot observe whether you ever redeemed the credential — which is why the ledger needs you to close the loop.

<Tip>
  Prefer mode B unless you have a specific reason not to. It self-settles the ledger record, it's one round trip instead of three, and it removes an entire class of "I minted a credential and forgot to use it" bugs.
</Tip>

## Where custody sits

This is the part worth understanding properly, because it explains an error you will eventually hit.

Both rails are **pull-based**. The credential the Router signs authorizes the *merchant* to take a specific amount from **your own custodial wallet**. Nevermined never holds your funds, never fronts them, and never moves them between users.

Two independent things therefore have to be true for a payment to succeed:

1. **The Delegation authorizes the spend** — enough cap remains and it hasn't expired. Otherwise: `402 BCK.ROUTER.0003`.
2. **The wallet actually holds the money** — on the specific network and in the specific asset the merchant demanded.

A cap is permission, not funds. You can hold a \$50 Delegation and still fail to buy something for a penny if your wallet is empty on that chain.

**What happens when you're short differs by rail** — and one `402 BCK.ROUTER.0009` covers two quite different things:

| Rail           | Before signing                        | When you're short                                                                                                                                       |
| -------------- | ------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **MPP-tempo**  | Reads your on-chain balance           | `402 BCK.ROUTER.0009`. Nothing minted, no budget reserved.                                                                                              |
| **MPP-stripe** | Reads nothing — the card is attempted | A decline comes back as the same `402 BCK.ROUTER.0009`. Nothing minted and no budget reserved, but it's a real decline on your card, not a local check. |
| **x402**       | No balance check at all               | Nothing stops you. The credential is signed and your budget reserved; the shortfall appears on-chain afterwards.                                        |

<Warning>
  **On x402 an underfunded wallet costs you budget.** With no pre-check the Router signs and reserves your cap, the merchant's transfer then fails on-chain, and the reserved **merchant leg** is **not** given back. Only a routing fee reserved on top can come back, and only on [the closed list of paths that release one](#when-a-fee-is-not-collected). Fund before you call; don't rely on being stopped.
</Warning>

## The routing fee

Nevermined charges a **routing fee** on each payment the Router makes for you. It's quoted in **basis points** over the amount you're paying the merchant — 100 basis points is 1% — and it's disclosed on the payment response, alongside what the merchant charged.

<Note>
  **The routing fee is 5%** — `500` basis points — of the amount you pay the merchant. It is added on top, so a $1.00 call debits your Delegation cap $1.05 and the merchant still receives \$1.00.

  The rate is resolved per payment and returned as `fee.bps` on every response, so read it from there rather than hard-coding it.
</Note>

Three things are worth knowing about how a fee is applied.

**It's a separate movement, not a bigger one.** The credential the Router signs authorizes the merchant's exact amount and nothing more — a fee never rides the merchant's authorization, and a merchant is never paid more than it asked for. The fee is charged as its own movement.

**It's reserved against your Delegation cap together with the merchant amount**, as a single combined charge. So your cap headroom drains by merchant + fee, which is why the merchant amounts on your ledger won't add up to the budget you've spent unless you count the fee too. `fee.capChargedCents` is the figure your cap was actually debited.

**The atomic fee rounds down; the cap charge rounds up.** These are two different numbers, rounded in opposite directions, and conflating them will understate what a payment costs you:

* `fee.amount` — the fee in the asset's smallest unit — is rounded **down**, so a fee is never rounded up in Nevermined's favour.
* `fee.capChargedCents` — what your Delegation cap is debited — is a **cents** figure, and cents always round up.

How much that costs depends on what the rail can tell the Router about converting its asset to cents. When it can, the merchant amount and the fee are rounded up **together**, as one figure — so a sub-cent fee only costs you an extra cent when it tips the total across a cent boundary. When it can't, the fee is rounded up **on its own**, and then **any non-zero rate costs at least one whole cent of cap per payment** — a 1-cent purchase at 2% is debited 2 cents. The one case that does *not* cost you a cent is a fee that truncates below a single atomic unit: it could never be transferred, so it is dropped outright rather than reserved, and you are charged the merchant amount alone.

So don't derive the cap charge from the amount and the rate. Read `fee.capChargedCents` — it's the figure your budget actually moved by.

Every mint response — `POST /payments` in mode A, `POST /route` in mode B — carries a `fee` object:

| Field                 | What it is                                                                                                                                                                                   |
| --------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `fee.bps`             | The rate applied to this payment, in basis points over a 10,000 denominator. `0` means no routing fee was charged.                                                                           |
| `fee.amount`          | The fee in the settlement asset's smallest unit — the same unit as `settlement.amount`, rounded **down**. Reported atomically because cents are rounded up and can't express a sub-cent fee. |
| `fee.cents`           | What the fee added to the cap reserve, in cents, rounded **up**.                                                                                                                             |
| `fee.capChargedCents` | The total debited from your Delegation cap for this payment: merchant leg + fee.                                                                                                             |

`settlement.approxCents` remains the **merchant** leg throughout — it is not the whole cap charge. With no fee configured the two are equal.

The streaming `/proxy` variant returns its payment metadata as response headers, and there is no fee header among them. For those calls, read the fee from [the ledger record](/docs/products/catalog/router/ledger#the-routing-fee-on-a-record).

### When a fee is not collected

A reserved fee isn't always collected, and what happens to the reserve then differs by leg.

**The merchant leg is never given back.** Once the credential is minted, the merchant may have taken the payment and then errored — so the reservation stands whatever the call did afterwards.

**The fee leg can come back — but only on a closed list of paths.** A mode-B hop that never returned 2xx, a facilitator that adjudicated and refused, or a fee movement that couldn't be signed: on each of those the fee's cents are credited back to your Delegation cap and the ledger row reads [`feeStatus: "Released"`](/docs/products/catalog/router/ledger#fee-lifecycle). Nothing else releases. A fee whose outcome is *unknown* stays `Submitted` and is resolved against the chain — and **resolving is not releasing**: a row the chain shows was never consumed becomes `Failed` with its reserve **still charged**. Read `feeStatus` for the credit; never infer it from a failure.

Two preconditions decide whether the question is even asked, and both are easy to miss:

* **Only the x402 rail can collect a routing fee at all.** MPP payments cannot produce a second settleable authorization, so they reserve the merchant leg alone.
* **Mode A collects only on calls that pass a `requestId`.** Without one a retry cannot be deduplicated, so the fee is neither collected nor reserved (`feeStatus: "None"`). `requestId` is optional in mode A and required in mode B, so this is the common case rather than an edge one.

The mode then decides when the fee settles. Mode B settles it only after the merchant returns 2xx, so a hop that fails releases the fee. Mode A settles it at mint, before your credential is ever presented — so on mode A a wallet holding only the merchant's price typically pays the fee and then loses the merchant leg on-chain, and there is nothing to release.

### Fund for the amount plus the fee

Because the fee is its own movement, the merchant's amount and the fee are **two separate transfers** pulled from the same wallet in the same asset. A wallet holding exactly the merchant's quoted price does not cover both, and the two succeed or fail independently — one failing doesn't roll the other back.

So size your funding by **amount + fee**, not by the quoted price. On x402, where [nothing checks your balance up front](#where-custody-sits), that's the difference between a shortfall being impossible and it being discovered after your budget is already committed.

## How settlement gets recorded

When the merchant accepts the credential it returns a settlement reference — a `PAYMENT-RESPONSE` header on x402, a `Payment-Receipt` on MPP. In mode B the Router reads it and stores it on the record.

* On success the record goes to **`Settled`** with the reference stored as `txHash`.
* If the merchant paid but returned no usable reference, the record stays **`Issued`** — a normal state meaning "the hop succeeded, settlement is pending observation". It is not an error and the Router will not fail an already-paid call over it.
* If the merchant rejects the credential and returns another 402, the record is marked **`Failed`**.

<Warning>
  The settlement reference is **merchant-controlled and stored unverified**. It's bounded in length and character set, but the Router does not confirm on-chain that the referenced transaction exists or paid what it claims. Treat it as an anchor for reconciliation, not as proof of payment.
</Warning>

## Next

<CardGroup cols={2}>
  <Card title="Quickstart" icon="rocket" href="/docs/products/catalog/router/quickstart">
    Run the whole flow yourself.
  </Card>

  <Card title="Guardrails" icon="shield-check" href="/docs/products/catalog/router/guardrails">
    Everything the Router checks before it signs.
  </Card>
</CardGroup>


## Related topics

- [Catalog Overview](/docs/products/catalog/overview.md)
- [How the x402 Facilitator Works](/docs/products/x402-facilitator/how-it-works.md)
- [Organizations & Workspaces](/docs/integrate/patterns/organizations.md)
- [MCP Point of Sales](/docs/solutions/mcp-point-of-sales.md)
- [Get a Nevermined API Key](/docs/agents-guide/get-api-key.md)
