How it works
One GET, one 402 challenge, one signed payment, one receipt. What travels over the wire at each step.
An agent buys a Swop product with two requests to the same URL. The first asks the price. The second pays it.
The agent requests the product
GET /api/v5/x402/store/travis.swop.id/buy/6a7f63002e22feb6ad48dd7c HTTP/1.1
Host: apps.apiswop.co
Accept: application/jsonAgents usually find this URL in a seller's store listing, or by following a shared product link (https://swopme.app/p/<swop.id>/<productId>). Shared links serve a page to browsers and redirect anything that doesn't ask for HTML (307) to the buy URL.
Swop answers 402 Payment Required
The response states exactly what to pay. This is a real response from production (the extensions block is shortened):
{
"x402Version": 2,
"error": "PAYMENT-SIGNATURE header is required",
"resource": {
"url": "https://apps.apiswop.co/api/v5/x402/store/travis.swop.id/buy/6a7f63002e22feb6ad48dd7c",
"description": "Cabal Card from travis.swop.id on Swop. … Digital item, delivered instantly. …",
"mimeType": "application/json"
},
"accepts": [
{
"scheme": "exact",
"network": "eip155:8453",
"amount": "1000000",
"maxAmountRequired": "1000000",
"resource": "https://apps.apiswop.co/api/v5/x402/store/travis.swop.id/buy/6a7f63002e22feb6ad48dd7c",
"description": "Cabal Card from travis.swop.id on Swop",
"mimeType": "application/json",
"payTo": "0xf3F6A4d1C0a3eF76951a96De4c20365b55EE0f32",
"maxTimeoutSeconds": 300,
"asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
"extra": { "name": "USD Coin", "version": "2" }
}
],
"extensions": { "bazaar": { "…": "discovery metadata" } }
}How to read it:
network: "eip155:8453"is Base mainnet, written as a CAIP-2 chain id.assetis the USDC contract on Base.amountis in USDC's smallest unit (6 decimals), so1000000is 1.00 USDC.payTois where the money goes: the seller's wallet for digital goods, or Swop's escrow wallet for physical goods.- The same object is also sent base64-encoded in the
PAYMENT-REQUIREDresponse header. x402 v2 clients read the header; v1 clients read the body.
The agent signs a USDC authorization
The exact scheme on Base uses EIP-3009 transferWithAuthorization: the buyer signs a message that lets exactly amount USDC move from their wallet to payTo, valid for a short window. Nothing is sent on-chain yet, and no gas is needed from the buyer. See Pay from an agent for the code.
The agent retries with the payment attached
GET /api/v5/x402/store/travis.swop.id/buy/6a7f63002e22feb6ad48dd7c HTTP/1.1
Host: apps.apiswop.co
Accept: application/json
PAYMENT-SIGNATURE: eyJ4NDAyVmVyc2lvbiI6Miwic2NoZW1lIjoiZXhhY3QiLCJuZXR3b3JrIjoi…PAYMENT-SIGNATURE is the x402 v2 header. Swop also accepts the v1 name, X-PAYMENT, with the same value.
Swop verifies, settles and returns a receipt
Swop sends the payment to an x402 facilitator, which checks the signature and amount (verify) and then submits the transfer on-chain (settle). Once it settles, Swop records the order, updates inventory, notifies the seller and returns:
{
"state": "success",
"data": {
"status": "paid",
"orderId": "6a8b0c1d2e3f405162738495",
"receipt": {
"handle": "travis.swop.id",
"product": "Cabal Card",
"selectedOptions": {},
"amountUsd": 1,
"currency": "USDC",
"network": "base",
"payTo": "0xf3F6A4d1C0a3eF76951a96De4c20365b55EE0f32",
"transaction": "0x…"
}
}
}The settlement result is also in the PAYMENT-RESPONSE header (and X-PAYMENT-RESPONSE for v1 clients), base64-encoded.
Physical goods and product options
Some products need more than money before they can be sold:
- Options. If the seller defined option groups (Size, Colour), the agent must pick one value from each.
- Shipping. Physical products need
name,email,line1,city,postalCodeandcountry.
Both travel in one header, X-ORDER: base64-encoded JSON, sent with the payment. The listing's variants and requiredOrderFields tell an agent what to collect from its user first.
{
"Size": "L",
"name": "Ada Lovelace",
"email": "ada@example.com",
"line1": "1 Market St",
"city": "San Francisco",
"postalCode": "94105",
"country": "US"
}If anything is missing, Swop answers 400 (not 402) with a missing array and a how hint, before any money is discussed.
For physical goods, payment goes to escrow and is released to the seller once delivery is confirmed. The paying agent can confirm receipt itself by proving it controls the paying wallet:
GET /api/v5/x402/orders/<orderId>/confirm-receiptreturns a one-timemessage(valid 10 minutes).- Sign it with
personal_signfrom the wallet that paid. POST /api/v5/x402/orders/<orderId>/confirm-receiptwith{"signature": "0x…"}.
Confirmation opens once the seller has marked the order shipped.
Responses you should handle
| Status | When | What to do |
|---|---|---|
402 | No payment header, or verification/settlement failed (error says why) | Pay, or fix the payment and retry |
200 | Paid. data.duplicate: true means this exact on-chain payment was already used | Store orderId and transaction |
400 | Options or shipping details missing or invalid, or the product id is malformed | Collect what's in missing and send X-ORDER |
404 | Unknown swop.id or product, or the product is archived | Re-read the store listing |
409 | code: "SOLD_OUT" | Don't pay. Nothing was charged |
503 | The seller has no payout wallet for agent payments yet | Try another product or seller |
Retrying a request that already settled is safe: Swop matches the on-chain transaction and returns the original order instead of creating a second one.