Automation
Resource URL
GET /api/resources/<intent-id>
- 402 while open: JSON includes
x402Version,accepts[], andextra.settlement=umbra-receiver-claimable-utxoso clients route work to the Umbra SDK instead of treatingpayToas a plain public SPL send. - 200 after the intent is marked settled: JSON includes
content(umbra-pay-links.unlocked) as the unlocked machine payload, plussettledAtand receipt fields.
Example 200 body (shape)
Abbreviated; see OpenAPI for full fields. settledAt is written on first confirm; older rows may fall back to createdAt in the resource response only when needed.
{
"unlocked": true,
"intentId": "…",
"label": "Invoice / product name",
"settledAt": "2026-04-24T12:00:00.000Z",
"amountAtomic": "1000000",
"mint": "EPjF…",
"message": "Payment recorded. This JSON is the unlocked resource…",
"content": {
"type": "umbra-pay-links.unlocked",
"version": 1,
"title": "Invoice / product name",
"body": "Access is granted for this intent…",
"receipt": {
"settlement": "umbra-receiver-claimable-utxo",
"amountAtomic": "1000000",
"mint": "EPjF…"
}
}
}Headless payer
npm run agent:pay runs scripts/agent-pay.mjs: load a keypair, read 402, run the same Umbra + UTXO path as the browser, POST confirm, re-fetch the resource. Environment variables are in README.md and .env.example.
Umbra SDK parity (browser vs agent)
Both paths call getUmbraClient, optional registration, then getPublicBalanceToReceiverClaimableUtxoCreatorFunction with the same browser ZK prover package. The only deliberate difference is the signer: Wallet Standard in React vs private key bytes in Node. Same settlement path, not a server-side fake payment.
OpenAPI
Machine-readable contract: /openapi.json (OpenAPI 3.1). Import into Postman, Insomnia, or codegen tools so your platform can treat intents as first-class resources.
REST surface
Routes are rate-limited per client IP (see README.md). POST /api/intents validates Solana addresses with @solana/kit address().
- POST /api/intents
- Create intent; returns pay URL and resource URL. Optional
webhookUrlfor a server POST on first settlement. - GET /api/intents/<id>
- Intent fields for the checkout UI.
- POST /api/intents/<id>/confirm
- Mark settled with an array of transaction signatures. Idempotent if signatures match an already-settled intent. Optional RPC verification when
REQUIRE_ONCHAIN_CONFIRM_FOR_SETTLEis enabled. - GET /api/resources/<id>
- 402 paywall or 200 when paid.