---
title: "x402 facilitator security: /verify and /settle | Settlens"
description: "How x402 facilitators verify and settle payments, the risks at /verify, /settle and /supported, and which of them Settlens can test without moving funds."
url: https://settlens.com/learn/x402-facilitator-security
last_updated: 2026-10-13
published: 2026-10-13
---

# x402 facilitator security

> **In short:** An x402 facilitator checks payments with a read-only POST /verify, commits them with POST /settle and lists what it supports at GET /supported. Risks include a /verify that accepts forged signatures, capabilities that drift from what servers advertise, and pending settlements retried unreconciled.

The facilitator is the part of x402 that turns a signature into a payment. This guide covers its three endpoints, the payment flows that decide when they run, the ways they fail, and what an outside test can and cannot prove.

In x402, the resource server decides whether a request is paid, but it rarely checks signatures or talks to a blockchain itself. It hands the client's payment to a [facilitator](https://settlens.com/learn/glossary#facilitator): a service that verifies the authorization and settles it on a network. The [x402 V2 core specification](https://github.com/x402-foundation/x402/blob/main/specs/x402-specification-v2.md) lets a resource server delegate this to a third party or host the endpoints itself. Either way, a facilitator error decides whether paid content leaks for free or a client pays twice.

> **Checked on Oct 13, 2026**
>
> Protocol statements on this page follow section 7 (facilitator interface), section 9 (error handling) and section 10 (security considerations) of the V2 core specification, and the [exact EVM scheme](https://github.com/x402-foundation/x402/blob/main/specs/schemes/exact/scheme_exact_evm.md). The scheme catalog evolves; re-read the specification before relying on a detail.

## The three facilitator endpoints

_x402 V2 facilitator interface_

| Endpoint | What it does | Answer |
| --- | --- | --- |
| `POST /verify` | Checks a payment authorization against the payment requirements without executing it. It is read-only: it must not commit payment state or write on chain. | `VerifyResponse`: `isValid`, and `invalidReason` when it is false. |
| `POST /settle` | Durably commits the payment, typically by broadcasting a transaction. It can be called more than once for one payment, as in the escrow flow. | `SettleResponse`: `success`, `transaction`, `network`, and `errorReason` on failure. |
| `GET /supported` | Lists what the facilitator can process. | `kinds` (version, scheme, network), `extensions` and `signers` per CAIP-2 pattern. |

Both `POST` endpoints take the same body: `x402Version`, the client's `paymentPayload` and the `paymentRequirements` it should satisfy. The resource server should send its own requirement there, not the copy the client echoed in `accepted`.

## When /verify runs: payment flows

The [payment flow](https://settlens.com/learn/glossary#payment-flow) decides which endpoints run, and in which order, around the resource handler:

_Facilitator calls by payment flow (x402 V2 core specification, section 6.1)_

| Flow | Order | Pre-handler check |
| --- | --- | --- |
| `authorization` (default) | verify, resource, settle, respond | `/verify` |
| `upfront` | settle, resource, respond | `/settle`; `/verify` is not part of this flow |
| `escrow` | settle, resource, settle, respond | The first `/settle`, which commits a deposit or ceiling |

The specification's invariant: a verify or a settle must run before the resource executes. Under the default flow, that makes `/verify` the only thing standing between a forged signature and the protected handler.

## What goes wrong

These are risks to look for in any facilitator, with the control the specifications imply for each.

_x402 facilitator risks and controls_

| Risk | Effect | Control |
| --- | --- | --- |
| /verify accepts a forged signature | Under the authorization flow the resource runs for a payment that can never settle: the content leaks for free. | Recover the signer from the EIP-712 digest and require it to equal `authorization.from`; reject the zero address. See the [EIP-3009 guide](https://settlens.com/learn/eip-3009). |
| /verify writes state | Funds or nonces are committed before the handler runs, although the authorization flow promises funds move only after it succeeds. | Keep `/verify` free of on-chain writes; commit only in `/settle`. |
| Capability drift | A resource advertises a scheme or network that the facilitator does not list, so payments fail at verification. | Keep each resource's `accepts` within the facilitator's `/supported` kinds, for the same `x402Version`. |
| Missing signers | A network with no entry in `signers` leaves integrators without the address that signs for it. | Publish signer addresses for every network, or for a namespace wildcard such as `eip155:*`. |
| `settlement_pending` retried blindly | A new authorization carries a new nonce, so it can settle on top of the first transaction: the client pays twice. | Return the broadcast hash and network, and reconcile on chain before any retry. See the [error codes reference](https://settlens.com/learn/x402-error-codes). |
| Replay of an authorization | A captured signature is submitted again or on another chain. | EIP-3009 nonces are single-use on chain, validBefore limits the lifetime, and the EIP-712 domain binds the signature to one chain and token. |

One thing a facilitator cannot do on the EVM `exact` scheme is change the amount or the destination: both are inside the payer's signed message, and the scheme specification limits the facilitator to broadcasting the transaction.

## What Settlens tests

A facilitator scan reads `GET /supported` passively. The `/verify` checks run only during an [active probe](https://settlens.com/learn/glossary#active-probe) that the endpoint owner authorized in writing. The table is generated from the Settlens check catalog.

_Settlens checks that read a facilitator_

| Check id | What it verifies |
| --- | --- |
| `facilitator.reachable` | GET \<facilitator>/supported returned an HTTP response within the timeout. Redirects are not followed.; Mode: facilitator · severity: high |
| `facilitator.response_body_limit` | The /supported response is at most 1 MiB.; Mode: facilitator · severity: high |
| `facilitator.supported_status` | GET /supported returned HTTP 200.; Mode: facilitator · severity: high |
| `facilitator.content_type` | The /supported Content-Type is application/json or another +json media type.; Mode: facilitator · severity: medium |
| `facilitator.https` | The facilitator URL uses HTTPS, or loopback HTTP for local testing.; Mode: facilitator · severity: medium |
| `facilitator.supported_schema` | The body has a non-empty kinds array (each with a positive integer x402Version, a scheme and a network, CAIP-2 for V2 kinds), an extensions array of strings and a signers object mapping networks to string arrays.; Mode: facilitator · severity: high |
| `facilitator.v2_capability` | At least one supported kind has x402Version 2.; Mode: facilitator · severity: high |
| `facilitator.duplicate_kinds` | No x402Version, scheme and network combination appears twice in kinds.; Mode: facilitator · severity: low |
| `facilitator.requirement_coverage` | Every scheme/network pair advertised by the resource appears in the facilitator's /supported kinds for the same x402Version. Skipped when /supported is invalid or unavailable.; Mode: facilitator · severity: high |
| `facilitator.signer_coverage` | Every advertised network has a non-empty signer list in /supported, either for the exact network or for its namespace wildcard (for example eip155:\*).; Mode: facilitator · severity: medium |
| `facilitator.verify_reachable` | During an authorized active probe, POST \<facilitator>/verify with the intentionally invalid payload completed. Reported as a warning only when it could not complete.; Mode: active · severity: medium |
| `facilitator.verify_response_schema` | The /verify answer to the intentionally invalid payload is a JSON object with a boolean isValid field.; Mode: active · severity: high |
| `security.facilitator_rejects_invalid_signature` | /verify returns isValid=false for the intentionally invalid, all-zero signature. Settlens never calls /settle.; Mode: active · severity: critical |

Two runs against the bundled demo target show the checks that matter most. Here the facilitator does not list the Base Sepolia kind that the resource advertises:

**Capability drift (demo target)**

```text
$ settlens scan http://127.0.0.1:4402/secure \
    --facilitator http://127.0.0.1:4402/facilitator-empty --no-write
Settlens x402 assessment 96327c63
Targets 1 · Active 0 · Settlement calls 0
 
127.0.0.1  GET http://127.0.0.1:4402/secure
22 pass · 1 fail · 0 warn · 0 skip
  FAIL high     Facilitator covers advertised payment requirements
       1 advertised payment choice(s) are absent from facilitator capabilities.
 
Total: 22 pass · 1 fail · 0 warn · 0 skip
```

Here the facilitator's `/verify` answers `isValid: true` to an all-zero signature. The probe sends that one invalid payload and never calls `/settle`:

**Authorized active probe of /verify (demo target)**

```text
$ settlens scan http://127.0.0.1:4402/secure \
    --facilitator http://127.0.0.1:4402/facilitator-accept \
    --active --authorized --authorization-ref DEMO-APPROVAL-003 --no-write
Settlens x402 assessment 513cfb74
Targets 1 · Active 1 · Settlement calls 0
 
127.0.0.1  GET http://127.0.0.1:4402/secure
26 pass · 1 fail · 0 warn · 0 skip
  FAIL critical Facilitator /verify rejects an invalid signature
       The facilitator reported isValid=true for an intentionally invalid, all-zero signature.
 
Total: 26 pass · 1 fail · 0 warn · 0 skip
```

## What an outside test cannot prove

- **Settlement.** Settlens never calls `/settle` and never moves funds, so it cannot show that a facilitator settles the right amount once, or handles `settlement_pending` correctly.
- **Chain state.** Balance checks, nonce use and transaction simulation need an RPC node; Settlens works without one.
- **Read-only `/verify`.** A single invalid probe cannot observe whether `/verify` writes state for valid payloads.
- **Valid payments.** The probe proves that one forged signature is rejected, not that every valid payment is accepted.

For these, review the facilitator's code and settlement records. The [facilitator section of the x402 security checklist](https://settlens.com/learn/x402-security-checklist#facilitators) lists every control, and [Settlens for facilitators](https://settlens.com/use-cases/facilitators) describes how operators use the scans. Check ids and fixes are in the [check reference](https://settlens.com/docs/checks).

## Frequently asked questions

**Is the x402 facilitator /verify endpoint allowed to change state?**

No. The x402 V2 specification defines /verify as read-only: it must not commit payment state or write on chain. Only /settle commits the payment.

**Can an x402 facilitator change the amount or the recipient?**

Not on the EVM exact scheme. The amount and recipient are part of what the payer signs (an EIP-3009 authorization by default), and the scheme specification limits the facilitator to broadcasting the transaction.

**Can Settlens test a facilitator without moving funds?**

Yes. It reads GET /supported passively and, with the owner's written authorization, sends one intentionally invalid payload to /verify. It never calls /settle, holds no funds and needs no wallet.

## Sources

1. [x402 protocol specification, version 2](https://github.com/x402-foundation/x402/blob/main/specs/x402-specification-v2.md) — x402 Foundation
2. [x402 scheme: exact on EVM](https://github.com/x402-foundation/x402/blob/main/specs/schemes/exact/scheme_exact_evm.md) — x402 Foundation
3. [ERC-3009: Transfer With Authorization](https://eips.ethereum.org/EIPS/eip-3009) — Ethereum Improvement Proposals
