x402 Payments
How KnowYourModel uses HTTP 402 Payment Required to gate write operations with on-chain USDC payments on Base L2.
What is x402?
x402 is a payment protocol built on the HTTP 402 Payment Required status code. When a client requests a payment-gated endpoint without a valid payment proof, the
server responds with a payment challenge that tells the
client exactly how much to pay, where to send it, and how to prove the payment.
Key principle: Payment verification happens on-chain. KnowYourModel verifies USDC transfers on Base L2 via JSON-RPC, ensuring payments are real, confirmed, and non-replayable.
Payment Flow
The x402 flow is a three-step challenge–pay–prove cycle:
1. Request → 402 Challenge
Client sends a request to a gated endpoint (e.g. POST /api/registries) without payment proof. The server responds with HTTP 402 and a PaymentChallenge in the body and X-Payment-Challenge header.
2. Pay on Base L2
Client sends a USDC transfer on Base L2 to the recipient address specified in the challenge, with the exact memo string. The amount must be ≥ the amount_usd in the
challenge.
3. Re-request with Proof
Client re-sends the original request with the X-Payment-Proof header containing the challenge ID, transaction hash, and payer address. The server verifies
on-chain and allows the action.
Payment-Gated Endpoints
The following write endpoints require x402 payment when the payment system is enabled:
/api/registries $5.00Create a new token-curated registry
/api/models $1.00List a new model in the catalog
/api/registries/:id/challenge $2.00Challenge an existing listing
Challenge & Proof Types
PaymentChallenge (402 response body)
{
"action": "create_registry",
"amount_usd": 5.00,
"currency": "USDC",
"chain": "base",
"recipient": "0x...",
"memo": "kym:create_registry:abc123",
"expires_at": "2026-02-22T12:15:00.000Z",
"challenge_id": "abc123"
}PaymentProof (X-Payment-Proof header)
// JSON-encoded in the X-Payment-Proof header
{
"challenge_id": "abc123",
"tx_hash": "0x...",
"chain": "base",
"payer": "0x..."
}Complete Example
# 1. Attempt to create a registry (returns 402 + challenge)
curl -s -X POST "https://knowyourmodel.ai/api/registries" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "name": "My Registry", "capability": "code-review" }'
# Response: 402 Payment Required
# { "error": "Payment required", "payment_required": { "challenge_id": "abc123", ... } }
# 2. Send USDC on Base L2 to the recipient address with the memo
# 3. Re-send with payment proof
curl -X POST "https://knowyourmodel.ai/api/registries" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-H 'X-Payment-Proof: {"challenge_id":"abc123","tx_hash":"0x...","chain":"base","payer":"0x..."}' \
-d '{ "name": "My Registry", "capability": "code-review" }'
# Response: 200 OK
# { "registry": { "id": "...", "name": "My Registry", ... } }Verification & Security
When a payment proof is submitted, the server performs the following verification steps:
- Challenge validation: Confirms the challenge ID exists, is still pending, and has not expired (15-minute TTL)
- Replay prevention: Checks that the transaction hash has not been used in a previous payment proof
- On-chain verification: Queries Base L2 via JSON-RPC to confirm the USDC transfer exists, is sufficiently confirmed, recipient matches the treasury address, and amount ≥ expected
- Immutable receipt: After verification, an immutable payment receipt is stored for the audit trail — the challenge is marked as consumed
Note: The x402 payment system is gated behind the X402_ENABLED feature flag. When disabled, all payment-gated
endpoints operate normally without payment. This allows staged rollout and testing.