Skip to main content
The standalone service example is the most comprehensive Key0 deployment pattern. It runs Key0 as its own microservice, decoupled from your backend, handling the full payment lifecycle: agent discovery, challenge issuance, on-chain verification, token delivery, payment notifications, and automatic refunds. This is the recommended architecture for production deployments where you want to isolate payment infrastructure from your application logic.

Architecture

Flow:
  1. Agent discovers the Key0 service via /.well-known/agent.json and requests access via A2A
  2. Key0 issues an x402 challenge; agent pays USDC on Base
  3. Key0 verifies the on-chain transfer and notifies your backend
  4. Key0 issues a JWT (locally or via your backend) and returns it to the agent
  5. Agent uses the JWT to call your protected API directly

What This Example Demonstrates


Configuration Reference

Core Settings

Backend Communication

Storage

Gas Wallet and Refunds

Agent Card Metadata


Code Walkthrough

Storage Backend Selection

The service selects its storage layer at startup based on a single environment variable. Both backends implement the same IChallengeStore and ISeenTxStore interfaces, so the rest of the code is storage-agnostic.
Redis uses atomic Lua scripts for state transitions and SET NX for double-spend prevention. Best for low-latency, single-region deployments.
Regardless of which storage backend you choose, the BullMQ refund cron always requires a Redis connection. If you use Postgres for storage, set REDIS_URL or BULLMQ_REDIS_URL separately for the job queue.

Auth Strategy Configuration

When Key0 communicates with your backend (to notify payments or request token issuance), it authenticates using one of three strategies:
Never use noAuth() in production. Use shared-secret as a minimum, or jwt for environments where services communicate across network boundaries.

Token Issuance Modes

After payment verification, Key0 needs to issue a credential. The standalone service supports two modes:
Key0 signs a JWT locally using AccessTokenIssuer. The token includes the challenge ID, resource ID, plan ID, and transaction hash:
Your backend validates the token using the same KEY0_ACCESS_TOKEN_SECRET. Best when Key0 and your backend share a secret.

Plan Catalog

The service defines a multi-tier pricing structure that agents discover via the A2A agent card:
Agents select a plan when requesting access. Key0 issues a challenge for the corresponding unitAmount, and the entire payment/verification/delivery flow proceeds automatically.

Payment Notifications

After a payment is verified and a credential is issued, Key0 notifies your backend so you can activate the subscription, update billing records, or trigger downstream workflows:
The payment notification is fire-and-forget. If the backend is unreachable, the error is logged but the agent still receives their token. Design your backend to handle idempotent replays if needed.

Refund Cron Setup

The BullMQ-based refund cron automatically processes refunds for challenges that reached the PAID state but failed delivery. It runs on a configurable interval and only processes challenges older than a grace period:
The refund processor transitions challenges through PAID -> REFUND_PENDING -> REFUNDED (or REFUND_FAILED), sending USDC back to the payer on-chain.
The refund cron requires KEY0_WALLET_PRIVATE_KEY to sign refund transactions. Without it, the cron starts but skips processing. Never commit private keys to source control — use a secrets manager.

Running the Example

1

Start infrastructure

You need Redis running (required for BullMQ, and optionally for storage). If using Postgres for storage, start that as well.
2

Configure environment variables

Create a .env file in the examples/standalone-service directory:
3

Install dependencies

4

Start the service

You should see:

Endpoints

Once running, the service exposes:

Testing

Verify the agent card

Check health

Expected response:

Run a full payment flow

Point an agent at this service to run a complete discovery-to-payment-to-access flow.

Test MCP discovery


Production Checklist

Before deploying to production:
  • Set KEY0_NETWORK=mainnet
  • Use a strong, randomly generated KEY0_ACCESS_TOKEN_SECRET (64+ characters)
  • Set BACKEND_AUTH_STRATEGY to shared-secret or jwt
  • Configure KEY0_PUBLIC_URL to your actual domain
  • Set KEY0_WALLET_PRIVATE_KEY to enable automatic refunds
  • Use a managed Redis (e.g., Upstash, ElastiCache) or managed Postgres
  • Run behind a reverse proxy (nginx, Cloudflare) with TLS
  • Set KEY0_WALLET_ADDRESS to a dedicated payment-receiving wallet

Source code

examples/standalone-service/server.ts