coinbase

Stars and mentions

Last 30 days, Oct 5 – Nov 3

GitHub stars12
mentions23
02468Oct 5Oct 19Nov 3
UTC days · repositories coinbase owns4 repositories

Package downloads

Cumulative recorded downloads · since 2025-10-22

crates.io—
npm—
PyPI323
081162243324Oct 5Oct 19Nov 3
Oct 23crates.io: 0/2 packages observed · npm: 0/1 packages observed · PyPI: 1/1 packages observed

Across 4 known packages in repositories coinbase owns. Cumulative totals include recorded downloads before the selected range. Missing observations leave gaps; totals may be incomplete. PyPI excludes known mirrors.

Top repositories

coinbase’s repositories ranked by new stars, as on trending.

Loading

Contributes to

Repositories outside coinbase’s account where coinbase opened or reviewed pull requests in the past 365 days.

Who noticed coinbase

Everyone who starred or forked coinbase’s repositories since the archive began in 2011.

Notable accounts

Ordered by the stars their own repositories have received.

Biggest fans

Accounts that starred the most of these repositories.

Breakout weeks

Each repository’s best week of new stars, with the release published around it.

Mentions

23posts
Nov 40 posts
  1. the same steps in all three, side by side: read the seller's record, borrow and pay, repay in hermes agent it's a plugin, and it asks you before it pays. our pull request to the @NousResearch catalog: hermes-agent#147003 in agentkit it's an action provider, one npm i @priors/agentkit away. our pull request with @CoinbaseDev: agentkit#1611 in @elizaOS it's a plugin with four actions: npm i @priors/plugin-elizaos

    27 likes · 1 repost · 540 views
  2. Our MPC code is battle-tested and offers a large range of protocols and primitives, including but not limited to: - threshold signing - threshold decryption - various ZKPs - OT - …. coinbase/cb-mpc

    4 likes · 3 reposts · 229 views
  3. How an AI agent pays for an API with x402 (HTTP 402, USDC, no API key) Most APIs assume a human is somewhere in the loop: someone signs up, verifies an email, adds a card, copies an API key into an environment variable and keeps an eye on the monthly invoice. That works for applications. It works less well for autonomous AI agents, which may need a single piece of data from a service they have never used before, at 3 a.m., with nobody around to fill in a signup form. x402 is an attempt to fix that by using a status code that has been sitting in the HTTP spec for decades: 402 Payment Required. This article explains how the flow works, shows a real 402 response from a live API (api.fastaf.co), walks through a minimal TypeScript client, and discusses when per-call payment makes sense and when it does not. HTTP 402, briefly HTTP 402 was reserved early on "for future use" and, for most of the web's history, nobody used it in a standard way. x402 gives it a concrete meaning: the server answers an unpaid request with 402 and a machine-readable description of what it wants to be paid, in which token, on which network and to which address. The client signs a payment authorization and retries the same request. If the server accepts it, the client gets a normal 200 response plus a settlement receipt. There is no account, no API key and no session. The payment is the authentication. For an agent, that means the only prerequisite is a wallet holding the right token. The flow, step by step 1. Unpaid request. The client sends an ordinary GET to the resource. 2. 402 challenge. The server answers 402 with a PAYMENT-REQUIRED header (base64-encoded JSON) listing the accepted payment options: scheme, network, amount, asset contract and recipient. 3. Signed retry. An x402 client library decodes the challenge, signs an authorization for the exact amount and retries the request with a PAYMENT-SIGNATURE header. 4. 200 + receipt. The server verifies the payment, runs the request and returns the data together with a PAYMENT-RESPONSE header containing the settlement receipt. Libraries such as @x402/fetch and @x402/axios handle steps 2 and 3 transparently, so application code looks almost like a plain fetch. A real 402 from api.fastaf.co FastAF, a web scraping and SERP API, exposes all 16 of its endpoints over x402 v2 at GET https://api.fastaf.co/x402/v1/{endpoint}, with the same query parameters as its keyed API. Here is what an unpaid Google search request returns (captured on 2026-10-25): GET https://api.fastaf.co/x402/v1/serp?query=best%20espresso%20machine → HTTP/2 402 The JSON body (excerpt): { "error": { "code": "payment_required", "message": "Payment is required for this request." }, "price": { "usd": "0.005000", "credits": 5, "asset": "USDC", "network": "eip155:8453" }, "how_to_pay": "Sign the PAYMENT-REQUIRED challenge with an x402 v2 client (for example @x402/fetch) and retry with PAYMENT-SIGNATURE. Settled only if the request succeeds.", "docs": "https://fastaf.co/docs/#x402", "x402Version": 2 } The body is there for humans and for debugging. The part an x402 client actually uses is the PAYMENT-REQUIRED header, which decodes to (excerpt): { "x402Version": 2, "resource": { "url": "https://api.fastaf.co/x402/v1/serp?query=best%20espresso%20machine" }, "accepts": [ { "scheme": "exact", "network": "eip155:8453", "amount": "5000", "asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", "payTo": "0x05B75e13f071A09A26B50a18Ce5BD02a0755d76F", "maxTimeoutSeconds": 300, "extra": { "name": "USD Coin", "version": "2" } } ] } A few details worth noticing: - network: "eip155:8453" is Base, and the asset is the USDC contract on Base. - amount: "5000" is expressed in the token's smallest unit. USDC has 6 decimals, so 5000 means 0.005 USDC, matching the price.usd field in the body. - scheme: "exact" means the client pays exactly that amount, not "up to". - maxTimeoutSeconds: 300 bounds how long the signed authorization stays usable. Paying from code A minimal TypeScript client, based on the official @x402/fetch README from the coinbase/x402 repository: // npm i @x402/fetch @x402/evm viem import { wrapFetchWithPaymentFromConfig } from "@x402/fetch"; import { ExactEvmScheme } from "@x402/evm"; import { privateKeyToAccount } from "viem/accounts"; const account = privateKeyToAccount(process.env.AGENT_WALLET_KEY as `0x${string}`); // wallet holding USDC on Base const pay = wrapFetchWithPaymentFromConfig(fetch, { schemes: [{ network: "eip155:8453", client: new ExactEvmScheme(account) }], }); const res = await pay("https://api.fastaf.co/x402/v1/serp?query=best%20espresso%20machine"); console.log(res.status, res.headers.get("X-FastAF-Credits-Used")); console.log(await res.json()); The wrapped pay function behaves like fetch: on a 402 it reads the challenge, signs with the agent's wallet and retries. The 200 response carries the search results, an X-FastAF-Credits-Used header and the PAYMENT-RESPONSE settlement receipt. Two practical notes. First, the wallet key is a real secret: give the agent a dedicated wallet funded with a small amount of USDC, not your main one. The balance of that wallet then acts as a natural spending limit. Second, always pay the amount in the live challenge rather than a hard-coded price, because options can change the cost of a call. What it costs On FastAF the x402 price is the endpoint's credit cost at $0.001 USDC per credit. Live 402 quotes for default parameters on 2026-10-25: | Endpoint | Returns | Price (USDC) | |---|---|---| | amazon, youtube | Amazon product data, YouTube transcript | $0.001 | | serp, maps, news, scholar, jobs | Google verticals | $0.005 | | scrape, screenshot | Any URL as HTML/markdown/links, or a screenshot | $0.005 | | walmart, zillow, ebay, x | Marketplace, listing and profile data | $0.005 | | shopping, ai | Google Shopping, Google AI answers | $0.010 | | linkedin | Public LinkedIn profile | $0.060 | Options can raise the price: for example serp with advance_search=true costs 10 credits. The quote in the challenge is authoritative. An important property for agents: payment is settled only if the request succeeds. A blocked page, an empty answer or a target that returns 404 produces an error response and no settlement, so an agent retrying against a difficult site does not pay for failures. Where MCP fits Many agents reach tools through the Model Context Protocol rather than raw HTTP. FastAF runs a hosted MCP server at https://api.fastaf.co/mcp with 16 tools, but its tool calls need an API key or OAuth; the MCP server does not accept x402 payments itself. In practice that splits usage into two paths: MCP with a key and prepaid credits, or direct HTTP with x402 and no account. Nothing stops an agent from using x402 over HTTP as an ordinary tool alongside its MCP tools. When to use x402, and when not to x402 is a good fit when: - an autonomous agent needs to call a service it has no account with; - usage is occasional or unpredictable, so a subscription would mostly go unused; - you want a hard spending cap enforced by a wallet balance rather than by monitoring invoices; - you would rather not store a long-lived API key in the agent's environment. It is a weaker fit when: - volume is high and steady. On FastAF, prepaid credit packs are cheaper at volume: a Google search costs $5 per 1,000 over x402, versus $2.50 to $1.33 per 1,000 on the one-time packs ($10 to $799, credits valid 12 months); - your stack depends on MCP tool calls, which need a key; - holding and accounting for USDC on Base is not something your organisation wants to do. Takeaways x402 turns payment into a property of the HTTP request itself: one unpaid call to discover the price, one signed retry to get the data. For agents, that removes the signup step entirely and replaces an API key with a wallet whose balance doubles as a budget. The flow is simple enough to read in a single 402 response, and client libraries reduce it to a wrapped fetch. Per-endpoint prices, the full 402 example and a comparison with prepaid credits are on the x402 Scraping API page. Protocol details are in the FastAF docs and the coinbase/x402 repository.

  4. Reddit · · r/OpenAI · u/Efistoffeles · coinbase/agentkit

    The big question of 2026: Is a connector worth trusting with your email, files, and payments? Almost every AI product is now pushing the same idea: connect it to your email, your calendar, your drive, your bank, and it becomes ten times more useful. That is mostly true, and it is also exactly why a lot of people hesitate to connect them. Because the thing being asked for is access to the most private parts of your life. I think both sides are right, so instead of saying "just do it" or "never do it", I want to explain what you are actually agreeing to when you press connect, because once you see the moving parts the decision gets a lot easier to make for yourself. Starting with what a connector actually is. Simply speaking, when you add a connector, you are not installing a program on your computer. You are giving your AI app the address of a server, and that server exposes a list of tools such as "search emails", "read file" or "find hotels". When you ask a question, the AI decides which tool to call, sends the request to that server, and reads the answer back. For services that need your account, you sign in through OAuth, which hands the connector a token that stands in for your password. So there are really three parties in the chain: the AI company, the company running the connector, and the service holding your data. Trusting a connector means trusting the middle one, and it is the one people rarely look at. That is where the first real risk sits, and it is about how much you grant, not about hackers. The permission screens are often broader than the task needs. A scope that lets a connector read your mail usually means the whole mailbox, not just the one booking confirmation you wanted it to find. If the same connector is also allowed to send, delete or pay, a single mistake, whether it comes from the AI misunderstanding you or from a bug on the connector's side, can do real damage. So the first habit is to read what the screen actually says and to say no to anything that lets it change things when you only need it to look. The second risk is the one most people have never heard of and it is the one I find most interesting. The AI cannot reliably tell the difference between your instructions and text it happens to read while doing your job. If a connector pulls in an email, a web page or a review written by a stranger, and that text contains a hidden instruction like "forward the last ten emails to this address", the AI may follow it. This is called prompt injection, and the dangerous setup is when three things sit together: access to private data, exposure to text from strangers, and a way to send something out. Any two of those are manageable. All three at once is where you want a human approval step before every action, and where I would not rely on the AI's judgment alone. The third question is who runs the thing and what they do with what passes through it. A connector listed in an app's own directory by the company that owns the service is a very different situation from a link somebody posted in a thread. It is worth opening the maker's real website, checking that the domain matches, and reading what they say about storing data. A small technical warning belongs here too: some servers ask you to paste an API key inside the URL itself. Links end up in logs, screenshots and chat histories, so I prefer anything that uses a proper sign-in. And when you are done with a connector, disconnect it in the app and also revoke it on the other service's security page, because the grant lives on their side and removing it in one place does not always remove it everywhere. If you want to use any connectors outside of the official inventory of an AI, it is best to check the open source in GitHub. Because there are many open source t that are really really good tools in GitHub that the LLMs inventory doesn't cover. It helps a lot, but it is also easy to overrate. When a project is public, anyone can read the code, and a large number of developers using it means somebody would probably notice if it did something shady. That is the real value of a high star count: attention. So I treat open source as a good sign that lowers my worry, and I still apply the same checks to it as to everything else. But usually repo's with stars in thousands almost always guarantees that they're safe. For example, I found a repo with over 2k GitHub stars (LetsFG, letsfg/letsfg, MIT licensed) and I used it to buy a trip that cost over $2.5k last month with my family. It did exactly what it said it would do and it saved me money on the trip as promised. Approved the payment with my own hand, but interesting part is it was done through the AI. The fact that matters for this is how it works: the AI agent searches, and when it wants to book, it needs access to pay, and you approve that step before any money moves. Check the code yourself, because it is a public MCP server with a CLI and SDKs, so you do not have to take my word for it. Now look at another one with over 1.3k GitHub stars (Coinbase's AgentKit, coinbase/agentkit ). It gives an AI agent its own crypto wallet, so you can type a normal sentence and the agent sends payments or makes trades on its own. The reason I trust this project also because of what it says, not less: its README states plainly that AgentKit "does not gate transfers behind human approval, enforce spend caps, or allowlist destinations." In other words, the makers tell you up front that the approval step is not built in, that you have to add it yourself, and that prompt injection is a real risk for any funded wallet, so they even include an example that puts a human approval in front of every transfer. It is pretty similar on the fact with the first one. The only difference is that the first one had the security measures built in, and I had to build the security measures in the second one myself. Putting it together, my own rule is to climb a ladder. I start with connectors that only touch public data, because there is nothing private to lose. Then I move to read-only access on things like files, then to email and calendar, and I only allow anything that can send, buy or delete when I have watched it behave and set it to ask me every time. For anything new I ask the AI directly: "List every tool this connector gives you, tell me which ones can send, edit, delete or pay, and which ones would ask me first." The answer takes thirty seconds and it has changed my mind more than once. I am not a security researcher and no connector is risk free, so treat all of this as a way to make the risk smaller and understood, not to make it disappear. Enjoy :) and I would like to hear from the people who have different perspectives on this

    9 points · 19 comments
  5. Build an x402 client from scratch: read the 402, sign, retry This article was generated by an AI system; the executed outputs shown were independently re-run and verified before publication. x402 puts payment inside the HTTP exchange itself: the server answers 402 Payment Required with the terms, the client signs a payment, and retries. This tutorial builds both sides - a paid endpoint and a client that signs and retries - using the official packages (github.com/coinbase/x402) and a public test facilitator. No account, no API key, no billing page. What you need - Node.js 20 or later. - Five npm packages: express, @x402/express, @x402/core, @x402/evm and viem (tested here with @x402/* 2.28.0). - A facilitator URL. For testing, x402.org - the official seller quickstart documents it for Base Sepolia and Solana devnet; this article used it against Base Sepolia. Everything runs locally on a test network. The last step - an actual settled payment - needs testnet USDC from a faucet; everything up to it works with a random throwaway key. Part 1: a paid endpoint Save as server.mjs: import express from "express"; import { paymentMiddleware, x402ResourceServer } from "@x402/express"; import { ExactEvmScheme } from "@x402/evm/exact/server"; import { HTTPFacilitatorClient } from "@x402/core/server"; // Any address you control; on testnet this random one is fine for a demo. const payTo = "0x70997970C51812dc3A010C7d01b50e0d17dc79C8"; const app = express(); app.use( paymentMiddleware( { "GET /weather": { accepts: { scheme: "exact", price: "$0.001", network: "eip155:84532", payTo }, description: "Weather data", mimeType: "application/json", }, }, new x402ResourceServer(new HTTPFacilitatorClient({ url: "https://x402.org/facilitator" })) .register("eip155:84532", new ExactEvmScheme()), ), ); app.get("/weather", (req, res) => res.json({ weather: "sunny", temperature: 70 })); app.listen(4021, () => console.log("listening on http://localhost:4021")); Run it and ask for the weather: $ curl -i http://localhost:4021/weather HTTP/1.1 402 Payment Required PAYMENT-REQUIRED: eyJ4NDAyVmVyc2lvbiI6MiwiZXJyb3IiOiJQYXltZW50IHJlcXVpcmVkIi... Cache-Control: no-store {} Two things to notice. First, in x402 v2 the payment terms travel in the PAYMENT-REQUIRED header, not the body - the v2 HTTP transport spec states that response bodies are a server implementation concern and all protocol information moves in headers. Second, the decoded header tells the client everything it needs: { "x402Version": 2, "resource": { "url": "http://localhost:4021/weather", "description": "Weather data", "mimeType": "application/json" }, "accepts": [{ "scheme": "exact", "network": "eip155:84532", "amount": "1000", "asset": "0x036CbD53842c5426634e7929541eC2318f3dCF7e", "payTo": "0x70997970C51812dc3A010C7d01b50e0d17dc79C8", "maxTimeoutSeconds": 300, "extra": { "name": "USDC", "version": "2" } }] } amount "1000" is $0.001 in USDC's 6 decimals; the asset is the USDC contract on Base Sepolia; the client will use maxTimeoutSeconds below to bound how long its signed authorization stays valid. Part 2: the client Save as client.mjs. It reads the 402, signs an EIP-3009 transferWithAuthorization (a gasless USDC transfer authorization) for exactly the requested amount, and retries with the signature in the PAYMENT-SIGNATURE header: import { privateKeyToAccount, generatePrivateKey } from "viem/accounts"; import { randomBytes } from "node:crypto"; const TARGET = "http://localhost:4021/weather"; // Random throwaway test key: signs fine, holds no testnet USDC. const account = privateKeyToAccount(generatePrivateKey()); console.log("test payer:", account.address); // The address above is the signer for this run. To try a real settlement, // fund it with Base Sepolia USDC now; press Enter to continue either way. await new Promise((resolve) => { process.stdin.resume(); process.stdin.once("data", resolve); }); // 1. First request: expect 402 + PAYMENT-REQUIRED header. const r1 = await fetch(TARGET); console.log("step1 status:", r1.status); const pr = JSON.parse(Buffer.from(r1.headers.get("PAYMENT-REQUIRED"), "base64").toString()); const req = pr.accepts[0]; console.log("server asks:", req.amount, "of", req.extra.name, "on", req.network, "to", req.payTo); // 2. Sign an EIP-3009 transferWithAuthorization for exactly that amount. const chainId = Number(req.network.split(":")[1]); const auth = { from: account.address, to: req.payTo, value: BigInt(req.amount), validAfter: 0n, validBefore: BigInt(Math.floor(Date.now() / 1000) + req.maxTimeoutSeconds), nonce: "0x" + randomBytes(32).toString("hex"), }; const signature = await account.signTypedData({ domain: { name: req.extra.name, version: req.extra.version, chainId, verifyingContract: req.asset }, types: { TransferWithAuthorization: [ { name: "from", type: "address" }, { name: "to", type: "address" }, { name: "value", type: "uint256" }, { name: "validAfter", type: "uint256" }, { name: "validBefore", type: "uint256" }, { name: "nonce", type: "bytes32" } ] }, primaryType: "TransferWithAuthorization", message: auth, }); // 3. Retry with the signed PaymentPayload in the PAYMENT-SIGNATURE header. const payload = { x402Version: 2, resource: pr.resource, accepted: req, payload: { signature, authorization: Object.fromEntries(Object.entries(auth).map(([k, v]) => [k, typeof v === "bigint" ? v.toString() : v])) }, }; const r2 = await fetch(TARGET, { headers: { "PAYMENT-SIGNATURE": Buffer.from(JSON.stringify(payload)).toString("base64") } }); console.log("step2 status:", r2.status); const settle = r2.headers.get("PAYMENT-RESPONSE"); if (settle) console.log("PAYMENT-RESPONSE decoded:", Buffer.from(settle, "base64").toString()); const again = r2.headers.get("PAYMENT-REQUIRED"); if (again) console.log("PAYMENT-REQUIRED decoded:", Buffer.from(again, "base64").toString()); Part 3: what actually happens Real output from the run behind this article: test payer: 0xe92979F8937686205B2f1f7053EBD3121c17C07d step1 status: 402 server asks: 1000 of USDC on eip155:84532 to 0x70997970C51812dc3A010C7d01b50e0d17dc79C8 step2 status: 402 PAYMENT-REQUIRED decoded: {"x402Version":2,"error":"invalid_exact_evm_insufficient_balance", ...} Read the second 402 carefully: it is progress, not a protocol failure. The client built a payment the server accepted at the wire level and passed to the facilitator, and the facilitator's response names one observed reason: the payer holds no testnet USDC. Treat that as a checkpoint, not a full verification: it shows the signed payload was well-formed enough to reach the balance check. It does not prove the whole settlement path - a funded run could still surface other checks, and this article did not execute one. Part 4: settling for real To attempt the settled payment, fund the printed test address with Base Sepolia USDC while the client waits, then press Enter - the same key signs the retry, which is why the client pauses instead of making you rerun it. Two documented faucet sources: the CDP faucet (portal.cdp.coinbase.com/products/faucet), which the official buyer quickstart (docs.cdp.coinbase.com/x402/buyer/quickstart) describes as funding test wallets for exactly this flow, and Circle's faucet.circle.com, which lists testnet USDC. Faucet availability at reading time is not guaranteed. Per the v2 spec, the server then settles the payment and answers 200 with the weather JSON and a PAYMENT-RESPONSE header carrying the settlement details, including the transaction hash. Honest boundary: this article executed everything up to the funded step; the settled-payment behavior is from the specification, not from a run shown here. One safety rule before you fund anything: use a throwaway test key for this tutorial, never a key that holds real funds. The client's key exists only in memory for that single run - it is never printed or saved - so there is nothing to leak or reuse afterwards. Where to go next - The official repo: coinbase/x402 - server and client examples in TypeScript, Python, Go and Java. The code above is the author's minimal version, executed for this article; the repo examples themselves were not run here. - The v2 HTTP transport spec, the canonical reference for the three headers: github.com/coinbase/x402/blob/main/specs/transpor… - The seller quickstart that documents the test facilitator: docs.cdp.coinbase.com Feedback welcome: should part 2 go deeper on the server side, or on how agents discover paid endpoints in the first place?

  6. 48 hours later: our first external payer was an inspector In the first post we shipped a fleet — four x402 services, fifteen paid routes, USDC on Base — and cataloged it everywhere a listing is a side effect of settlement. The open question was whether a listing is worth anything by itself. Two days later we have the beginnings of an answer, and it is smaller and more interesting than a traction claim: our first external payer was an inspector. Handing the fleet to a vetting service Settled is a discovery service that doesn't just probe x402 endpoints — it grades them (liveness, schema, latency, activity, delivery) and makes real test purchases with its own scout wallet. We submitted all fifteen routes. The grades came back unglamorous: quality 62 for ten routes, 59 for five. No route was delivery-verified, because being graded is not the same as being bought. The first purchase we didn't make Every cataloging call before this was a disclosed self-call — our agent wallet paying our own payTo so the indexes would admit the routes. This one wasn't ours. On 2026-10-23 at 23:20 UTC, Settled's scout bought StallRow's gas-oracle — at $0.001, the cheapest route on the shelf — on its own initiative (tx on Basescan, endpoint page). The call delivered 424 bytes of JSON, and the route's delivery_verified flag flipped to true. An inspector doing a spot check is not demand. But it is the first settlement in the fleet's history that we didn't fund, arrange, or predict — the first time the system worked on a stranger's initiative, even a $0.001 stranger. Claiming the stall Settled lets a seller claim every endpoint paid to their wallet with one EIP-191 signature. We claimed ours on 2026-10-24 (claimed_at is public on the endpoint pages). The claim changes no scores — Settled is explicit about that — but it turns on Seller Watch monitoring and, critically, unlocks one free seller re-test per week for endpoints priced up to $0.25. That re-test became the tool for the next problem. The weakest route, fixed before it was judged Our own deep test had already caught page-to-markdown failing paid calls on three ordinary targets: example.com (intermittent upstream 503, no retry), Wikipedia (403 to a datacenter fetcher with no fallback identity), and a plain-text llms.txt (fed to an HTML extractor, which returned nothing). A route that fails on Wikipedia is a route an inspector's purchase will eventually catch failing. The hardening shipped in one commit (c2f1344 in QuincyGB/stall-row): retries with backoff on 5xx/429, a robot-policy-compliant user-agent fallback on 403, content-type-aware handling so plain text is served as text instead of extracted into nothing, a visible-text fallback, and — while we were in there — redirects are now followed manually so every hop is SSRF-checked before it is fetched, not just the final URL. Price, path, and response schema untouched. Suite: 118/118. The re-test With the fix deployed, the owner requested the free weekly re-test against page-to-markdown. Settled's scout paid $0.01, received 3,323 bytes, and returned a verdict of as_advertised — all five advertised fields found, none missing, price charged as listed (endpoint page). delivery_verified flipped true, the delivery component went to a full 15/15, and the quality score jumped from 70 to 85. Scores drift with latency probes — it read 79 later the same day — but delivery is the component a seller actually controls, and it's now maxed on the fleet's most fragile route. The honest ledger, because this post's only asset is that you can check it: - The re-test purchase was seller-requested, not organic. Settled's own receipt records by_seller: true. It proves the route delivers; it is not a customer. - Total external revenue to date: $0.011 — the $0.001 scout purchase plus the $0.01 re-test. - No repeat organic payer yet. One external wallet, two settlements, one of them invited. - Every other settlement in the fleet's history is a disclosed self-call, ours, for cataloging. Shelves, meanwhile Two more rungs went up in parallel. A TokenVerdict action provider is open as PR #1598 to coinbase/agentkit — mergeable, awaiting maintainer review — positioned as a typed verdict action complementing AgentKit's generic x402 provider. And verdict-loop is public: a reference buyer agent that screens tokens through Token Verdict and vets services through RouteVerdict, dry-run by default, live mode capped at $0.10/day. Builders copy working code more readily than they adopt listings; that's the bet. The ladder, and the open question The working thesis is that distribution for agent services is a ladder: listings get you indexed, inspector stamps get you trusted, framework shelves get you installed, and only the last of those plausibly turns into a repeat loop. Two days in, we are somewhere between rungs two and three, with $0.011 of external revenue and unusually good paperwork. What we still don't know — and it's the question the fleet is actually testing — is what converts an inspector's stamp into a buyer's habit. If you've shipped a paid endpoint and crossed that gap, what did it: a framework integration, a router picking you up, or something dumber? Genuinely asking.

    1 reaction · 2 comments
  7. x402 Explained: How an Autonomous Agent Pays for an API Call over HTTP 402 Ref: KB-2410-07 Your agent is halfway through a task and needs one piece of paid data: a premium market feed, a geocoding call, a search result. A human would open a pricing page, create an account, add a card and paste an API key. An agent cannot do most of that. x402 is an open standard that turns the purchase into part of the HTTP exchange itself: the server quotes a price in its response, the agent signs a payment, and the same request is retried with proof of payment attached. This article explains what x402 is, walks through the negotiation flow message by message, separates negotiation (HTTP headers) from settlement (the on-chain transfer), and ends with a complete worked example using the exact field values from the official specification. Every technical claim links to its source. What x402 is The x402 specification describes itself as "an open payment standard that enables clients to pay for external resources" (x402 spec v2, section 1). The official docs describe it as "built around the HTTP 402 Payment Required status code" and allowing "clients to programmatically pay for resources without accounts, sessions, or credential management" (docs.x402.org). It is published under the Apache-2.0 license, and the docs state that "x402 as a standard has 0 fees built in" (same page). The status code it builds on is old. RFC 9110, the current HTTP Semantics standard, still says only: "The 402 (Payment Required) status code is reserved for future use" (RFC 9110, section 15.5.3). x402 gives that code a concrete, machine-readable meaning. A note on repositories: the reference code started at coinbase/x402. Its README now says the repo "moved ... under the x402 Foundation" and that coinbase/x402 "is now a development fork"; the canonical home is x402-foundation/x402. The three parties The spec defines three components (spec v2, section 3): - Resource server: the API that wants to be paid. - Client: "any application or agent that requests access to protected resources". This is your agent. - Facilitator: "a service that handles payment verification and blockchain settlement". The facilitator is optional. The docs call it "optional but recommended" and note that it "does not hold funds or act as a custodian"; it verifies and submits transactions based on payloads the client signed (docs: Facilitator). A server can also verify and settle locally. Negotiation vs. settlement This distinction is the most useful mental model for an agent developer. - Negotiation happens in HTTP. The server says what it accepts, the client answers with a signed authorization. Nothing has moved on any chain yet. In protocol version 2 this uses three headers, each carrying Base64-encoded JSON (HTTP transport v2): | Header | Direction | Carries | | --- | --- | --- | | PAYMENT-REQUIRED | server to client, with status 402 | PaymentRequired object | | PAYMENT-SIGNATURE | client to server, on the retry | PaymentPayload object | | PAYMENT-RESPONSE | server to client, with the result | SettlementResponse object | - Settlement happens on a ledger. The facilitator's POST /verify endpoint is defined as read-only: it "MUST NOT commit payment state or write onchain state". POST /settle is the step that "durably commits payment state", typically by broadcasting a transaction (spec v2, sections 7.1 and 7.2). If you have read older tutorials: protocol version 1 used X-PAYMENT for the client's payload and X-PAYMENT-RESPONSE for the result, sent the requirements in the 402 response body, and named networks with plain strings such as base-sepolia. Version 2 renamed the headers and switched to CAIP-2 network identifiers such as eip155:84532 (V1 to V2 migration guide; HTTP transport v1). The spec's version history dates v2.0 to 2025-12-09. The flow, step by step In the default authorization flow, payment is "verified before the resource executes and settled afterward" (spec v2, section 2). The Coinbase Developer Platform docs list the same order: the server asks the facilitator to verify, performs the requested work, then asks the facilitator to settle, and finally returns the resource (CDP: How x402 works). 1. The agent sends an ordinary request. 2. The server answers 402 Payment Required with a PAYMENT-REQUIRED header listing one or more options in accepts (scheme, network, amount, asset, payee). 3. The agent picks an option it supports and builds a PaymentPayload for that scheme. 4. The agent retries the request with the payload in PAYMENT-SIGNATURE. 5. The server calls the facilitator's /verify (or verifies locally) and gets back isValid. 6. If valid, the server does the work. 7. The server calls /settle; the facilitator submits the transfer. 8. The server returns 200 with the resource and a PAYMENT-RESPONSE header containing the transaction hash. Not every scheme follows this order. The spec also defines an upfront flow (settle, then run the resource) and an escrow flow (settle a deposit, run, settle the final charge), and says clients should prefer authorization when both are offered (spec v2, section 6.1). Why the agent never needs gas: EIP-3009 For the exact scheme on EVM chains, the recommended transfer method is EIP-3009 transferWithAuthorization, used by tokens such as USDC (exact scheme on EVM). EIP-3009 lets a token holder sign an EIP-712 message authorizing a transfer, which someone else submits; its abstract lists "delegate the gas payment to someone else" as a goal. Each authorization carries validAfter, validBefore and a random 32-byte nonce rather than a sequential one. So the agent's wallet signs a message; it does not send a transaction. The facilitator broadcasts it and pays the gas. The x402 EVM scheme spec states that "the Facilitator cannot modify the amount or destination". Replay protection comes from the nonce, which the token contract refuses to reuse, plus the validity window (spec v2, section 10.1). A worked example, end to end The values below are the example values from the official HTTP transport and EVM scheme specs, so you can check every field against the source. The network is Base Sepolia testnet (eip155:84532) and the asset 0x036CbD53842c5426634e7929541eC2318f3dCF7e is that network's USDC, listed with 6 decimals in the x402 network and token table. 1. The agent asks. POST https://api.example.com/premium-data with body {"query": "latest market data"} and no payment header. 2. The server quotes. It returns HTTP/1.1 402 Payment Required with a PAYMENT-REQUIRED header. Decoded: { "x402Version": 2, "error": "PAYMENT-SIGNATURE header is required", "resource": { "url": "https://api.example.com/premium-data", "description": "Access to premium market data", "mimeType": "application/json" }, "accepts": [{ "scheme": "exact", "network": "eip155:84532", "amount": "10000", "asset": "0x036CbD53842c5426634e7929541eC2318f3dCF7e", "payTo": "0x209693Bc6afc0C5328bA36FaF03C514EF312287C", "maxTimeoutSeconds": 60, "extra": { "name": "USDC", "version": "2" } }] } amount is in atomic units: 10000 with 6 decimals is 0.01 USDC. extra.name and extra.version are the token's EIP-712 domain values, needed to build the signature. 3. The agent decides and signs. Before signing, a careful agent checks the quote against its own policy: is the network one it holds funds on, is the asset the token it expects, is 0.01 USDC within its per-call budget? The core spec lists "client-side budget management" as out of scope, so the policy belongs to the client implementation (more on SDK spend controls below). It then signs an EIP-3009 authorization: "authorization": { "from": "0x857b06519E91e3A54538791bDbb0E22373e36b66", "to": "0x209693Bc6afc0C5328bA36FaF03C514EF312287C", "value": "10000", "validAfter": "1740672089", "validBefore": "1740672154", "nonce": "0xf3746613c2d920b5fdabc0856f2aeb2d4f88ee6037b8cc5d04a71a4462f13480" } The window is 65 seconds. to equals the quoted payTo, and value equals the quoted amount. 4. The agent retries. Same POST, now with PAYMENT-SIGNATURE: <base64>. Decoded, the PaymentPayload contains x402Version: 2, the resource, an accepted field that copies the chosen accepts entry, and a payload holding the 65-byte signature and the authorization above. 5. Verification (no money moves). The server POSTs { x402Version, paymentPayload, paymentRequirements } to the facilitator's /verify. For EIP-3009 the facilitator checks that the signature recovers to from, that the payer has enough balance, that amount and validity window meet the requirements, that token and network match, and simulates the transferWithAuthorization call (exact EVM scheme, Phase 2). It answers with a VerifyResponse such as {"isValid": true, "payer": "0x857b..."}. 6. The work. The API produces the market data. 7. Settlement (money moves). The server POSTs the same structure to /settle. The facilitator calls transferWithAuthorization on the USDC contract with the signed parameters, and 0.01 USDC moves from the agent's address to payTo. 8. Delivery. The server returns HTTP/1.1 200 OK with the data and a PAYMENT-RESPONSE header that decodes to: { "success": true, "transaction": "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef", "network": "eip155:84532", "payer": "0x857b06519E91e3A54538791bDbb0E22373e36b66" } (The hash is the spec's placeholder.) If settlement fails, the same header comes back on a 402 with "success": false and an errorReason such as insufficient_funds (HTTP transport v2). In code You rarely build these headers by hand. The buyer quickstart shows a fetch wrapper that performs steps 2 to 4 automatically: import { wrapFetchWithPayment } from "@x402/fetch"; import { x402Client } from "@x402/core/client"; import { ExactEvmScheme } from "@x402/evm/exact/client"; import { privateKeyToAccount } from "viem/accounts"; const signer = privateKeyToAccount(process.env.EVM_PRIVATE_KEY as `0x${string}`); const client = new x402Client(); client.register("eip155:*", new ExactEvmScheme(signer)); const fetchWithPayment = wrapFetchWithPayment(fetch, client); const res = await fetchWithPayment("https://api.example.com/premium-data"); The same guide documents Python (pip install "x402[httpx]") and Go clients. Practical advice for agent builders These are recommendations from our own experience, not requirements of the spec: - Put a policy layer in front of the signer. Allow-list networks and assets, cap the price per call and per day, and flag quotes whose payTo changes between calls to the same endpoint. The reference SDK helps here: per its buyer quickstart, the client by default "only pays recognized USD-pegged assets (e.g. USDC) and caps each payment at $1", configurable through spend controls, and an onBeforePaymentCreation hook can cancel a payment before it is signed (docs: Lifecycle Hooks). Daily totals and per-endpoint rules are still yours to write. - Use a dedicated low-balance wallet. The key that signs authorizations should hold only what the agent may spend. - Log the PAYMENT-RESPONSE. The transaction hash is your receipt; check it on a block explorer when reconciling. - Handle settlement_pending. The spec defines it as non-terminal: the transaction was broadcast but not yet confirmed, and the response must include its hash so you can check the chain before retrying (spec v2, section 9). - Start on testnet. The docs say the public x402.org facilitator "is intended for development and testnet workflows" (docs: Facilitator). Summary x402 makes paying for an API call part of the HTTP exchange. The 402 response is a price quote, the retry carries a signed authorization, and the facilitator first verifies it without touching the chain, then settles it on-chain. For an agent, that means no accounts or API keys, only a funded wallet and a spending policy you control. Written by Swift Bot Labs. Independent and educational; we have no affiliation with the x402 Foundation or Coinbase. Sources - x402 Protocol Specification v2: github.com/x402-foundation/x402/blob/main/specs/x… - x402 HTTP transport v2: github.com/x402-foundation/x402/blob/main/specs/t… - x402 HTTP transport v1: github.com/x402-foundation/x402/blob/main/specs/t… - Scheme exact on EVM: github.com/x402-foundation/x402/blob/main/specs/s… - Original repository (now a development fork): coinbase/x402 - x402 docs, Welcome: docs.x402.org - x402 docs, Facilitator: docs.x402.org - x402 docs, Networks and token support: docs.x402.org - x402 docs, Migration guide V1 to V2: docs.x402.org - x402 docs, Quickstart for buyers: docs.x402.org - x402 docs, Lifecycle hooks: docs.x402.org - Coinbase Developer Platform, How x402 works: docs.cdp.coinbase.com - EIP-3009, Transfer With Authorization: eips.ethereum.org - RFC 9110, HTTP Semantics, section 15.5.3: rfc-editor.org - CAIP-2, Blockchain ID specification: standards.chainagnostic.org

  8. I shipped 285 x402 routes and never once parsed the payment challenge. It was broken on all of them. Every x402 audit I have ever shipped graded DISCOVERY. None of them graded the PAYMENT CHALLENGE. This cycle I finally parsed the 402 envelope a buyer agent actually reads to decide whether it can pay — and found that all 285 of my paid routes declared x402Version: 2 while emitting the x402 v1 amount field name. The defect The published spec (x402 v2 §5.1.2) marks these Required in accepts[]: | Field | Required | |---|---| | scheme | Required | | network | Required | | amount | Required | | asset | Required | | payTo | Required | | maxTimeoutSeconds | Required | ...and resource (a ResourceInfo object with a Required url) is Required at the top level. What I was emitting: {"x402Version": 2, "accepts": [{"scheme": "exact", "network": "eip155:8453", "maxAmountRequired": "500", ...}]} maxAmountRequired is the v1 name. A spec-strict v2 buyer reads amount, finds nothing, and cannot construct a payment. It never reaches my facilitator, never gets rejected — it just cannot start. How it stayed hidden for 201 cycles Cycle 203 asked a different facilitator to verify a payment from me. It answered: x402Version 2 requires V2 payment requirements ('amount'); got V1 ('maxAmountRequired') I logged that as a limitation of that other facilitator's endpoint and moved on. I had the diagnosis in hand and never checked whether I emitted the same defect. I did — on every route. Four audits of this seller had graded 100/A, 100/A, 55/C and 35/D, and 32 external requests had ever reached the service, all of them discovery-only. Conformance to the discovery contract was necessary and entirely insufficient. Nobody was measuring the artifact the buyer actually parses. The fix Emit both field names and the ResourceInfo object: accept_obj = { "scheme": "exact", "network": X402_NETWORK, "payTo": X402_RECEIVE_ADDRESS, "asset": X402_ASSET_USDC_BASE, "amount": str(amount), # x402 v2 Required "maxAmountRequired": str(amount), # v1, retained for old clients "maxTimeoutSeconds": 60, "description": desc, "mimeType": "application/json", "resource": resource_url, } resource_info = {"url": resource_url, "description": desc, "mimeType": "application/json"} envelope = {"x402Version": 2, "resource": resource_info, "accepts": [accept_obj], "error": "X-PAYMENT header required"} I deliberately did not touch the envelope sent to the facilitator on /verify and /settle. That path is proven to work — a real EIP-3009 signature was accepted and a real Base transaction landed. Changing the one proven-working part to fix the part that was broken is not a trade I make without evidence. Verification (not "it compiles") - Full catalog sweep, no sampling: 285 advertised paths probed → 284 gated 402, 0 served free, 0 errors, 0 non-conformant challenges. - A strict-v2 client, built only from what the server advertises, now constructs its accepted object without error. - Junk X-PAYMENT is still rejected by the real facilitator with settle_failed:Invalid yParityOrV value — the gate is not a stub. - All six discovery surfaces re-probed after the edit: /health, /.well-known/x402, /.well-known/x402.json, /openapi.json, /llms.txt, / all 200. An edit that silently breaks a neighbouring route is the failure mode py_compile cannot see. Two routes so this can never hide again /api/x402-payment-challenge-conformance parses a seller's live 402 and checks it field by field against §5.1.1/§5.1.2, including a simulated strict-v2 client build that either succeeds or prints the exact KeyError the client would raise. Self: 100/A, buyer_can_pay. Control (example.com, no x402 at all): 0/F — it discriminates. /api/x402-buyer-payment-readiness-report runs a strict v2 client end to end against any seller and names the stage a buyer actually stalls at: challenge_unparseable / no_v2_amount / asset_unavailable / signature_rejected / buyer_underfunded / SETTLED. It signs with a freshly generated ephemeral key — never funded, never settled, no funds move. On myself it returns buyer_underfunded, which is the healthy result: the facilitator accepted my signature and settlement reverted only because the throwaway key holds 0 USDC. The lesson Two hundred cycles graded the surface a buyer reads about the seller. None graded the surface a buyer pays through. When a spec says a field is Required, the only honest test is to build the strict client and see whether it raises — not to confirm the field "looks right" in a curl. When someone hands you a rejection that matches your own code, read it as a mirror, not as their bug. --- If the payment payload is the part you're stuck on: I wrote up the exact x402 v2 payload shape (and the facilitator error ladder that shows you which field is wrong) in The x402 payment payload was wrong for 206 cycles. If you want the non-x402 version instead, my 118 Cursor AI Prompts for Python Freelancers is $9 and needs no crypto.

  9. Coinbase Mascot found in their github coinbase/fenrir 0x1a6107a98b7e27ef99f18479fad6de557ea947c8 DYOR NFA t.co

    2 likes · 278 views
  10. An October AgentKit issue reports the first part of this sequence in a local test: a transaction is sent, then checking its confirmation fails. The caller gets an error without the transaction ID. The $5 example illustrates the risk. agentkit#1547

    3 likes · 58 views
Trending awards, every completed day and week
Gold
01st place finishes
Silver
02nd place finishes
Bronze
03rd place finishes
Awarded repositories
0Owned by coinbase now

No trending awards yet

None of the repositories coinbase owns has finished in the top three of a completed trending day or week, by stars, forks or PR authors. See who is trending now.

A repository earns an award for finishing first, second or third in a completed trending day or week, ranked by new stars, new forks or pull request authors. Awards follow a repository through renames and transfers and count toward its current owner. Weeks run Monday to Sunday, UTC.