---
title: PayAI x402 Facilitator — developer reference
description: Endpoints, authentication, error model, versioning, and rate limits for the PayAI x402 Facilitator API.
source: https://facilitator.payai.network/developers
---

# PayAI x402 Facilitator — developer reference

Everything an agent or a developer needs to call this API. Machine-readable equivalents: OpenAPI 3.1 at /openapi.json, agent guide at /llms.txt.

## What this API does

This origin is the PayAI x402 facilitator. It implements the facilitator role of the [x402 protocol](https://docs.payai.network//x402/introduction): it verifies signed stablecoin payment payloads and settles them on-chain, so a resource server can charge per request without touching a wallet, an RPC node, or a private key.

x402 revives the HTTP `402 Payment Required` status code. A server answers an unpaid request with `402` and machine-readable payment terms, the client signs a stablecoin payment, and the facilitator verifies and settles it. No accounts, no API keys, no card on file, no human in the loop.

The base URL for every endpoint below is `https://facilitator.payai.network`. A complete OpenAPI 3.1 description is served at [`/openapi.json`](https://facilitator.payai.network/openapi.json).

## When to call it

- You received an HTTP `402 Payment Required` response and need to check whether a signed payment is valid before serving a resource — call `POST /verify`.
- You have verified a payment and want the funds moved on-chain — call `POST /settle`.
- You need to know which chains, schemes, and protocol versions are live right now — call `GET /supported`.
- You want to discover services an agent can pay for — call `GET /discovery/resources`.

This facilitator settles stablecoin micropayments over HTTP. It is not a payment processor for consumer checkout: no card payments, no fiat payouts, no bank transfers, no subscription billing, and it never custodies merchant balances.

## Endpoints

| Method and path | What it does |
| --- | --- |
| `GET /health` | Liveness probe. Returns 200 while the facilitator is accepting traffic. |
| `GET /supported` | Every (x402 version, scheme, network) combination that is live right now, plus the fee-payer and facilitator addresses that sponsor gas. |
| `GET /verify` | Self-describing hint: names the endpoint and its expected request body. |
| `POST /verify` | Verify a signed payment against its payment requirements. Does not move funds. |
| `GET /settle` | Self-describing hint for the settle endpoint. |
| `POST /settle` | Settle a payment on-chain. Idempotent: re-submitting an identical body returns the original outcome rather than paying twice. |
| `GET /discovery/resources` | The PayAI Bazaar catalog of x402-payable HTTP endpoints and MCP tools, with payment terms and, where published, input and output schemas. Paginated by `limit` and `offset`. |
| `GET /discovery/stats` | Aggregate catalog and settlement statistics. |
| `GET /discovery/resources/{resource}/stats` | Settlement statistics for one catalog resource. |
| `GET /list` | Deprecated. Redirects (308) to `/discovery/resources`. |

## Authentication

Every `GET` endpoint is public and unauthenticated. `POST /verify` and `POST /settle` take an optional `Authorization: Bearer <api-key>` for credit accounting, per-account settlement lanes, and analytics attribution. Without a key you are served on the free tier. Keys come from [the merchant portal](https://merchant.payai.network).

```bash
curl -s https://facilitator.payai.network/supported

curl -s -X POST https://facilitator.payai.network/verify \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer <api-key>' \
  -d '{"x402Version":1,"paymentPayload":{...},"paymentRequirements":{...}}'
```

## Error model

Errors are always JSON, never an HTML page. Two shapes exist, and which one you get depends on the endpoint.

`POST /verify` and `POST /settle` return the x402 response shape even on a non-2xx status, because the x402 client SDKs parse the body regardless of status code:

- `/verify` — `{ isValid: false, invalidReason, invalidMessage }`
- `/settle` — `{ success: false, errorReason, errorMessage, transaction, network, payer }`

Every other endpoint, every unknown path, and every unhandled failure returns [RFC 9457](https://www.rfc-editor.org/rfc/rfc9457) problem details with `Content-Type: application/problem+json`:

```json
{
  "type": "https://facilitator.payai.network/developers#not-found",
  "title": "Not Found",
  "status": 404,
  "detail": "No resource is served at GET /no-such-path."
}
```

Treat `errorReason: "settlement_pending"` on `/settle` as unresolved rather than failed: the payment may still land. Re-submit the identical body to poll for the final outcome — idempotency makes that safe.

`POST /settle` also accepts an optional `Idempotency-Key` header. A key is bound to the first request body it is used with for 24 hours, even while the outcome is unresolved: same-body retries replay a recorded terminal response with `Idempotency-Replayed: true`, reuse with a different body returns 422 regardless of outcome state, and concurrent same-body use returns 409.

`settlement_pending`, `duplicate_settlement`, 429, and 5xx outcomes are never cached, so a retry can continue polling instead of replaying an unresolved result. Terminal responses are retained for 24 hours, and signed-payload idempotency protects every settlement whether or not the header is present.

### Problem type: not-found

No route is served at the requested path. Check the endpoint table above; note that there is no `/v1/` prefix. Returned as `404`.

### Problem type: bad-request

The request could not be parsed — most often a body that is not valid JSON. Returned as `400`. On `/verify` and `/settle` this arrives in the x402 response shape instead, with reason `invalid_payload`.

### Problem type: internal-server-error

The facilitator failed to handle the request. The response carries no internal detail by design; retry with backoff, and quote the time of the request when contacting support. Returned as `500`.

## Versioning

This API is versioned by the x402 protocol version it speaks, not by a URL path segment and not by a version request header. There is no `/v1/` prefix, and sending one will 404.

Every request carries `x402Version` (`1` or `2`) in its body, and the response echoes the version it was handled as. `GET /supported` advertises which (version, scheme, network) combinations are live: v1 uses short network names such as `base` and `solana`, v2 uses CAIP-2 identifiers such as `eip155:8453`. Both versions are served from the same paths, so an integration pins a version by what it sends, not by what it calls.

A payment kind is withdrawn by disappearing from `GET /supported` before the endpoints stop accepting it, so a client that polls `/supported` sees a removal coming. Breaking changes to request or response shapes arrive as a new `x402Version`; existing versions keep working until they leave `/supported`.

## Rate limits

Throughput is limited per client IP at the edge, split into three buckets so an expensive settlement cannot starve the cheap reads that sit inside every paid call. Exceeding a bucket is rejected before the request reaches the API.

| Policy | Applies to | Requests per second, per IP |
| --- | --- | --- |
| `settle` | `POST /settle` | 100 |
| `payments-read` | `/verify`, `/supported` | 200 |
| `discovery` | `/discovery/*` and all other paths | 25 |

Each response carries a `RateLimit-Policy` header naming the bucket that governs the path you called. The budget is enforced per ingress replica, so it is a floor rather than an exact ceiling.

No `RateLimit` header reporting remaining budget is emitted, because the limiter runs at the edge and the API is not told how much of your budget is left. Back off on the response status, not on a header countdown.

Separately from request rate, the free tier is capped by total settlements. Exhausting it returns HTTP 403 with `errorReason` beginning `free_tier_exhausted`; buy credits at [the merchant portal](https://merchant.payai.network) to lift it. Current allowances are on the [pricing section](https://facilitator.payai.network/#plan).

## Machine-readable surfaces

- [`/openapi.json`](https://facilitator.payai.network/openapi.json) — OpenAPI 3.1 description of every endpoint above. This is the canonical copy.
- [`/llms.txt`](https://facilitator.payai.network/llms.txt) — short orientation guide for agents, including when to reach for this service and when not to.
- [`/llms-full.txt`](https://facilitator.payai.network/llms-full.txt) — the guide plus this entire reference inline.
- [`/.well-known/api-catalog`](https://facilitator.payai.network/.well-known/api-catalog) — RFC 9727 linkset naming every published API description.
- [`/.well-known/mcp.json`](https://facilitator.payai.network/.well-known/mcp.json) — MCP server manifest.
- [`/.well-known/ai-catalog.json`](https://facilitator.payai.network/.well-known/ai-catalog.json) — the callable interfaces PayAI exposes.
- [`/.well-known/security.txt`](https://facilitator.payai.network/.well-known/security.txt) — RFC 9116 vulnerability disclosure contact.

Every page on this origin also serves Markdown. Request it with `Accept: text/markdown`, or append `.md` to the path — for example [`/developers.md`](https://facilitator.payai.network/developers.md).

## Testing an integration

[The x402 Echo Merchant](https://x402.payai.network/) is a live merchant that returns HTTP 402, for testing a client end to end against real payment terms. Quickstarts for Express, Hono, Next.js, FastAPI, Flask, and Gin are in [the documentation](https://docs.payai.network//x402/servers/introduction); client quickstarts for Axios, Fetch, httpx, requests, and Go are at [https://docs.payai.network//x402/clients/introduction](https://docs.payai.network//x402/clients/introduction).

Questions, support, and security reports: [info@payai.network](mailto:info@payai.network).
