docs
Get startedTroubleshootingPaymentsWebhooksAgent paymentsSwop MCPOviIdentity (swop.id)SwivyRPC (preview)API reference

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/json

Agents 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.
  • asset is the USDC contract on Base. amount is in USDC's smallest unit (6 decimals), so 1000000 is 1.00 USDC.
  • payTo is 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-REQUIRED response 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, postalCode and country.

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.

Decoded X-ORDER
{
  "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:

  1. GET /api/v5/x402/orders/<orderId>/confirm-receipt returns a one-time message (valid 10 minutes).
  2. Sign it with personal_sign from the wallet that paid.
  3. POST /api/v5/x402/orders/<orderId>/confirm-receipt with {"signature": "0x…"}.

Confirmation opens once the seller has marked the order shipped.

Responses you should handle

StatusWhenWhat to do
402No payment header, or verification/settlement failed (error says why)Pay, or fix the payment and retry
200Paid. data.duplicate: true means this exact on-chain payment was already usedStore orderId and transaction
400Options or shipping details missing or invalid, or the product id is malformedCollect what's in missing and send X-ORDER
404Unknown swop.id or product, or the product is archivedRe-read the store listing
409code: "SOLD_OUT"Don't pay. Nothing was charged
503The seller has no payout wallet for agent payments yetTry 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.

On this page