Repository navigation
Conversation
palango
left a comment
There was a problem hiding this comment.
The facilitator sentence is in the right place and the 402 check does what it says. I ran the server block from this branch with @x402/express 2.20.0, and curl -i http://localhost:3000/premium returns 402 Payment Required even with no API key set.
Two things keep the step from working as the checkpoint #2263 asked for. The response body is {} and the price only appears in the base64 PAYMENT-REQUIRED header, so a reader won't see 10000 anywhere. And the paid half has no buyer on this page, the route is on mainnet, and payTo is still a placeholder, so nobody can get to "you have charged an agent $0.01" from here. Pointing at the buyer script in the celo-composer x402 template, or adding a short Celo Sepolia buyer snippet, would close that gap. Details inline.
#2396 and #2398 merge cleanly on top of this, so the order doesn't matter.
|
|
||
| ## How It Works | ||
|
|
||
| A *facilitator* is a service that checks a buyer's signed payment and submits it on-chain on the seller's behalf, so the seller does not run a node or hold gas. |
There was a problem hiding this comment.
Small accuracy point: the Celo facilitator pays gas up front but bills it back to the seller's balance (gas at cost plus 0.3% after the free credits, see /api/config and the paragraph under Getting an API Key). "so the seller does not run a node or need CELO for gas" avoids suggesting settlement is free.
| curl -i http://localhost:3000/premium | ||
| ``` | ||
|
|
||
| The response is `402 Payment Required`, and the payment requirements describe the route's price: `10000` base units of USDC, which is $0.01 because USDC has 6 decimals. That `402` means the middleware is wired to the route. |
There was a problem hiding this comment.
Running this against the example server gives a {} body. The requirements are only in the base64 PAYMENT-REQUIRED header, so 10000 never shows up in the curl -i output. Could you either say that, or add a decode step? For example:
curl -s -o /dev/null -D - http://localhost:3000/premium | awk -F': ' 'tolower($1)=="payment-required"{print $2}' | tr -d '\r' | base64 -dIt's also worth saying that this check needs no API key.
|
|
||
| The response is `402 Payment Required`, and the payment requirements describe the route's price: `10000` base units of USDC, which is $0.01 because USDC has 6 decimals. That `402` means the middleware is wired to the route. | ||
|
|
||
| A buyer that signs the authorization and retries the request receives `200` with `{"data":"paid content"}`, and the payment settles on Celo for the price above. At that point you have charged an agent $0.01. Settlement needs the API key from the next section. |
There was a problem hiding this comment.
This is the checkpoint the ticket asked for, but the page gives the reader no way to be the buyer. There's no client example here, the route is mainnet with real USDC, and payTo is still 0xYourSellerPayoutAddress. Could we link the buyer script from npx @celo/celo-composer@latest create --template x402 (see /build/quickstart), or add a short @x402/fetch buyer against Celo Sepolia? I'd also move this paragraph after Getting an API Key, since it depends on it.
…orks step (#2263) Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Show how to read the payment requirements from the PAYMENT-REQUIRED header, say the check needs no API key, point to a buyer, move the step after the API key section and correct the gas wording. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
6099c39 to
56119a5
Compare
|
Rebased and reworked: facilitator sentence now says the seller does not need CELO for gas; the check explains the empty body and the base64 |
palango
left a comment
There was a problem hiding this comment.
Thanks, the facilitator sentence and the decode step are what I asked for. I re-ran the server block from this head with @x402/express 2.20.0 and no API key. curl -i gives a 402 with a {} body, and the decode command prints the requirements with "amount":"10000".
The paid half still doesn't work if a reader follows it. If you switch only the network and payTo to Celo Sepolia, the server crashes on startup, because the block still points at https://api.x402.celo.org and that facilitator's /supported lists only eip155:42220. Separately, the Composer buyer sends POST to localhost:3001/paid, but this route is GET /premium on port 3000, so the buyer gets a 404 here, not a 402. Details inline.
Could you also update the PR body? It still says the section follows the resource-server example and that the curl check wasn't run.
The broken-links failure in CI is the Mintlify CLI crashing (The onCancel handler was attached after the promise settled), not a link problem, and mint broken-links passes locally, so a re-run should clear it. #2396 and #2398 still merge cleanly on top.
|
|
||
| The decoded JSON shows the route's price: `10000` base units of USDC, which is $0.01 because USDC has 6 decimals. A `402` with that price means the middleware is wired to the route. | ||
|
|
||
| To see a paid response you need a buyer that signs the authorization and retries the request. The `x402` template of Celo Composer includes a buyer script that pays an x402 endpoint in USDC; see [x402 paid API](/build/quickstart#x402-paid-api). The route above uses Celo mainnet and a placeholder `payTo`, so point both at a Celo Sepolia route and an address you control first, using the Celo Sepolia values under [Celo Configuration](#celo-configuration). A paid request returns `200` with `{"data":"paid content"}` and the payment settles on Celo for the price above. At that point you have charged an agent $0.01. Settlement needs the API key from the previous section. |
There was a problem hiding this comment.
Following this as written crashes the server. The block above hardcodes url: "https://api.x402.celo.org", and that facilitator's /supported only lists eip155:42220. With just the network, asset and payTo switched to Celo Sepolia, startup fails with:
RouteConfigurationError: x402 Route Configuration Errors:
- Route "GET /premium": Facilitator does not support scheme "exact" on network "eip155:11142220"
It works once the URL is https://api.x402.sepolia.celo.org. Could this sentence say to change the facilitator URL too?
Also, the Composer buyer (templates/x402/apps/api/src/buyer.ts.hbs) calls payFetch(url, { method: "POST" }) against SELLER_URL, which defaults to http://localhost:3001/paid. Pointed at this server it gets a 404, because only GET /premium exists here. Either tell readers to run the template's own seller and buyer (pnpm api:dev, then pnpm api:buy) and expect its response rather than {"data":"paid content"}, or tell them to set SELLER_URL=http://localhost:3000/premium and switch the buyer to GET. Minor: on Sepolia it's test USDC, so "charged an agent $0.01" could say so.
… Composer buyer to its own seller Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
|
Pushed the fixes from the last round: the Celo Sepolia switch now includes the facilitator URL ( |
|
Ran the paid path end to end on live Celo Sepolia: unpaid |
palango
left a comment
There was a problem hiding this comment.
Thanks, this covers everything from both rounds. I re-ran the server block from this head with @x402/express 2.20.0, switched to Celo Sepolia the way the new paragraph says. It starts, curl -i gives a 402, and the decode command prints "amount":"10000" on eip155:11142220. With the mainnet facilitator URL left in place it still fails at startup with a RouteConfigurationError, so the warning is right. The Composer pointer matches the template: api:dev and api:buy exist, it defaults to the Sepolia facilitator, and the buyer pays its own POST /paid. Both settlement txs in the PR body succeeded on Celo Sepolia.
One optional suggestion inline. Approving.
|
|
||
| The decoded JSON shows the route's price: `10000` base units of USDC, which is $0.01 because USDC has 6 decimals. A `402` with that price means the middleware is wired to the route. | ||
|
|
||
| To see a paid response you need a buyer that signs the authorization and retries the request. The simplest way is the `x402` template of Celo Composer, which ships its own seller and buyer wired to Celo Sepolia (see [x402 paid API](/build/quickstart#x402-paid-api)). Run the seller with `pnpm api:dev` and the buyer with `pnpm api:buy`. The buyer pays the template's own route and prints the response and the settlement transaction, so expect that output rather than the `{"data":"paid content"}` from the server above. The buyer wallet needs test USDC on Celo Sepolia and no CELO. |
There was a problem hiding this comment.
Optional: the template's seller only charges once X402_PAY_TO is set in apps/api/.env. Without it, /paid runs for free (index.ts.hbs warns "/paid is running FREE") and the buyer gets no settlement tx. A short "fill in apps/api/.env as the template's X402_SETUP.md describes" before pnpm api:dev would save someone that detour.
Part of #2263 (second PR).
Two gaps on the x402 page from the ticket: facilitator was used without a definition, and the Celo setup had no point where a reader could tell it worked.
Changes
curl, the402with an empty{}body, and a decode command for the base64PAYMENT-REQUIREDheader that shows10000base units (USDC has 6 decimals, so $0.01). This check needs no API key.pnpm api:dev,pnpm api:buy), which run on Celo Sepolia with test USDC.urltohttps://api.x402.sepolia.celo.orgas well as the network, asset andpayTo. The mainnet facilitator only listseip155:42220, so the server fails on startup otherwise.The base-unit comments (
amount: "10000", // $0.01 — USDC has 6 decimals) the ticket asked for are already on the page, so nothing changes there. The ticket'smaxValue: "1000000"example is no longer on the page.Verification
mint validatepasses on this branch;mint broken-linkspassed earlier, and the CI failure was the Mintlify CLI crashing, not a link problem.@x402/express2.20.0, no key set; not by me in this environment):curl -ireturns402, the body is{}, and the decode command prints"amount":"10000".https://api.x402.sepolia.celo.org/supportedlistseip155:11142220andhttps://api.x402.celo.org/supportedlists onlyeip155:42220. Checked the Composer buyer defaults to testnet and pays its ownPOST /paidroute.create --template x402,pnpm api:dev,pnpm api:buy) run on Celo Sepolia:/freeanswers, the buyer getsHTTP 200with{"message":"You paid for this response.",...}and a settlement receipt, tx0x7cd73324…3c00. This is the output the page tells readers to expect.pnpm installneeded the public npm registry here because of a local registry auth setting, which is unrelated to the template.payToaddress I control and the Sepolia facilitator URL, plus the metering key, and a buyer built on@x402/fetch. The unpaid request returned402with an empty body and a decodedamountof10000; the paid request returned200with{"data":"paid content"}and a settlement receipt, tx0x9b59c880…665f21.🤖 Generated with Claude Code