A production-ready Key0 standalone service with configurable storage, auth strategies, token modes, gas wallet support, and automatic refunds.
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.
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
Postgres
Copy
Ask AI
const redis = new Redis(process.env.REDIS_URL!);store = new RedisChallengeStore({ redis, challengeTTLSeconds: 900 });seenTxStore = new RedisSeenTxStore({ redis });
Redis uses atomic Lua scripts for state transitions and SET NX for double-spend prevention. Best for low-latency, single-region deployments.
Copy
Ask AI
const postgres = (await import("postgres")).default;const sql = postgres(process.env.DATABASE_URL!);store = new PostgresChallengeStore({ sql });seenTxStore = new PostgresSeenTxStore({ sql });
Postgres uses row-level locking for atomicity. Best when you already run Postgres and want a single data store.
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.
Agents select a plan when requesting access. Key0 issues a challenge for the corresponding unitAmount, and the entire payment/verification/delivery flow proceeds automatically.
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.
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.