Skip to main content
Protocol

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:

POST /api/registries $5.00

Create a new token-curated registry

POST /api/models $1.00

List a new model in the catalog

POST /api/registries/:id/challenge $2.00

Challenge an existing listing

Challenge & Proof Types

PaymentChallenge (402 response body)

PaymentChallenge
{
  "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)

X-Payment-Proof header
// JSON-encoded in the X-Payment-Proof header
{
  "challenge_id": "abc123",
  "tx_hash": "0x...",
  "chain": "base",
  "payer": "0x..."
}

Complete Example

create-registry.sh
# 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.