Docs
Pay per query
Paid endpoints charge $0.10 to $0.50 per call, settled in USDC on
Base via x402: an HTTP-native
payment protocol built on the 402 Payment Required
status code. No account, no API key, no subscription. This page
covers how to pay for a query end to end.
Step 0: a funded wallet
Every paid query settles from a wallet holding USDC on Base. USDC is a digital dollar: 1 USDC = $1, no trading, no price risk. Base is the low-fee network it moves on. You don't need to understand blockchains to use either, just how to buy USDC and where to send it. Pick your path:
Buy USDC on Coinbase
Sign in at coinbase.com, or open an account (a one-time identity check, like opening a brokerage account). Buy $10 to $20 of USDC with a card or bank transfer. Buy a little more than you plan to spend; the purchase fee comes out of it.
Install Coinbase Wallet
Coinbase Wallet is a free app, separate from your Coinbase account: get the browser extension to pay from the live demo, or the phone app otherwise. Your Coinbase account holds USDC for you; the wallet is the app QueryLines actually talks to. Both are made by Coinbase. They are not the same thing.
Send the USDC to your wallet, on Base
In Coinbase, send your USDC to the wallet address from step 2 and pick Base as the network. The transfer is free (Coinbase covers the fee) and usually lands in under a minute.
Pick Base, not Ethereum. USDC sent on the wrong network can be stranded.
Spend your first dime
Back on the homepage, run a free query in the live demo, then a paid one. When the payment challenge appears, choose "Settle it for real (USDC)" and approve the two prompts in your wallet: one to connect, one to sign. $5 of USDC is about 50 queries at the $0.10 tier.
Create a dedicated hot wallet
Generate a fresh keypair you'll use only for paying QueryLines (and other x402 APIs), not a wallet holding anything else. Any of these work:
openssl rand -hex 32for a raw private key, or- viem's
generatePrivateKey()in Node, or - a fresh Coinbase account and its withdrawal address.
Fund it with a few dollars of USDC on Base
Withdraw USDC from any exchange directly to Base (select the "Base" network, not Ethereum mainnet), or bridge/onramp USDC to Base from anywhere else. $5 of USDC is about 50 queries at the $0.10 tier.
Keep it small and separate
- Use a key dedicated to paying APIs, never a personal wallet's key.
- Fund it with a small, disposable balance, not your savings.
- Store the private key in an environment variable or secret manager, never in code or version control.
No ETH needed, ever. Paying with x402's "exact" scheme is a sign-only operation: your client signs an EIP-3009 USDC authorization (an EIP-712 typed-data signature, not a transaction) and the facilitator submits the on-chain settlement and pays the gas itself. Your wallet only ever needs USDC, never ETH for gas.
Wallet questions
Is this crypto speculation?
No. USDC is pegged 1:1 to the dollar. You're moving dollars to pay for a query, not holding an asset that trades.
What if I lose access to the wallet?
Treat it like petty cash: a few dollars, kept small on purpose. If the laptop or phone dies, you're out the balance and nothing else.
Can I get receipts for accounting?
Every paid query settles with a public transaction hash on Base, viewable on basescan.org with the amount and timestamp. A cleaner paper trail than most invoices.
Is this okay for a business to use?
USDC is a dollar-backed stablecoin from a regulated US issuer. You're paying a vendor for data; on the books it's a data expense, not a crypto position.
Do I need to buy Ethereum too?
No. Your wallet only ever needs USDC. The payment facilitator submits the on-chain settlement and pays the network fee.
What if I just want to try it once?
The discovery endpoints are free and need no wallet at all. Set one up only when a ten-cent query is worth it.
Quickstart, official SDKs
Full, tested code for the three languages with official x402 SDKs.
Every snippet pays for the same call:
GET /v1/premium?state=FL.
$ npm install @x402/fetch @x402/evm @x402/core viem
import { decodePaymentResponseHeader } from "@x402/core/http"; import { ExactEvmScheme } from "@x402/evm"; import { wrapFetchWithPaymentFromConfig } from "@x402/fetch"; import { privateKeyToAccount } from "viem/accounts"; // EVM_PRIVATE_KEY is the wallet you funded in Step 0 const account = privateKeyToAccount(process.env.EVM_PRIVATE_KEY); // "eip155:*" accepts whatever eip155 network the server asks for (Base mainnet here) const fetchWithPayment = wrapFetchWithPaymentFromConfig(fetch, { schemes: [{ network: "eip155:*", client: new ExactEvmScheme(account) }], }); const res = await fetchWithPayment("https://api.querylines.com/v1/premium?state=FL"); console.log(await res.json()); // the settlement receipt is a base64 JSON header on the paid response const receiptHeader = res.headers.get("PAYMENT-RESPONSE"); if (receiptHeader) console.log(decodePaymentResponseHeader(receiptHeader));
{
"success": true,
"network": "eip155:8453",
"transaction": "0x7a3fd1…c91e",
"payer": "0x9f2b6a…4a71",
"amount": "100000"
}
x402 v2.15.0
$ pip install "x402[httpx,evm]"
import asyncio import os from eth_account import Account from x402 import x402Client from x402.http.clients import x402HttpxClient from x402.mechanisms.evm import EthAccountSigner from x402.mechanisms.evm.exact.register import register_exact_evm_client async def main(): client = x402Client() # EVM_PRIVATE_KEY is the wallet you funded in Step 0 account = Account.from_key(os.getenv("EVM_PRIVATE_KEY")) register_exact_evm_client(client, EthAccountSigner(account)) async with x402HttpxClient(client) as http: response = await http.get("https://api.querylines.com/v1/premium?state=FL") await response.aread() print(response.text) asyncio.run(main())
$ go get github.com/x402-foundation/x402/go@latest
package main import ( "fmt" "io" "net/http" "os" x402 "github.com/x402-foundation/x402/go" x402http "github.com/x402-foundation/x402/go/http" evm "github.com/x402-foundation/x402/go/mechanisms/evm/exact/client" evmsigners "github.com/x402-foundation/x402/go/signers/evm" ) func main() { // EVM_PRIVATE_KEY is the wallet you funded in Step 0 signer, _ := evmsigners.NewClientSignerFromPrivateKey(os.Getenv("EVM_PRIVATE_KEY")) client := x402.Newx402Client(). Register("eip155:*", evm.NewExactEvmScheme(signer)) httpClient := x402http.WrapHTTPClientWithPayment( http.DefaultClient, x402http.Newx402HTTPClient(client), ) resp, err := httpClient.Get("https://api.querylines.com/v1/premium?state=FL") if err != nil { fmt.Println("request failed:", err) return } defer resp.Body.Close() body, _ := io.ReadAll(resp.Body) fmt.Println(string(body)) }
More languages, community SDKs
These are community-maintained, not published by the x402 foundation or Coinbase. Verify the package before trusting it with a funded key; each row is a link to the real registry listing, not a code block QueryLines has run.
| Language | Package | Registry & version | Notes |
|---|---|---|---|
| C#/.NET | x402.Client |
NuGet, v2.2.0 | x402-v2-native. Wraps HttpClient with automatic pay-and-retry. |
| Rust | x402-reqwest |
crates.io, v2 | x402-v2 middleware for reqwest. |
| Ruby | x402-payments |
RubyGems, supports x402 v2 | Early-stage; signs payment headers for EVM and Solana. |
PHP's community package is x402-v1-only and won't work against QueryLines (a v2 resource server), so it's skipped here.
Escape hatch: x402-proxy
For any language without a native SDK,
x402-proxy
(npm, community-maintained) is a CLI sidecar that pays 402
challenges on your behalf. Point it at a paid QueryLines URL and it
behaves like curl, handling the challenge, signing,
and retry itself:
$ npx x402-proxy https://api.querylines.com/v1/premium?state=FL
It walks you through wallet setup on first run if you don't already have one funded. See docs.x402.org's third-party SDK list and x402.org for the full, continuously-updated ecosystem beyond what's listed here.
It's just HTTP
None of this requires an SDK. The free endpoints
(/v1/premium/sample, /v1/coverage,
/v1/lines) work from any HTTP client in any language
with zero payment code at all. And the paid protocol itself
(402 → sign an EIP-3009 typed-data authorization →
base64-encode it into a header → retry) is implementable in
any language that has an EIP-712 signing library. The SDKs above
just save you from writing that by hand.
The 402 flow, end to end
This is what actually happens on the wire for a paid call, using
the real challenge a live request to
GET /v1/premium?state=FL returns.
- Client requests
GET /v1/premium?state=FLwith no payment attached. - Server responds
HTTP/2 402with an empty body and a base64-encoded challenge in thePAYMENT-REQUIREDresponse header. - Client base64-decodes the header and reads the
acceptsarray to find a scheme/network it can pay:exactoneip155:8453(Base mainnet). - Client signs an EIP-3009
transferWithAuthorizationfor the exact USDC amount: an EIP-712 typed-data signature, no on-chain transaction, no gas spent by the client. - Client retries the same request with the signed authorization attached as a payment payload.
- The facilitator (Coinbase's CDP-hosted facilitator on Base mainnet) verifies the signature and submits the settlement transaction on-chain, paying its own gas.
- Server responds
200 OKwith the JSON body and a base64-encoded settlement receipt in thePAYMENT-RESPONSEresponse header.
The decoded challenge (real, abridged)
This is base64decode() of a live PAYMENT-REQUIRED
header from GET /v1/premium?state=FL. The full header
also carries an x402 Bazaar discovery block (input/output schema
for agent marketplaces) that's trimmed here for length.
{
"x402Version": 2,
"error": "Payment required",
"resource": {
"url": "https://api.querylines.com/v1/premium?state=FL",
"mimeType": "application/json",
"serviceName": "QueryLines"
},
"accepts": [
{
"scheme": "exact",
"network": "eip155:8453",
"amount": "100000",
"asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
"payTo": "0x16be07aec4d16e8ec9039d16e7049ee47834acd7",
"maxTimeoutSeconds": 300,
"extra": { "name": "USD Coin", "version": "2" }
}
],
// "extensions.bazaar" (input/output schema for agent discovery) omitted here
}
amount is USDC's atomic unit (6 decimals): 100000
is $0.10. asset is Base mainnet's native USDC contract.
payTo is QueryLines' receiving address.
The decoded receipt
On a settled payment, the retried response carries a
PAYMENT-RESPONSE header that decodes to:
{
"success": true,
"network": "eip155:8453",
"transaction": "0x…",
"payer": "0x…",
"amount": "100000"
}
transaction is the on-chain settlement hash on Base
(look it up on basescan.org);
payer is the wallet address that signed the
authorization.