- Exposes a plan catalog at
GET /discover - Issues a USDC payment challenge at
POST /x402/access - Settles the on-chain payment and returns a signed JWT (
AccessGrant) - Protects your own routes with
validateAccessTokenmiddleware
New to Key0? Read Core Concepts first to understand terms like Plan, Challenge, AccessGrant, and EIP-3009.
Prerequisites
Before you begin, make sure you have:- Bun v1.3+ (or Node.js 18+)
- A wallet address on Base Sepolia (testnet) — get testnet USDC from faucet.circle.com (select Base Sepolia)
- Redis running locally or remotely (Postgres is also supported — see Storage)
Setup
Configure and mount
Create a
server.ts file. Key0 mounts as middleware on your existing server — it adds the agent card endpoint (/.well-known/agent.json), the plan discovery endpoint (/discover), the payment endpoint (/x402/access), and leaves your existing routes untouched.Set environment variables
Create a
.env file in your project root:.env
ACCESS_TOKEN_SECRET must be at least 32 characters. This secret is used to sign JWTs issued to agents after payment. Use a cryptographically random string.Run and test
Start your server:Test the agent card, plan discovery, and payment endpoints with curl:The agent card describes your service. The discovery endpoint lists all plans — use the
Agent card
Expected output
Browse plans (returns 200 with plan catalog)
Expected output
Request access (returns 402 challenge)
Expected output (HTTP 402)
planId values when requesting access. The access endpoint creates a PENDING challenge containing the payment amount, destination wallet, and chain ID. A client uses the challenge to sign an EIP-3009 authorization and submit payment. See Paying for Access for the full client walkthrough.Optional: Pay-Per-Request Routes
The quickstart above uses a subscription plan — the agent pays once and receives a signed JWT that grants access for the token’s lifetime. Key0 also supports pay-per-call routes, where each API call is paid for individually and no JWT is issued. The difference in configuration is adding a paid route to top-levelroutes:
validateAccessToken, you gate them with key0.payPerRequest() middleware. The middleware handles the entire payment cycle inline: it returns a 402 if no payment header is present, settles on-chain if it is, then calls next() so your route handler runs normally:
What’s next
Pay-Per-Request (Embedded)
Full example: weather and joke routes with inline payment settlement.
Integrations
Detailed integration guides for Express, Hono, Fastify, and MCP.
Storage Setup
Configure Redis or Postgres for challenge and transaction storage.
Building a Seller
End-to-end guide covering plans, storage, mainnet, and production deployment.

