Docs
The x402 payment rail on Solana — the handshake, the middleware, the program.
Overview
HTTP 402 “Payment Required” is the status code the web reserved and never shipped — formally reserved in RFC 9110 §15.4.3. x402 revives it as a real payment handshake: a server answers a request with 402 and a machine-readable price, the client pays, and the same request is replayed and served.
Otomat is Solana’s x402 payment rail for machine-to-machine, per-call APIs. It settles each request in USDC on Solana through a spec-compliant facilitator and an on-chain settlement program.
Not Solana Pay. Solana Pay encodes a human scanning a QR to pay a merchant. Otomat is the opposite side of the market: software paying software per API call, negotiated entirely over HTTP headers with no human in the loop.
The three payment headers
The handshake rides on three headers. Each carries a base64(JSON) v2 document.
PAYMENT-REQUIREDServer → client on the 402 challengePAYMENT-SIGNATUREClient → server on the paid retryPAYMENT-RESPONSEServer → client with the settled resourceThe flow
- 1Client sends GET for the resource.
- 2Server answers 402 with PAYMENT-REQUIRED (base64 JSON price + payTo + network).
- 3Client decodes the requirements and builds a partially-signed Solana VersionedTransaction paying the amount.
- 4Client replays the request carrying the signed transaction in PAYMENT-SIGNATURE.
- 5The facilitator verifies the payment and settles it on Solana.
- 6Server returns 200 with the resource and the settlement in PAYMENT-RESPONSE.
Quickstart
Price a route with one line of middleware. Pass the per-call price, the asset, and your payTo address.
import express from 'express';
import { otomat } from '@otomat/middleware';
const app = express();
// One line prices the route. Unpaid calls get 402; paid calls run the handler.
app.get(
'/report',
otomat.express({ price: '$0.002', asset: 'USDC', payTo: 'YOUR_SOLANA_ADDRESS' }),
(req, res) => res.json({ report: buildReport() }),
);
app.listen(3000);// app/api/report/route.ts
import { otomat } from '@otomat/middleware';
export const GET = otomat.next(
{ price: '$0.002', asset: 'USDC', payTo: 'YOUR_SOLANA_ADDRESS' },
async () => Response.json({ report: buildReport() }),
);import { Hono } from 'hono';
import { otomat } from '@otomat/middleware';
const app = new Hono();
app.get(
'/report',
otomat.hono({ price: '$0.002', asset: 'USDC', payTo: 'YOUR_SOLANA_ADDRESS' }),
(c) => c.json({ report: buildReport() }),
);Facilitator API
The facilitator is the stateless verifier and settler. It exposes three endpoints.
/verifyValidate a PAYMENT-SIGNATURE against the requirements without moving funds./settleSubmit and confirm the payment on Solana, then return the settlement./supportedList the (scheme, network) pairs the facilitator settles.curl https://facilitator.otomat.fun/supported
# { "kinds": [ { "scheme": "exact", "network": "solana:mainnet" } ] }On-chain program
Settlement is enforced by the otomat_rail Anchor program. The exact scheme commits a receipt per call; channels escrow a deposit and settle a run of off-chain checks in one transaction.
FwFC1nDo5r224uXDeTMc2X8FhXuiz9CqBF7tg3trEVhN