x402 quickstart
Build an AI agent that pays as it goes — over the x402 HTTP 402 payment protocol — and have the settlement happen privately through Umbra without changing your agent code.
What you get
- A managed x402 facilitator that verifies payment headers and settles on-chain against the merchant’s Solana account.
- Private settlement through Umbra’s shielded layer — payer wallet, merchant address, and amount stay off the public ledger.
- An attestation for every settled request, fetchable from the merchant dashboard or the SDK for receipts, accounting, and refund reconciliation.
Mental model
The x402 standard adds two HTTP semantics to any paid resource:
| HTTP | What it means |
|---|---|
402 Payment Required | Server is asking the client to pay before serving the resource. The response advertises accepted assets and the merchant’s settlement target. |
X-PAYMENT request header | Client retries the request carrying a signed payment commitment. The facilitator verifies + settles, and the server proceeds with the original request. |
Your agent code doesn’t need to know anything about Solana, Umbra, or shielded UTXOs — the SDK adapter handles the round trip, and NinjaPay handles the rest.
Minimal agent client
import { x402Client } from '@ninjapay/sdk/x402';
const client = x402Client({
payerPrivateKey: process.env.AGENT_KEYPAIR!,
rpcUrl: 'https://api.devnet.solana.com',
facilitator: 'https://facilitator.ninjapay.finance',
});
// First call returns 402 with a payment requirement.
// The adapter signs an X-PAYMENT header, retries, and returns the
// final response transparently.
const res = await client.fetch('https://api.example.com/premium-data');
const data = await res.json();The reference implementation in apps/x402-demo-agent/ shows the
full flow end-to-end, including attestation lookup and error handling
for payment_invalid, quote_expired, and merchant_not_registered.
Server-side: monetize an endpoint
If you’re a service operator wanting to charge per request, point the facilitator at your merchant account and gate the endpoint:
import { x402Gate } from '@ninjapay/sdk/x402';
const paid = x402Gate({
apiKey: process.env.NINJAPAY_SECRET_KEY!,
price: { amount: 100, currency: 'USDC' }, // $0.01
});
app.get('/premium-data', paid, async (req, res) => {
res.json({ answer: 42, attestationId: req.x402.attestationId });
});The middleware emits the 402 challenge on unauthenticated requests,
verifies the X-PAYMENT header on retries, and attaches the
attestationId to the request for your own logging.
Attestations + reconciliation
Every settled request produces a X402Attestation row that the
merchant can list, retrieve, and link to receipts:
const attestation = await ninja.x402.attestations.retrieve('att_…');
attestation.amount; // 100 (USDC base units)
attestation.endpointId; // 'x402_endpoint_…'
attestation.routerTxSig; // Solana tx — confirmable via the public scanner
attestation.umbraDepositId; // shielded settlement referenceThe dashboard surfaces the attestation timeline alongside the
endpoint’s revenue chart at /dashboard/agent-commerce.
Adapters
Drop-in adapters for the popular agent frameworks:
- MCP servers —
@ninjapay/sdk/x402/mcp - LangChain tools —
@ninjapay/sdk/x402/langchain - Vercel AI SDK —
@ninjapay/sdk/x402/ai
Each adapter signs and retries on 402 transparently; your tool code
stays free of payment plumbing.
Errors worth handling
| Error code | Meaning |
|---|---|
payment_invalid | The X-PAYMENT header didn’t verify — bad signature or stale quote. |
quote_expired | The price quote referenced has elapsed. Refetch the 402 and retry. |
merchant_not_registered | The merchant hasn’t completed Umbra registration for private settlement. The facilitator falls back to public settlement when the merchant has opted in. |
cross_mint_rate_limited | The payer is exceeding the per-payer cross-mint rate cap. Back off and retry. |
Next steps
- Spin up the reference agent:
pnpm -F x402-demo-agent dev - Read the x402 spec and Coinbase’s referenceÂ
- Wire up an endpoint in your own service with
x402Gateand watch attestations roll into/dashboard/agent-commerce