Skip to content

How It Works ​

s402 adds a payment negotiation layer to standard HTTP. The flow is simple: a client requests a resource, the server says "pay me first", the client pays, and the server delivers.

The HTTP 402 Flow ​

Agent                          Server                     Facilitator
  |                              |                            |
  |-- GET /api/premium-data ---->|                            |
  |                              |                            |
  |<---- 402 Payment Required ---|                            |
  |      (payment-required hdr)  |                            |
  |                              |                            |
  |  [read requirements]         |                            |
  |  [choose scheme]             |                            |
  |  [build PTB, sign]           |                            |
  |                              |                            |
  |-- GET /api/premium-data ---->|                            |
  |   (x-payment header)        |--- verify + settle ------->|
  |                              |<--- { success, txDigest } -|
  |<---- 200 + data ------------|                            |
  |      (payment-response hdr)  |                            |

Step by Step ​

1. Client requests a resource

The client sends a normal HTTP request. No special headers needed.

GET /api/premium-data HTTP/1.1
Host: api.example.com

2. Server responds with 402

The server doesn't recognize a payment, so it responds with HTTP 402 and encodes its requirements in the payment-required header:

HTTP/1.1 402 Payment Required
payment-required: eyJzNDAyVmVyc2lvbiI6IjEiLC...  (base64 JSON)

The decoded document is an x402 V2 PaymentRequired envelope — the same shape an unmodified x402 client already reads, on every s402 route, with no server option (ADR-016). It tells the client everything it needs:

  • What is being paid for (resource.url)
  • One accepts[] entry per offered scheme, exact first
  • Per entry: which network and asset (sui:mainnet, 0x2::sui::SUI), how much (1000000 MIST = 0.001 SUI), and where (payTo)
  • s402's own per-entry fields (facilitatorUrl, expiresAt, the fee fields) inside that entry's extra
  • s402's envelope-level fields — the wire version, and any mandate — under extensions.s402. Their PRESENCE is what makes a 402 an s402-profile 402; their absence makes it a plain x402 402 an s402 client still pays.
json
{
  "x402Version": 2,
  "resource": { "url": "https://api.example.com/premium-data" },
  "accepts": [
    {
      "scheme": "exact",
      "network": "sui:mainnet",
      "asset": "0x2::sui::SUI",
      "amount": "1000000",
      "payTo": "0xrecipient...",
      "maxTimeoutSeconds": 60,
      "extra": { "facilitatorUrl": "https://facilitator.example.com" }
    }
  ],
  "extensions": { "s402": { "version": "2" } }
}

3. Client builds and signs a payment

The client picks the first accepts[] entry it has a scheme registered for on that entry's own network, builds a Sui Programmable Transaction Block (PTB), and signs it. The signed transaction is encoded in the x-payment header, along with the network of the entry it chose — a 402 may offer the same scheme on two networks at different prices, and the scheme name alone cannot say which one was paid.

GET /api/premium-data HTTP/1.1
Host: api.example.com
x-payment: eyJzNDAyVmVyc2lvbiI6IjEiLCJzY2hlbWUiOiJleGFjdCI...

4. Server forwards to facilitator

The server sends the payment payload and original requirements to the facilitator for verification and settlement. The facilitator:

  1. Validates the payload structure
  2. Recovers the signer address
  3. Dry-runs the transaction to verify it will succeed
  4. Broadcasts the transaction to Sui
  5. Returns the settlement result

5. Server delivers the resource

If settlement succeeded, the server delivers the resource with a payment-response header containing the transaction digest:

HTTP/1.1 200 OK
payment-response: eyJzdWNjZXNzIjp0cnVlLCJ0eERpZ2VzdCI6IjlHTlJZRDFS...
Content-Type: application/json

{ "data": "the premium content" }

What the facilitator can and cannot do ​

The client sends a fully signed, pre-built PTB to the facilitator. The transaction is cryptographically locked at this point. Here is exactly what the facilitator can and cannot do:

Facilitator
Verify the transaction will succeed (dry-run)✅ Can
Broadcast the transaction to Sui✅ Can
Return the settlement result to the server✅ Can
Reject a payment that fails verification✅ Can
Change the payment amount❌ Cannot
Redirect funds to a different recipient❌ Cannot
Replay the signed transaction for a second payment❌ Cannot (Sui nonces prevent replay)
Silently fail without the server knowing❌ Cannot (settlement failure is an explicit typed error)

The facilitator cannot steal or alter anything — it is a delivery service for a pre-sealed package, not a trusted custodian. This is why direct mode is possible: the same security properties hold whether the client hands the PTB to a facilitator or broadcasts it directly.

Direct Settlement ​

For the exact scheme, the client can bypass the facilitator entirely by signing and broadcasting the transaction directly to Sui. This is useful when:

  • No facilitator is available
  • The client wants minimum latency
  • The server trusts its own Sui node

Set settlementMode: 'direct' in the requirements to indicate support.

Discovery ​

Servers can advertise s402 support at /.well-known/s402.json:

json
{
  "s402Version": "1",
  "schemes": ["exact", "upto", "prepaid", "escrow", "stream", "unlock"],
  "networks": ["sui:mainnet"],
  "assets": ["0x2::sui::SUI"],
  "directSettlement": true,
  "mandateSupport": true,
  "protocolFeeBps": 50
}

This allows agents to discover payment capabilities before making their first request.

Released under the Apache 2.0 License.