# 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](/docs/examples/langchain) | [langchain.mjs](/docs/examples/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](/docs/examples/openai-agents-sdk) | [openai-agents-sdk.mjs](/docs/examples/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](/examples/openai-agents) | 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](/docs/examples/llamaindex) | [llamaindex.mjs](/docs/examples/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](/docs/examples/vercel-ai-sdk) | [vercel-ai-sdk.mjs](/docs/examples/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](/docs/examples/claude-agent-sdk) | [claude-agent-sdk.mjs](/docs/examples/claude-agent-sdk.mjs) | Claude Agent SDK | JavaScript | The `quoteproof-mcp` MCP server (stdio) | Yes, when `QUOTEPROOF_X402_KEY` is set |
| [fetch-x402.md](/docs/examples/fetch-x402) | [fetch-x402.mjs](/docs/examples/fetch-x402.mjs) | None | JavaScript | Plain `fetch`, one x402 payment step by step | Yes |
| [python-x402.md](/docs/examples/python-x402) | [python-x402.py](/docs/examples/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](/examples/crewai) | 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](/examples/pydantic-ai) | 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](/examples/mastra) | 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](/examples/curl) | Code on the page | None | Shell | `curl`: the 402 price, then one x402 payment | Yes, when a key is set |
| [mcp.md](/examples/mcp) | 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_KEY` is set.
- OpenAI Agents SDK sends no payment with no wallet key and returns the price; it needs `OPENAI_API_KEY` for 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_KEY` for the model.
- Vercel AI SDK sends no payment with no wallet key. With `ANTHROPIC_API_KEY` set, the model decides when to call the tools; without it, the file calls `verify_quote` once 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](https://s2h6qt73jtzlgbgnnfacln2poq.srv.us/openapi.json).

| 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

1. **Payment.** A paid route without payment answers `402` with the price. See [Limits](https://s2h6qt73jtzlgbgnnfacln2poq.srv.us/docs/limits).
2. **402 Payment Required.** A valid request gets `402` when it has no payment. The offer is in the `PAYMENT-REQUIRED` header: base64 JSON with the amount (USDC, 6 decimals), network and pay-to address.
3. **x402.** Sign the offer and send the same request again with the `PAYMENT-SIGNATURE` header. Payment settles only when the route answers with a status below 400; the answer then carries a `PAYMENT-RESPONSE` header.

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

```sh
# 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/quotes` call: [OpenAI Agents SDK](https://s2h6qt73jtzlgbgnnfacln2poq.srv.us/examples/openai-agents), [Claude Agent SDK](https://s2h6qt73jtzlgbgnnfacln2poq.srv.us/examples/claude-agent-sdk), [Vercel AI SDK](https://s2h6qt73jtzlgbgnnfacln2poq.srv.us/examples/vercel-ai-sdk), [LangChain (Python)](https://s2h6qt73jtzlgbgnnfacln2poq.srv.us/examples/langchain), [LlamaIndex (Python)](https://s2h6qt73jtzlgbgnnfacln2poq.srv.us/examples/llamaindex) and [CrewAI](https://s2h6qt73jtzlgbgnnfacln2poq.srv.us/examples/crewai), [Pydantic AI](https://s2h6qt73jtzlgbgnnfacln2poq.srv.us/examples/pydantic-ai) and [Mastra](https://s2h6qt73jtzlgbgnnfacln2poq.srv.us/examples/mastra)
- [Payments](https://s2h6qt73jtzlgbgnnfacln2poq.srv.us/docs/payments)
- [MCP server](https://s2h6qt73jtzlgbgnnfacln2poq.srv.us/docs/mcp)
- [llms.txt](https://s2h6qt73jtzlgbgnnfacln2poq.srv.us/llms.txt)
