Agent
Server
Facilitator
Account
The 402 response
HTTP/1.1 402 Payment Required
{
"x402Version": 1,
"accepts": [{
"scheme": "otsukai",
"network": "eip155:4663",
"asset": "0x5fc5360D0400a0Fd4f2af552ADD042D716F1d168",
"maxAmountRequired": "10000",
"payTo": "0x…",
"resource": "https://otsukai.dev/api/paid/quote?symbol=NVDA&usd=100",
"description": "Executable price of a tokenized stock against USDG…",
"mimeType": "application/json",
"maxTimeoutSeconds": 60
}]
}The signed payment
The client checks the price against its own maximum, then signs this EIP-712 struct with the agent key. The domain is { name: "Otsukai", version: "1", chainId: 4663, verifyingContract: <account> }, so a signature is valid for one account only.
Payment(address payee, uint256 amount, bytes32 resource, bytes32 nonce, uint64 validBefore)
resource = keccak256(utf8(accepts[0].resource))
nonce = 32 random bytes (calls can run in parallel)
validBefore = now + 60 sIt retries the request with X-PAYMENT: base64({ scheme, network, account, payment, sig }).
Settlement
The server asks the facilitator to verify (an eth_call of account.pay) and to settle (the real transaction, then the receipt). Only then does it answer, with X-PAYMENT-RESPONSE: base64({ txHash, receiptId }). A refused payment gets a new 402 with the contract's reason in error.
Clients
Two single files, served from this site, both built on viem:
- otsukai.mjs:
otsukaiFetch(url, init),balance(),left(),receipts(). SetOTSUKAI_MAXto change the local price ceiling (default $0.05). - otsukai-mcp.mjs: a stdio MCP server with
otsukai_fetch,otsukai_leftandotsukai_receipts, for Claude Desktop and Claude Code.
$ npm i viem && curl -O https://otsukai.dev/sdk/otsukai.mjs$ OTSUKAI_KEY=0x… OTSUKAI_ACCOUNT=0x… node quote.mjs# 402 → signed $0.01 → settled< 200 { symbol: 'NVDA', usdIn: 100, feeTier: 500, … }