Integrations
x402 Payments
Put a per-request paywall in front of your knowledge base so other people's agents can buy verified answers, no account required.
This is the mirror image of the OpenAI Agents SDK recipe. There, your agent was the buyer and the discipline was verifying what it got. Here you are the seller, and the discipline is deciding what a verified answer is worth.
What x402 is
x402 revives HTTP's long-unused 402 Payment Required. A client requests a resource, the server answers 402 with machine-readable payment terms, the client signs a stablecoin transfer and retries with proof attached, and the server serves the resource. The whole exchange is three headers.
| Header | Direction | Carries |
|---|---|---|
PAYMENT-REQUIRED | Server to client, on the 402 | Base64 PaymentRequired object with an accepts array |
PAYMENT-SIGNATURE | Client to server, on the retry | The signed PaymentPayload |
PAYMENT-RESPONSE | Server to client, on the 200 | Settlement confirmation |
accepts names a scheme (usually exact), a network in CAIP-2 form such as eip155:8453, an amount, the payTo address, the asset, and a maxTimeoutSeconds. A facilitator does the chain work on your behalf through two endpoints, /verify and /settle, so your server never holds a private key or watches a block.The protocol was published by Coinbase in May 2025 and moved to the Linux Foundation's x402 Foundation in 2026. Header names above are v2. If you are reading older material that says X-PAYMENT, that is v1.The pricing decision this forces
Senso exposes the same vector query at four levels of finish, and each one costs you a different amount to serve. That is a price list waiting to happen.
| Endpoint | What the buyer gets | Costs you |
|---|---|---|
POST /org/search/content | Matching source IDs and titles | A vector query |
POST /org/search/context | Raw chunks, buyer synthesizes | A vector query |
POST /org/search | A grounded answer, written for them | A vector query plus generation |
Prerequisites
- A Senso API key with KB scope (create one on the API Keys page)
- A receiving wallet address on the network you intend to accept
- A facilitator URL —
https://x402.org/facilitatorserves the testnet - Python 3.10+
export SENSO_API_KEY="YOUR_SENSO_KEY"
export PAY_TO_ADDRESS="0xYOUR_WALLET"
pip install "x402[fastapi,httpx]" fastapi uvicorn requestsHow it works
- Agent asks — a
GET /answer?q=...arrives with no payment attached - You quote — the server returns
402and aPAYMENT-REQUIREDheader built from the price for that route - Agent pays — it signs a transfer and retries the identical request with
PAYMENT-SIGNATURE - Facilitator verifies — your server hands the payload to
/verifybefore doing any work - You serve — only now does the request reach
POST /org/search, and the grounded answer goes back withPAYMENT-RESPONSE - You log both halves — the settlement proves they paid, the
content_ids prove what they were given
The paid endpoint
import os, requests
from fastapi import FastAPI, Request, Response
from x402 import x402ResourceServer, ResourceConfig
from x402.mechanisms.evm.exact import ExactEvmServerScheme
from x402.http import HTTPFacilitatorClient
SENSO = "https://apiv2.senso.ai/api/v1"
HEADERS = {
"X-API-Key": os.environ["SENSO_API_KEY"],
"Content-Type": "application/json",
}
facilitator = HTTPFacilitatorClient(url="https://x402.org/facilitator")
server = x402ResourceServer(facilitator)
server.register("eip155:*", ExactEvmServerScheme())
server.initialize()
# One price per level of finish. A citation list is a lookup; a written answer
# carries generation cost, so it is not the same product at a discount.
PRICES = {"/citations": "$0.002", "/context": "$0.01", "/answer": "$0.05"}
def terms(path: str) -> ResourceConfig:
return ResourceConfig(
scheme="exact",
network="eip155:8453",
pay_to=os.environ["PAY_TO_ADDRESS"],
price=PRICES[path],
)
app = FastAPI()
@app.get("/answer")
async def answer(request: Request, q: str):
signature = request.headers.get("PAYMENT-SIGNATURE")
requirements = server.build_payment_requirements(terms("/answer"))
# No proof means quote, do not serve. The 402 body is the price list, and it
# is the only thing an unpaid caller can learn about this endpoint.
if not signature:
return Response(
status_code=402,
headers={"PAYMENT-REQUIRED": server.encode(requirements)},
)
settlement = await server.verify_and_settle(signature, requirements)
if not settlement.ok:
return Response(status_code=402, content="Payment could not be settled.")
# Verified. Only now spend anything on their behalf.
resp = requests.post(
f"{SENSO}/org/search",
headers=HEADERS,
json={"query": q, "max_results": 5},
)
resp.raise_for_status()
body = resp.json()
sources = {c["content_id"]: c.get("title", "") for c in body.get("results", [])}
# The receipt and the citations are one audit record. Six months from now a
# dispute is "what did this buyer actually receive", and only this row knows.
log_delivery(settlement.transaction, q, list(sources))
return Response(
content={"answer": body.get("answer", ""), "sources": sources},
headers={"PAYMENT-RESPONSE": server.encode(settlement)},
)The ordering matters. Verify before you query. A server that runs the search first and checks payment afterwards has already paid for the vector query and the generation, and will do it again for every unpaid request that arrives — which, on a public endpoint, is most of them.
What the buyer sees
An agent using an x402-aware client needs no special handling. The wrapper catches the 402, signs, and retries, so the caller sees one request.
from x402 import x402Client
from x402.mechanisms.evm.exact import ExactEvmScheme
client = x402Client()
client.register("eip155:*", ExactEvmScheme(signer=my_signer))
# The wrapper handles 402 -> sign -> retry; the caller just gets an answer.That is the point of the protocol, and it is also the thing to be careful about: an agent that pays without asking will pay repeatedly. Bound it at the application layer, the way the OpenAI Agents SDK recipe bounds a knowledge lookup.
Buying instead of selling
The same wiring runs backwards. If your agent needs data your knowledge base does not have — a sanctions list, a market feed, a verification service — it can buy that page over x402, then post the result into your knowledge base with POST /org/kb/raw so the next agent to ask does not have to buy it twice.
Paying once and ingesting the answer turns a per-request cost into a fixed one. It also means the purchased fact now goes through the same verification as everything else you publish, rather than living in a single conversation and disappearing.
What to watch
- Charge for the answer, not the attempt. A query that matches nothing should still return
200with an empty result set, not a paid non-answer. Buyers who get billed for silence do not come back. - Rate-limit anyway. Payment is not authentication. A paying caller can still hammer you, and every request costs you a vector query even when it is settled.
- Scope the key behind the endpoint. The API key your server uses should reach only the folders you intend to sell. See Permissions.
Where to take it next
- Read Core Concepts for what "compiled" means — an uncompiled source returns nothing, and a paid endpoint returning nothing is a refund
- Serve the same knowledge free to your own agents over the MCP Server
- Use Analytics to see which questions buyers ask, which is the clearest signal you will get about what to write next
