---
title: "Route a request through the Router, paying the agent’s 402 and relaying the reply (mode B)"
method: POST
path: "/router/route"
tags: ["Router"]
---

# Route a request through the Router, paying the agent’s 402 and relaying the reply (mode B)

`POST /router/route`

## Request

- Base URL: `https://api.sandbox.nevermined.app/api/v1`
- URL: `https://api.sandbox.nevermined.app/api/v1/router/route`
- Auth: HTTP bearer

Hand the Router the request you want made to an upstream x402 agent; it probes, pays any 402
with your Delegation (same engine as `POST /router/payments`), and relays the agent’s response in ONE
call — you never see the 402 or handle the credential yourself.

Prerequisite: a Delegation `id` (`POST /api/v1/delegation/create`, provider `erc4337`).

Provide the target `url` (+ optional `method`, `headers`, `body`). A free (non-402) upstream is
relayed unchanged with `paid=false` and no `payment`. `requestId` is REQUIRED (the Router pays automatically, so a retry must be idempotency-keyed); a duplicate returns 409 with the original paymentId (from API 1.48, the first purchase's retained result instead — see `GET /router/payments/{id}/result`).

For LARGE or STREAMED responses, a transparent streaming variant exists at `ALL /api/v1/router/proxy`:
point your HTTP client at it with headers `X-Router-Target-Url` and `X-Router-Delegation-Id`
(optional `X-Router-Upstream-Authorization` for the agent’s own auth). Method/body/headers pass
through and the response streams back, with payment metadata in `X-Router-Payment-Id`,
`X-Router-Payment-Status`, and `X-Router-Tx-Hash` response headers. Use this JSON endpoint when
you want a single structured result instead.

## Request body

- ProxyRequestDto
  - `delegationId` string, required: The caller's erc4337 delegation to spend against (as in `POST /router/payments`).
  - `url` string: Absolute upstream URL to route to (http/https only). Provide EXACTLY ONE of `url` or `slug`.
  - `slug` string: Catalog slug to invoke via the opaque Router broker. The Router resolves the slug to the real upstream server-side, so the URL is never exposed. Mutually exclusive with `url`. Required to read the result of an async service (an endpoint the catalog marks `auth: "siwx"`): the Router answers its wallet challenge only on a slug call.
  - `path` string: Optional subpath appended to the resolved upstream when `slug` is used (e.g. `scrape` → the merchant's `/scrape`). Path segments only — it may not change the host: `//`, `..`, a backslash and an embedded absolute URL are rejected (400). A catalog template placeholder (`{jobId}`, `:id`) must be filled with a real value, or the call is refused (400). Ignored when `url` is used.
  - `search` string: Query string for a slug-routed request, without the leading ?. It is attached to the resolved merchant URL without changing its host. Use this instead of embedding ? in path. With a raw url, include the query in url; sending search with url is refused.
  - `method` 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE': HTTP method to use for the upstream request.
  - `headers` object: Headers to forward to the upstream (e.g. the agent’s own auth). Optional.
  - `body` unknown
  - `protocol` 'x402' | 'mpp': Payment protocol. On the mode-B proxy (`/route`, `/proxy`) this is ADVISORY: the Router AUTO-DETECTS the protocol from the upstream 402 — `WWW-Authenticate: Payment` → `mpp`; `accepts` / `PAYMENT-REQUIRED` → `x402` — and the DETECTED protocol is authoritative for the mint (a mismatching hint here does not change what gets paid).
  - `requestId` string, required: Idempotency key — REQUIRED for routed payments (mode B). The Router makes the upstream call and pays automatically, so a retry after a dropped connection must not double-spend. At most one payment is minted per (caller, requestId); a duplicate returns 409 (BCK.ROUTER.0002) carrying the original paymentId, rather than paying again.

## Response `201`

The relayed upstream response (`status` + `body`) plus the `payment` that was made.

- RouteResultDto
  - `status` number, required: The upstream HTTP status code that was relayed.
  - `body` unknown, required
  - `paid` boolean, required: Whether a payment was made (false = the upstream was free).
  - `payment` RouteResultPaymentDto
    - `resultUrl` string: Where this paid result stays readable by you for 24 hours (GET it with the same API key), in case the response is lost on the way back to you. Relative to the API host. API 1.48 and later.
    - `paymentId` string, required
    - `settlement` SettlementDescriptorDto, required
      - `recipient` string, required: The on-chain recipient (the agent’s `payTo` address from its 402).
      - `amount` string, required: Amount in the asset’s smallest unit (USDC/EURC = 6 decimals).
      - `asset` string: For x402 the asset symbol (`USDC`/`EURC`); for mpp the tempo payment token contract address (mpp carries no on-wire symbol).
      - `network` string, required: Network the payment settles on (name or CAIP-2).
      - `approxCents` string, required: The MERCHANT leg in cents (rounded up) — what this credential pays the upstream agent. This is not necessarily the whole cap charge: Nevermined’s routing fee is reserved on top, so the whole-cent total debited from the delegation is `approxCents + fee.cents` (also reported directly as `fee.capChargedCents`; the exact sub-cent debit is `fee.capChargedMicros`). With no fee configured the two are equal.
      - `scheme` 'exact' | 'charge' | 'spt': Ledger settlement scheme: `exact` for x402 (EIP-3009), `charge` for MPP-tempo (a native Tempo transaction), `spt` for MPP-stripe (a Shared Payment Token). Omitted (defaults to `exact`) on the x402 path.
    - `fee` RouterFeeDto, required
      - `bps` number, required: Rate applied to this payment, in basis points over a 10,000 denominator (e.g. `200` = 2%). `0` means no routing fee was charged.
      - `amount` string, required: The fee in the settlement asset’s smallest unit — the same unit as `settlement.amount`. Reported atomically rather than in cents because cents are ceiling-rounded and cannot express a sub-cent fee.
      - `cents` string, required: Cents this fee added to the delegation-cap reserve, i.e. `capChargedCents - settlement.approxCents`.
      - `capChargedCents` string, required: The delegation-cap debit for this payment (merchant leg + routing fee), rounded UP to a whole cent. The cap itself accrues at sub-cent resolution, so the exact debit is `capChargedMicros`; this figure is the per-call price guard that `maxTotalCents` is compared against.
      - `capChargedMicros` string, required: The exact delegation-cap debit for this payment (merchant leg + routing fee), in micros — millionths of the currency unit, i.e. 1/10,000 of a cent. It is a ceiling of the true price at that resolution, never below it. It is the debit AT MINT: if the routing fee or the merchant leg is later found uncollected, that part is given back to the cap while this figure stays as minted.
    - `txHash` string, nullable: On-chain settlement tx, if the upstream reported one.
    - `status` 'Issued' | 'Settled', required

## Other responses

- `202`: API version 1.48 or later: the payment was made but the merchant had not answered within 45 s. The call keeps running on the Router (bounded at 120 s) and its result will be readable by you for 24 hours at `resultUrl` (also the `Location` header). Poll `GET /api/v1/router/payments/{id}/result`; do not repeat the call — a retry with the same `requestId` returns this same answer, then the result.
- `400`: Invalid request, no fundable option, or an upstream/402 error (BCK.ROUTER.0001); or every option advertised an EIP-712 domain its own settlement token does not sign under (BCK.ROUTER.0012); or the payment credential would overwrite a header you asked the Router to forward, with no `credentialHeader` naming where the service wants it instead (BCK.ROUTER.0021 — refused before minting, so no money moved). A request-body validation failure arrives as BCK.HTTP.400 instead.
- `401`: Missing/invalid Nevermined API key.
- `402`: Delegation budget exceeded, expired, or inactive (BCK.ROUTER.0003).
- `403`: Credential barred from the Router spend rails — an OAuth-minted key (device/auth-code ceremony) may not spend here; use a plain account key (BCK.OAUTH.0030). Permanent, do not retry.
- `409`: The `requestId` was already used — idempotency conflict (BCK.ROUTER.0002).

---

[API](https://skmtc.dev/nevermined/apis/nevermined-api.md) · [All operations](https://skmtc.dev/nevermined/apis/nevermined-api/llms.txt) · [OpenAPI document](https://skmtc.dev/nevermined/apis/nevermined-api/revisions/cabbe618c80b?raw)
