AttestPage recipes
Last updated: 2026-10-17
Short, runnable recipes for calling AttestPage from an agent. In each one, the agent checks a source before it cites it. Copy one, run it, then change the tools to fit your agent.
| Recipe | Runnable file | Framework | Language | How it calls AttestPage | Pays with x402 |
|---|---|---|---|---|---|
| langchain.md | langchain.mjs | LangChain (create_agent, createAgent) | Python and JavaScript | Python: a small client using only the standard library. JavaScript: the client from the OpenAI Agents SDK recipe | Python: no payment; returns the price. JavaScript: yes, when a key is set |
| openai-agents-sdk.md | openai-agents-sdk.mjs | OpenAI Agents SDK | JavaScript | A small client over fetch | Yes, with @x402/fetch when a key is set |
| openai-agents.md | Code on the page | OpenAI Agents SDK | JavaScript | The quoteproof-mcp server over stdio, or a verify_quotes call over HTTP | Yes, with @x402/fetch (HTTP) or QUOTEPROOF_X402_KEY (MCP) when a key is set |
| llamaindex.md | llamaindex.mjs | LlamaIndex.TS (agent, tool) | JavaScript | The client from the OpenAI Agents SDK recipe | Yes, when a key is set |
| vercel-ai-sdk.md | vercel-ai-sdk.mjs | Vercel AI SDK (generateText, tools) | JavaScript | The client from the OpenAI Agents SDK recipe | Yes, when a key is set |
| claude-agent-sdk.md | claude-agent-sdk.mjs | Claude Agent SDK | JavaScript | The quoteproof-mcp MCP server (stdio) | Yes, when QUOTEPROOF_X402_KEY is set |
| fetch-x402.md | fetch-x402.mjs | None | JavaScript | Plain fetch, one x402 payment step by step | Yes |
| python-x402.md | python-x402.py | None | Python | httpx and the x402 package: one unpaid call, then one x402 payment step by step | Yes, when a key is set |
| crewai.md | Code on the page | CrewAI (Agent, Task, Crew) | Python | A verify_quotes tool that calls the route with the x402 package | Yes, with the x402 package when a key is set |
| pydantic-ai.md | Code on the page | Pydantic AI (Agent, tool_plain) | Python | A verify_quotes tool that calls the route with the x402 package | Yes, with the x402 package when a key is set |
| mastra.md | Code on the page | Mastra (Agent, createTool) | JavaScript | A verify_quotes tool that calls the route with @x402/fetch | Yes, when a key is set |
| curl.md | Code on the page | None | Shell | curl: the 402 price, then one x402 payment | Yes, when a key is set |
| mcp.md | Code on the page | MCP clients | Any | The quoteproof-mcp server (stdio), no install step | Yes, with QUOTEPROOF_X402_KEY when it is set |
Run a recipe
Each page shows its code in full, with what to install and the command that runs it. The LangChain (JavaScript), LlamaIndex.TS, Vercel AI SDK and OpenAI Agents SDK recipes share one client, [attestpage.mjs](/docs/examples/attestpage.mjs), shown on the OpenAI Agents SDK page.
- Plain fetch with x402 always pays, so it needs
ATTESTPAGE_X402_KEY, the key of a wallet holding a little USDC. - Python with x402 makes one unpaid call with no wallet key (it returns the price), then pays for one call when
ATTESTPAGE_X402_KEYis set. - OpenAI Agents SDK sends no payment with no wallet key and returns the price; it needs
OPENAI_API_KEYfor the model. - LangChain (JavaScript), LlamaIndex.TS and Claude Agent SDK send no payment with no wallet key and return the price; they need
ANTHROPIC_API_KEYfor the model. - Vercel AI SDK sends no payment with no wallet key. With
ANTHROPIC_API_KEYset, the model decides when to call the tools; without it, the file callsverify_quoteonce and prints the answer.
Service address
https://s2h6qt73jtzlgbgnnfacln2poq.srv.us
Every recipe uses this address by default. To call another address, set ATTESTPAGE_URL (the MCP server reads QUOTEPROOF_URL).
Routes and prices
Prices are per call in USDC. The full list is at [/pricing.json](https://s2h6qt73jtzlgbgnnfacln2poq.srv.us/pricing.json) and in the OpenAPI document.
| Route | What it answers | Price |
|---|---|---|
POST /v1/verify/quote | Is this quote on the page at this URL: exact, fuzzy or none, with offsets and page hashes | US$0.01 |
POST /v1/verify/citations | The same for up to 10 quote and URL pairs | US$0.10 per batch |
POST /v1/verify/quotes | The same for up to 20 quotes on one page, fetched once | US$0.02 per batch |
POST /v1/verify/text-quote | The same check against text you already hold, nothing fetched | US$0.005 |
POST /v1/verify/document | Every quote with its link in a finished document, checked on the live page | US$0.10 per part of up to 10 pairs |
POST /v1/verify/document/preview | The pairs a document check would make, and its price | free |
POST /v1/fetch | A page as clean text, with a verdict on what came back (real, bot_wall, js_shell, paywall, http_error and others) | US$0.002 |
POST /v1/recheck | Fetches a page again and compares it with an earlier receipt: unchanged, changed, gone or unreadable, with a receipt naming both hashes | US$0.003 |
POST /v1/check/links | Status, redirects, final URL and verdict for up to 10 URLs | US$0.005 per batch |
POST /v1/check/packages | Whether up to 10 npm, PyPI or crates.io names exist, with latest version | US$0.005 per batch |
POST /v1/attest | A signed, timestamped receipt over a SHA-256 you send | US$0.002 |
POST /v1/receipt/verify | Checks a receipt's signature against the published keys | free |
Every answer from a paid route carries a receipt: an Ed25519-signed JWS of what the fetcher saw and when. A receipt records what was on the page at that time, not whether a statement on it is correct.
How a call is paid
- Payment. A paid route without payment answers
402with the price. See Limits. - 402 Payment Required. A valid request gets
402when it has no payment. The offer is in thePAYMENT-REQUIREDheader: base64 JSON with the amount (USDC, 6 decimals), network and pay-to address. - x402. Sign the offer and send the same request again with the
PAYMENT-SIGNATUREheader. Payment settles only when the route answers with a status below 400; the answer then carries aPAYMENT-RESPONSEheader.
Payments run on Base (eip155:8453). USDC on Base is real money: each paid call is charged. Use a wallet holding only the USDC you can spare.
A bad request gets 400 before any offer and is never charged. Error codes are listed at [/docs/errors](https://s2h6qt73jtzlgbgnnfacln2poq.srv.us/docs/errors).
Try it without code
# Free: what a verify/quote answer looks like
curl -s https://s2h6qt73jtzlgbgnnfacln2poq.srv.us/v1/sample/quote
# The 402 offer for verify/quote, decoded
curl -s -o /dev/null -D - -X POST https://s2h6qt73jtzlgbgnnfacln2poq.srv.us/v1/verify/quote \
-H 'content-type: application/json' -d '{}' \
| grep -i '^payment-required:' | cut -d' ' -f2 | tr -d '\r' | base64 -d
More
- Several quotes from one page in one
POST /v1/verify/quotescall: OpenAI Agents SDK, Claude Agent SDK, Vercel AI SDK, LangChain (Python), LlamaIndex (Python) and CrewAI, Pydantic AI and Mastra - Payments
- MCP server
- llms.txt