Quickstart
Go from npx to an AI agent completing a sandbox checkout in about five minutes — one scaffold command, three run commands, four scenarios, zero install.
The fastest path is the scaffolder: it writes a runnable merchant + buyer agent that complete a sandbox checkout end to end on the offline mock rail — no chain, no wallet, no real money. The only prerequisite is Node ≥ 22.6.
The 5-minute path
Scaffold a project
npx @veto-protocol/create-checkout my-shop --template quickstartThis writes a small project — and nothing else runs yet, so it's safe:
merchant.ts— a digital-goods shop standing upcreateCheckout(...)on thenode:httpadapter, test mode / mock rail, with a 3-item catalog and aBALANCED()policy.buyer.ts— a buyer agent that discovers the manifest and runs four canonical scenarios.scripts/setup-keys.ts— mints the test Veto issuer keypair the demo trusts.
The scaffolder is itself zero-dependency — it only writes files and prints the run command
last. quickstart is the only template today.
Mint the test issuer keypair
cd my-shop
node --experimental-strip-types scripts/setup-keys.tsThis writes a test veto issuer keypair into keys/ (gitignored). The merchant trusts the
public JWKS; the buyer agent signs mandates with the matching private seed — exactly
mirroring reality, where a merchant only ever holds the public key.
Start the merchant
node --experimental-strip-types merchant.ts &The shop comes up on http://localhost:8787 in test mode / mock rail and prints its
discovery URL (/.well-known/agentic-checkout.json) and receipt JWKS URL
(/.well-known/jwks.json).
Run the buyer agent
node --experimental-strip-types buyer.tsThe agent is given only the merchant origin. It discovers the manifest and follows the self-describing responses through four scenarios:
| # | Scenario | Expected |
|---|---|---|
| a | Small purchase ($5), no mandate | accepted on reputation alone |
| b | Large purchase ($40), no mandate | hold — MANDATE_REQUIRED_HOLD |
| c | Large purchase ($120) with a minted veto mandate | accepted (premium) + verified receipt |
| d | Replay the same mandate | rejected — MANDATE_REPLAY |
Expect the final line: Summary: 4/4 scenarios passed.
That is a real AI agent completing a sandbox checkout — discovery, the acceptance gate, signed mutual receipts, and replay defense — with no chain and no install. The rest of this page builds the same thing from scratch so you understand every moving part.
From scratch
This is the whole integration by hand: one config object, one server, and an order settled end to end on the mock rail.
1. Install
npm install @veto-protocol/checkoutThe SDK has zero runtime dependencies and targets Node ≥ 22.6. The examples below
run as-is with node --experimental-strip-types server.ts — no build step.
2. Stand up a checkout
createCheckout(config) returns a handle whose methods map 1:1 to the wire endpoints.
createNodeServer mounts them on node:http.
import { createCheckout, BALANCED } from '@veto-protocol/checkout';
import { createNodeServer } from '@veto-protocol/checkout/http';
const checkout = createCheckout({
merchant: { id: 'acme', name: 'Acme Corp', domain: 'shop.acme.example' },
catalog: [
{
sku: 'widget',
name: 'Blue Widget',
price: { amount: '12.50', currency: 'USD' },
available: true,
},
],
// Non-custodial: YOUR receiving address. (mock shown; add x402 for real settlement.)
receiving: { x402: { chain: 'base', address: '0xYourAddress', asset: 'USDC' } },
policy: BALANCED(), // STRICT() | BALANCED() | OPEN(), then tweak fields
// rails defaults to [x402, mock] when omitted.
});
createNodeServer(checkout).listen(8080);
console.log('Veto Checkout listening on :8080');That is a fully self-describing agentic checkout on port 8080.
3. Discover, create, settle
An agent only needs the manifest URL; every response carries the literal next call.
# 1) Discover — the single bootstrap URL
curl http://localhost:8080/.well-known/agentic-checkout.json
# 2) Create a session (returns a self-describing `payment_required`)
curl -X POST http://localhost:8080/agent/checkout \
-H 'content-type: application/json' \
-d '{
"agent_id": "11111111-1111-1111-1111-111111111111",
"items": [{ "sku": "widget", "qty": 1 }],
"rail": "mock"
}'
# 3) Settle — run the acceptance gate, then capture
curl -X POST http://localhost:8080/agent/checkout/<SESSION_ID>/settle \
-H 'content-type: application/json' \
-d '{ "payment": { "mock": true } }'You can also drive the handle directly, without any HTTP:
const created = await checkout.createSession({
agent_id: '11111111-1111-1111-1111-111111111111',
items: [{ sku: 'widget', qty: 1 }],
rail: 'mock',
});
const settled = await checkout.settle(created.body.session_id, {
payment: { mock: true },
});
console.log(settled.status, settled.body);
// → 'accepted' { status: 'accepted', order_id, receipt, fulfillment }4. The result
On allow, the settle returns 200 with an order_id, a signed
receipt, and your fulfillment:
{
"status": "accepted",
"order_id": "…",
"receipt": "<compact JWS merchant receipt>",
"fulfillment": { "/* merchant-defined */": "download url, license key, …" }
}The receipt is an Ed25519-signed compact JWS. Anyone can verify it offline.
Already on a framework?
The SDK ships adapters for node:http, Express, Hono, and Next.js. See
SDK → HTTP adapters.
Set up Veto end-to-end (hosted)
Zero to a live agent purchase on the hosted platform — sign in, mint keys, create a merchant, add a product, set your receiving address, publish, connect your site, and watch an AI agent buy it over x402.
Test mode
Run the entire acceptance gate offline with the mock rail — no chain, no network, no install — so you can test policy decisions deterministically.