x402 beside a seller's stack
Serve an x402 resource with your own server and facilitator, and the seller door for the ATR and the check.
This guide serves an x402 resource from your own server, with your own facilitator, and uses the seller door for the
ATR and the check. The pairing is x402/exact/eip155/eip3009: H is the nonce of the EIP-3009 authorization the
payer signs.
sequenceDiagram
participant B as Buyer's agent
participant R as Your resource server
participant D as Seller door
participant F as Your facilitator
B->>R: GET /v1/report
R->>D: issue (accepts, request, content)
D-->>R: atrHash, link, carriers
R-->>B: 402 PaymentRequired with extensions.legalContext
B->>R: GET /v1/report with PAYMENT-SIGNATURE
R->>D: claim (payment, chosen = accepted)
D-->>R: settling
R->>F: verify, settle
F-->>R: transaction
R->>D: report (reference = transaction)
R-->>B: 200 and the resource
What each call sends
| Call | Field | Value |
|---|---|---|
issue | offers | Each PaymentRequirements exactly as the 402 will carry it, with pairing x402/exact/eip155/eip3009. |
request | The commitment to the request the 402 answers. | |
lifetimeSeconds | The largest maxTimeoutSeconds. | |
claim | payment | The PaymentPayload, exactly as received. |
chosen | Its accepted. | |
network | accepted.network. | |
request | The same commitment. | |
settleBy | The authorization's validBefore. | |
report | reference | The facilitator's transaction. |
chosen | accepted, when the payment was not claimed. |
The whole flow
This program issues the ATR, builds the 402 with the LCP package's x402 entry point, and claims the payment the buyer
presents. The door is the stand-in (see Getting started), so the buyer's payment is vector
CV6's. Your facilitator would verify and settle between the claim and the report.
import type { ClaimResponse, IssueRequest, IssueResponse, Refusal } from "@integraledger/agentic-connectors";
import { } from "@integraledger/agentic-connectors";
import { , type , type } from "@integraledger/lcp/x402";
const = .. ?? "https://seller.example/door";
const = .. ?? "";
async function <>(: string, : unknown): <> {
const = await (`${}${}`, {
: "POST",
: { : `Bearer ${}`, "content-type": "application/json" },
: .(),
});
const = (await .()) as | Refusal;
if (!.) throw new (`${}: ${.} ${( as Refusal).}`);
return as ;
}
const : = {
: "exact",
: "eip155:84532",
: "10000",
: "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
: "0x209693Bc6afc0C5328bA36FaF03C514EF312287C",
: 60,
: { : "USDC", : "2" },
};
const = {
: "GET",
: "/v1/report",
: "",
: "0xe3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
} as ;
// 1. Issue the ATR before the 402 goes out.
const : IssueRequest = {
: "chk_7Q2:v1",
: "quote",
: .,
: [{ : "x402/exact/eip155/eip3009", }],
,
: [{ : "terms", : .('"Pay 10000 base units of USDC for one report."').("base64") }],
};
const = await <IssueResponse>("/issue", );
// 2. Place H and the link in the 402, through the LCP package's entry point for the pairing.
const : = {
: 2,
: { : "https://api.seller.example/v1/report" },
: [],
};
const = .(, ., ., );
if ("refused" in ) throw new (.);
const = .?.["legalContext"]?.;
.("402 carries H:", .() === .(..));
// 3. The buyer pays. Claim the payment before the facilitator sees it.
const = (["CV6"]!.[1]!.. as { : { : } }).;
const = ( as unknown as { : { : { : string } } })...;
const = await <ClaimResponse>("/claim", {
: "quote",
: "x402/exact/eip155/eip3009",
,
: .,
: ..,
,
: (),
});
.("claim:", ., "claimed:", ..);
// 4. Verify and settle with your facilitator, then report its `transaction` to the door.402 carries H: true
claim: settling claimed: trueAfter your facilitator settles, report {atrHash, pairing, outcome: "paid", reference: <transaction>, network} (see
the report operation).
Where H is on chain
The facilitator submits the payer's authorization to the token contract, which verifies the signature when it
executes the transfer. H is then on chain as the nonce topic of the contract's AuthorizationUsed event in the
settlement transaction. Anyone holding the ATR can hash it and find that event; the chain alone does not reveal the
ATR's content.
Other x402 pairings
Every x402 pairing uses the same calls; what differs is where H rides and what the record proves. The pairings reference lists them, and the LCP package's documentation at lcp.integraledger.com describes each binding. For Tron and Polkadot, the profile facilitator is a facilitator you can run.
Last updated on