# Paying for pro access (x402)

Paid access with [x402](https://www.x402.org) is announced but not active. This guide is rendered from the service configuration, so it always states the current mode. Everything under `/v1/` except `/v1/pro/*`, and the `/mcp` endpoint, is free.

## Status

Paid access is announced but **not active**. Pro routes (`/v1/pro/*`) and the pro MCP endpoint (`/mcp/pro`) currently serve free data: no payment is required and none is charged. This page lists the network, asset and prices once paid access is activated.

The rest of this page describes how paying will work, so a client can be built ahead of time.

## Paying over REST

1. Call a pro route with a plain `GET` and no payment. The answer is 402 with the problem type [payment-required](https://api.criptonlabs.com/errors/payment-required.md) and a `PAYMENT-REQUIRED` header.
2. `PAYMENT-REQUIRED` is base64 of JSON: `{ "x402Version": 2, "error": ..., "resource": { "url": ... }, "accepts": [ ... ] }`. Each `accepts` entry is one way to pay: `scheme`, `network`, `asset`, `amount` (atomic units), `payTo`, `maxTimeoutSeconds`, `resource` and `extra.feePayer`.
3. Choose the `accepts` entry whose `extra.feePayer` belongs to the facilitator you want to settle through, and sign a payment for exactly that entry.
4. Repeat the same `GET` with the payment in the `PAYMENT-SIGNATURE` header (base64 of the JSON payment payload).
5. On 200 the `PAYMENT-RESPONSE` header carries the settlement result (base64 of JSON, including the transaction signature) and the body carries the data.

Rules that always hold:

- **One payment per call.** A payment key can be used once; sending it again answers 402 [payment-already-used](https://api.criptonlabs.com/errors/payment-already-used.md).
- **Only `GET` on the exact paths is charged.** `HEAD` and every other method on a priced path answer 405 [method-not-allowed](https://api.criptonlabs.com/errors/method-not-allowed.md); a path with a trailing slash is 404 and is never priced.
- **A payment is bound to the exact resource.** It covers the path without the query string (`https://api.criptonlabs.com/v1/pro/xrpl/fee`), so one payment covers one call to that path with any query. A payment signed for another path is refused with 402.
- **Size cap.** `PAYMENT-SIGNATURE` and the MCP payment value are limited to 8192 bytes; larger values are refused with 402 before they are decoded.
- **Settlement comes first.** The service settles only after the data route answered 2xx, and releases the data only if settlement succeeded. If settlement fails the answer is 402 [payment-settlement-failed](https://api.criptonlabs.com/errors/payment-settlement-failed.md) with no data. A route that answers 4xx or 5xx is not charged.
- **A failed or expired payment is spent.** If verification failed, the facilitator was unavailable or settlement failed, the payment key cannot be reused: sign a new payment. The same holds when the route answered a handler error or any non-2xx status: nothing was charged and the reservation ends as `expired` with the flag `not_served`, yet the same signed payment answers 402 [payment-already-used](https://api.criptonlabs.com/errors/payment-already-used.md). Sign a new payment.

## Paying over MCP

`/mcp/pro` is the paid twin of `/mcp`: the same tools, schemas and docs resources. `initialize`, `tools/list`, resources and prompts are free; only `tools/call` is charged.

1. Call a tool without payment. The result has `isError: true` and its `structuredContent` is the same PaymentRequired object as the REST header (`x402Version`, `error`, `resource`, `accepts`) merged with the problem fields.
2. Sign a payment for the `accepts` entry you chose and send it in the call as `_meta["x402/payment"]` (the JSON payload object, not base64), at most 8192 bytes serialized.
3. On success the result carries `_meta["x402/payment-response"]` with the settlement result.

A payment is bound to one tool: its resource is `mcp://criptonlabs/pro/<tool>`, so a payment signed for `xrpl_fee` is refused for `xrpl_orderbook` even when both cost the same.

## Prepay: skip the 402 round trip

`GET /v1/pro/requirements?resource=<resource>` is free (cheap rate tier) and never asks for payment. It returns `{ "x402Version": 2, "resource": { "url": ... }, "accepts": [ ... ], "payments_mode": ... }`. `resource` is a `/v1/pro/*` path without a query string, or `mcp://criptonlabs/pro/<tool>` for a paid tool. Fetch `accepts`, sign, and send the payment on the first call.

Without `resource`, `GET /v1/pro/requirements` returns the price index instead: every paid route and tool with its price, the network, asset and mint in x402 mode, and a link to each per-resource offer. It is free, uncharged and in the cheap rate tier too.

The offer is deterministic for one price table and one facilitator set, so a prepaid payment stays valid only while those facilitators stay available and healthy. When it changes, the call answers 402 with the current offer. The live source of the current `accepts` is the 402 `PAYMENT-REQUIRED` header or this route, never a copy of an earlier answer. While `payments_mode` is off or gateway, `accepts` is empty and `payments_mode` says so.

## Discovery metadata

`https://api.criptonlabs.com/openapi.json` marks every free operation with `security: []`. While x402 payments are enabled and healthy, each priced `/v1/pro/*` operation also carries `x-payment-info` (`protocols: [{"x402": {}}]` and a fixed price in `EUR` as a human decimal amount, for example `0.005`, not atomic units) next to its documented 402 response, and declares no `security` requirement. Otherwise no operation carries `x-payment-info`. `info.contact` and `info["x-guidance"]` give a short agent summary.

`https://api.criptonlabs.com/.well-known/x402` lists the absolute URL of every priced `/v1/pro/*` route as `{ "version": 1, "resources": [...] }` while x402 payments are enabled and healthy, and answers 404 otherwise. The runtime 402 challenge stays the authoritative source of the offer. `https://api.criptonlabs.com/.well-known/ard.json` lists the MCP Server Card and the agent card for Agentic Resource Discovery clients.

## Server-side clients only

Paid access is designed for server-side clients and agents. Browsers are not supported: pro routes send no CORS headers, so a page script cannot read their answers or send the payment headers.

## Statuses

| Status | Problem type | Meaning | What to do |
|---|---|---|---|
| 402 | [payment-required](https://api.criptonlabs.com/errors/payment-required.md) | No payment, or one that was not accepted (wrong amount, network, asset or resource, bad signature, too large, or rejected on verification). Carries `PAYMENT-REQUIRED`. | Sign one of the listed options and repeat the call. |
| 402 | [payment-settlement-failed](https://api.criptonlabs.com/errors/payment-settlement-failed.md) | Settlement failed or could not be confirmed in time. No data. Carries `PAYMENT-REQUIRED`. | Sign a new payment and repeat the call. If your wallet was debited, keep the transaction signature and check it before paying again. |
| 402 | [payment-already-used](https://api.criptonlabs.com/errors/payment-already-used.md) | This payment was already used. Carries `PAYMENT-REQUIRED`. | Sign a new payment for every call. |
| 403 | [payer-blocked](https://api.criptonlabs.com/errors/payer-blocked.md) | This payer cannot use paid access. | Use another payer or the free routes. |
| 405 | [method-not-allowed](https://api.criptonlabs.com/errors/method-not-allowed.md) | A priced path answers `GET` only. | Use `GET`. |
| 429 | [payer-limit-reached](https://api.criptonlabs.com/errors/payer-limit-reached.md) | The payer reached its daily limit of failed settlements. `Retry-After` is the time to 00:00 UTC. | Wait for `Retry-After`. |
| 429 | [rate-limited](https://api.criptonlabs.com/errors/rate-limited.md) | Per-IP rate limit (the `pro` tier for paid calls). `Retry-After` says how long. | Wait, then retry. |
| 503 | [payments-unavailable](https://api.criptonlabs.com/errors/payments-unavailable.md) | Paid access is temporarily unavailable (verification could not be completed, or the configuration is invalid). Nothing was served or charged. | Retry later with a new payment, or use the free routes. |
