Config File
The bankr.x402.json file defines your x402 Cloud services — pricing, methods, and schemas for agent discovery.
Created automatically by bankr x402 init and updated by bankr x402 add and bankr x402 configure.
Example
{
"network": "base",
"currency": "USDC",
"services": {
"weather": {
"description": "Real-time weather data for any city",
"price": "0.001",
"methods": ["GET"],
"category": "data",
"tags": ["weather", "forecast"],
"schema": {
"input": {
"type": "object",
"properties": {
"city": { "type": "string", "description": "City name" },
"units": { "type": "string", "description": "Temperature units", "enum": ["celsius", "fahrenheit"] }
},
"required": ["city"]
},
"output": {
"type": "object",
"properties": {
"temperature": { "type": "number", "description": "Current temperature" },
"conditions": { "type": "string", "description": "Weather conditions" }
}
}
}
},
"sentiment": {
"description": "AI-powered sentiment analysis",
"price": "0.01",
"methods": ["POST"],
"schema": {
"input": {
"type": "object",
"properties": {
"text": { "type": "string", "description": "Text to analyze" }
},
"required": ["text"]
},
"output": {
"type": "object",
"properties": {
"sentiment": { "type": "string", "description": "positive, negative, or neutral" },
"score": { "type": "number", "description": "Sentiment score from -1 to 1" },
"confidence": { "type": "number", "description": "Confidence level 0-1" }
}
}
}
}
}
}
Top-Level Fields
| Field | Default | Description |
|---|---|---|
payTo | Your Bankr wallet | Wallet address to receive payments |
network | "base" | Blockchain network |
currency | "USDC" | Token symbol (display only) |
tokenAddress | null (USDC) | ERC-20 contract address (only USDC is supported currently) |
Service Fields
Each key in services is the service name. Names must be alphanumeric, hyphens, or underscores — max 47 characters.
| Field | Default | Description |
|---|---|---|
price | "0.001" | Price per request in the configured token (minimum: 0.000001) |
description | — | Human-readable description shown to agents during discovery |
methods | ["GET", "POST"] | Accepted HTTP methods |
currency | Inherits top-level | Token symbol (display only) |
network | Inherits top-level | Blockchain network |
tokenAddress | Inherits top-level | ERC-20 contract address |
category | — | Category for discovery |
tags | [] | Tags for discovery search |
paymentScheme | "exact" | Payment scheme: "exact" (fixed price) or "upto" (usage-based, settle actual cost) |
schema | — | Input/output schema for agent discovery (see below) |
Service-level currency, network, and tokenAddress override the top-level defaults.
Payment Schemes
The paymentScheme field controls how payments are authorized and settled.
Exact (default)
The client pays exactly the listed price for every request. This is the simplest model — one price, one payment.
{
"services": {
"weather": {
"price": "0.001",
"paymentScheme": "exact"
}
}
}
Upto (usage-based)
The client authorizes up to the listed price, but your handler reports the actual cost via the X-402-Settle-Amount response header. Only the actual amount is settled on-chain.
This is ideal for endpoints where cost varies per request — for example, processing a variable number of items, or calling an LLM where token count differs.
{
"services": {
"batch-process": {
"price": "0.01",
"paymentScheme": "upto",
"description": "Process 1-20 items at $0.0005 each",
"methods": ["GET"]
}
}
}
How it works:
- The 402 response advertises the
priceas the maximum cost - The caller authorizes up to that amount via Permit2
- Your handler runs and sets
X-402-Settle-Amountto the actual cost (in atomic USDC — 6 decimals, e.g."500"= $0.0005) - The router settles only the actual amount on-chain
// In your handler — set the actual cost
return new Response(JSON.stringify(result), {
headers: {
"Content-Type": "application/json",
"X-402-Settle-Amount": String(actualCostAtomicUsdc),
},
});
If your handler doesn't set X-402-Settle-Amount, the full price is settled as a fallback.
The upto scheme uses Permit2 for payment authorization. Callers using the Bankr API or CLI have this handled automatically. If you're building a custom x402 client, the caller's wallet needs a one-time ERC-20 approval of USDC to the Permit2 contract (0x000000000022D473030F116dDEE9F6B43aC78BA3).
Schema
The schema field describes your service's inputs and outputs using JSON Schema so AI agents can discover and call your endpoint automatically.
The schema has two fields:
| Field | Description |
|---|---|
input | JSON Schema object describing request parameters. For GET services, properties map to query params. For POST services, properties map to JSON body fields. |
output | JSON Schema object describing the response shape. |
Each schema is a JSON Schema object with properties, optional required array, and optional description on each property.
Supported JSON Schema properties
| Property | Description |
|---|---|
type | "string", "number", "integer", "boolean", "array", "object" |
description | Human-readable description of the field |
required | Array of required property names (on the parent object) |
enum | Array of allowed values |
items | Schema for array items |
properties | Nested object properties |
GET service
For GET services, input properties are sent as query parameters:
{
"schema": {
"input": {
"type": "object",
"properties": {
"city": { "type": "string", "description": "City name" },
"units": { "type": "string", "description": "Temperature units", "enum": ["celsius", "fahrenheit"] }
},
"required": ["city"]
},
"output": {
"type": "object",
"properties": {
"temperature": { "type": "number" },
"conditions": { "type": "string" }
}
}
}
}
Callers send: GET /weather?city=London&units=celsius
POST service
For POST services, input properties are sent as a JSON body:
{
"schema": {
"input": {
"type": "object",
"properties": {
"text": { "type": "string", "description": "Text to analyze" },
"language": { "type": "string", "description": "ISO language code" }
},
"required": ["text"]
},
"output": {
"type": "object",
"properties": {
"sentiment": { "type": "string" },
"score": { "type": "number" }
}
}
}
}
Callers send: POST /sentiment with body {"text": "Hello world", "language": "en"}
Array and nested types
{
"schema": {
"input": {
"type": "object",
"properties": {
"symbols": {
"type": "array",
"items": { "type": "string" },
"description": "List of token symbols"
}
},
"required": ["symbols"]
},
"output": {
"type": "object",
"properties": {
"prices": {
"type": "array",
"items": {
"type": "object",
"properties": {
"symbol": { "type": "string" },
"price": { "type": "number" }
}
}
}
}
}
}
}
The legacy queryParams, body, and input schema fields are still accepted for existing endpoints. New services should use the JSON Schema input/output format described above.