---
title: "Settle Permission"
method: POST
path: "/x402/settle"
tags: ["X402 - Permissions"]
---

# Settle Permission

`POST /x402/settle`

## Request

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

Finalizes and records delegated permission usage after service delivery.

## Request body

- SettlePermissionRequest: Body of `POST /x402/settle` — the same `SettlePermissionsDto` as verify. `paymentRequired` and `x402AccessToken` are both required and the handler runs a `ValidationPipe`, so a body missing either is rejected with 400 before settlement runs. `planId`, `subscriberAddress`, `agentId`, the endpoint and the HTTP verb are read out of the token — never sent alongside it.
  - `paymentRequired` X402PaymentRequired, required: The server's 402 PaymentRequired response (`X402PaymentRequiredDto`), echoed back to the facilitator on verify and settle. The facilitator checks that the `accepted` scheme carried inside the token matches one of `accepts`.
    - `x402Version` integer, required: x402 protocol version.
    - `error` string: Human-readable error message from the 402 response.
    - `resource` X402Resource, required: x402 protected-resource descriptor (`X402ResourceDto`). The same shape appears in the server's 402 `paymentRequired` and in the payload you mint at `POST /x402/permissions`.
      - `url` string, required: URL of the protected resource or endpoint.
      - `description` string: Human-readable description of the resource.
      - `mimeType` string: Expected response MIME type.
    - `accepts` X402Scheme[], required: Payment schemes the server accepts for this resource.
      - `scheme` 'nvm:erc4337' | 'nvm:card-delegation', required: Payment scheme identifier. Selects the settlement rail: `nvm:erc4337` settles on-chain, `nvm:card-delegation` settles against an enrolled card.
      - `network` string, required: Settlement RAIL, not the environment. Card flows send `stripe`, `braintree` or `visa`; crypto flows send `eip155:<chainId>`. An environment name such as `sandbox` or `live` is rejected by request validation.
      - `planId` string: Plan id (256-bit identifier). Required for BOTH schemes — a mint without it is refused with `BCK.X402.0030` (HTTP 402). Request validation does not enforce it for either scheme: the DTO marks it optional, so the rejection comes from the scheme handler rather than from the `ValidationPipe`.
      - `extra` X402SchemeExtra: Scheme-specific extra fields (`X402SchemeExtraDto`). Every field is optional. On `tokenVersion` 3, `agentId` and `httpVerb` are signed as the empty string when omitted — which binds the token to that value being ABSENT rather than to any value. `version` is not part of the v3 signed struct at all, so omitting it binds nothing.
        - `version` string: Scheme version.
        - `agentId` string: Agent id the token is bound to, used for endpoint validation.
        - `httpVerb` string: HTTP verb the token is bound to, used for endpoint validation.
    - `extensions` object, required: Extensions object. Empty (`{}`) for `nvm:erc4337`, but the field itself must be present — it is validated as required.
  - `x402AccessToken` string, required: The x402 payment payload, base64-encoded — the token minted by `POST /x402/permissions`.
  - `maxAmount` string: Maximum credits to redeem during settlement. Send it as a decimal STRING: the value is parsed with `BigInt()` and then required to be a bigint, so a JSON number is rejected with 400.
  - `agentRequestId` string: Agent request id for observability, as returned by `POST /x402/verify`. Bounded to 1–128 URL-safe ASCII characters because the value is interpolated into a Helicone filter and persisted to `agent_tasks`.
  - `batch` boolean: Whether this settles a batch — several LLM calls made under one `agentRequestId`.
  - `marginPercent` number: Margin percentage used for credit calculation. Mutually exclusive with `maxAmount` when `agentRequestId` is supplied.

## Response `201`

Settlement complete

- SettlePermissionResponse: Settlement receipt. `success` alone tells you the settle worked; what to check in addition depends on `billingModel`. On `credits` plans the payment shows up as `creditsRedeemed > 0`. On `pay-as-you-go` plans there is no credit balance, so `creditsRedeemed` and `remainingBalance` are always the string "0" even on a charge that succeeded — the proof there is `success: true` plus a non-empty `orderTx` (fiat rails) or `transaction` (crypto rails). Do not gate on `creditsRedeemed` without reading `billingModel` first: on a card rail that reports a real charge as a decline and invites a retry of a payment that already went through. Note the credit fields are strings, so "0" is truthy while Number("0") > 0 is false.
  - `success` boolean: Whether settlement was successful.
  - `errorReason` string: Reason for settlement failure (only present if success is false).
  - `payer` string: Address of the payer's wallet.
  - `transaction` string: Blockchain transaction hash. On crypto pay-as-you-go plans this is also the reference for the per-request charge.
  - `network` string: Network identifier. The discriminator is the rail, not the billing model: a CAIP-2 chain id (eip155:84532) for crypto rails under both billing models, or the settling payment provider (stripe, braintree, visa) for fiat card-delegation rails.
  - `billingModel` 'credits' | 'pay-as-you-go': Which billing model this settle was priced under. Present regardless of `success` — check `success` before treating it as evidence of a charge. Read it before the two credit fields.
  - `creditsRedeemed` string: Number of credits redeemed. Always "0" for pay-as-you-go plans, which hold no credit balance — including on a settle that charged the buyer successfully.
  - `remainingBalance` string: Subscriber's remaining credit balance. Always "0" for pay-as-you-go plans — the per-request charge is referenced by `orderTx` (fiat) or `transaction` (crypto), not here.
  - `orderTx` string: Reference for the order or per-request charge, if one occurred. On fiat pay-as-you-go this is the per-request charge (a Stripe PaymentIntent id, a Braintree transaction id); crypto pay-as-you-go reports its on-chain order in `transaction` instead. On credits plans it is set only when the settle had to order credits first (auto top-up).

## Other responses

- `402`: Settlement failed - insufficient credits

---

[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)
