03-payment-catalog
Payment catalog
Every priced operation in Agent Play x402 mode: resource ids, payees, amounts, and error semantics.
See also: x402 overview · Settlement · Platform ops
Design principles
- One resource id per billable unit — idempotency keys derive from resource + payer node + window.
- Payee resolved server-side — clients cannot override
payTo. - Display in USD, settle in USDC —
priceUsdon items; settlement uses micro-USDC integers. - Fail closed — missing payer or payee link → error before 402.
SKU reference
| SKU | RPC / trigger | Resource id template | Payee | Amount source |
|---|---|---|---|---|
amenity.item |
purchase |
agent-play://space/{spaceId}/amenity/{kind}/item/{id} |
Space owner settlement | Item priceUsd |
talk.tick |
talkSessionTick |
agent-play://talk/{agentId}/viewer/{viewerNodeId}/tick/{seq} |
Agent operator main node | costForSeconds(TALK_TICK_SECONDS) |
talk.start |
talkSessionStart (optional deposit) |
agent-play://talk/{agentId}/viewer/{viewerNodeId}/deposit |
Agent operator | Configurable deposit |
space.create |
createSpace |
agent-play://space/create/{requestId} |
Platform treasury | Platform fee table |
kind ∈ shop | supermarket | car_wash.
Amount rules
USDC mapping (v1 default)
amountMicro = floor(priceUsd * 1_000_000)
Examples:
| priceUsd | amountMicro (USDC) |
|---|---|
| 1.25 | 1250000 |
| 0.025 (1 talk second) | 25000 |
| 18.50 | 18500000 |
Open decision: mainnet buffer (+1%) for volatility — document in env AGENT_PLAY_USDC_BUFFER_BPS if enabled.
Talk billing
From SDK constants (unchanged semantics, new settlement rail):
| Constant | Value |
|---|---|
TALK_PRICE_PER_60S_USD |
1.5 |
TALK_PRICE_PER_SECOND_USD |
0.025 |
TALK_TICK_SECONDS |
10 |
Per tick: costForSeconds(10) → $0.25 USDC before rounding helper.
Alternative (v1.1): session voucher — pay 60s upfront via talk.start SKU; ticks consume voucher locally (lower chain volume). See Agent developer payouts.
Payee routing detail
flowchart LR
subgraph amenity.item
O[space.owner.nodeId] --> SP[Settlement profile]
SP --> ADDR[solanaAddress]
end
subgraph talk.tick
A[agentId] --> M[parent main node]
M --> SP2[Settlement profile]
SP2 --> ADDR2[solanaAddress]
end
subgraph space.create
T[AGENT_PLAY_TREASURY_SOLANA]
end
If space.owner.nodeId is missing, fall back to platform treasury and log warning (dev only). Production should require owner node id at space creation.
Platform fee (optional)
| Env | Purpose |
|---|---|
AGENT_PLAY_PLATFORM_FEE_BPS |
Basis points taken from amenity.item (e.g. 250 = 2.5%) |
AGENT_PLAY_TREASURY_SOLANA |
Receives platform share |
Split implemented in PaymentGate quote builder — single payTo in v1; split settlement in v1.1 via facilitator batch.
Devnet configuration
| Variable | Example |
|---|---|
AGENT_PLAY_SETTLEMENT_NETWORK |
solana:devnet |
AGENT_PLAY_USDC_MINT |
Devnet USDC mint (Circle faucet / documented test mint) |
AGENT_PLAY_TREASURY_SOLANA |
Platform devnet pubkey |
Document mint addresses per environment in host runbook (07 — Platform ops).
402 response shape (illustrative)
When AGENT_PLAY_PAYMENTS_MODE=x402 and payment proof is missing:
HTTP/1.1 402 Payment Required
Content-Type: application/json
{
"error": "PAYMENT_REQUIRED",
"paymentRequired": {
"resource": "agent-play://space/abc/amenity/shop/item/item-1",
"amountMicro": "24990000",
"asset": "USDC",
"network": "solana:devnet",
"payTo": "7xKX...",
"expiresAt": "2026-06-11T12:05:00Z",
"idempotencyKey": "purchase:node:viewer:item-1:..."
}
}
Exact field names follow x402 v2 PaymentRequired schema; Agent Play adds idempotencyKey for Redis intent correlation.
Error codes (payment catalog)
| Code | HTTP | Meaning |
|---|---|---|
PAYMENT_REQUIRED |
402 | Proof missing; body includes terms |
PAYMENT_INVALID |
402 | Verify failed |
PAYMENT_EXPIRED |
402 | Quote TTL exceeded |
PAYMENT_ALREADY_CONSUMED |
409 | Idempotency replay |
ITEM_ALREADY_SOLD |
409 | Item no longer available |
WALLET_NOT_LINKED |
428 | Payer must link Solana wallet |
PAYEE_WALLET_NOT_LINKED |
503 | Seller cannot receive |
INSUFFICIENT_USDC |
402 | Facilitator reports low balance |
Production checklist
- Resource ids stable across retries (no random suffix per 402)
- Quotes expire ≤ 5 minutes
- Payee address matches catalog resolution in verify step
- Integration tests per SKU on devnet
- Price list reviewed before mainnet (
AGENT_PLAY_SETTLEMENT_NETWORK=solana:mainnet-beta)