AttestPage · Docs · Pricing · OpenAPI · llms.txt

How to check a quote an LLM cites, step by step with curl

Last updated: 2026-10-10

To check that a quote an LLM cites really appears on the source page, send the page URL and the quote, word for word, to POST /v1/verify/quote (US$0.01 per call). AttestPage fetches the live page, searches its text for the quote and answers exact, fuzzy or none, with a verdict on the page and a signed receipt.

This guide runs the check with curl and jq against https://vehcdj664efetfrsolne5umanq.srv.us, then shows the same call as an MCP tool. For why a plain string search falls short, see How to verify a quote an LLM cites.

What the check does

Price

US$0.01 per call, paid in USDC with x402 v2 on Base Sepolia (a test network). No account, key or sign-up. A request that fails validation gets 400 before payment and is never charged. All prices: pricing.json.

1. See an answer for free

The free sample runs the same route on a demo page:

curl -s https://vehcdj664efetfrsolne5umanq.srv.us/v1/sample/quote | jq '{match: .result.match, score: .result.score, kind: .page.content_kind, advice}'
{
  "match": "fuzzy",
  "score": 0.963,
  "kind": "real",
  "advice": "The page loaded and looks like real content."
}

2. Read the price from the 402 offer

A request with an empty body gets the payment offer without being charged. The PAYMENT-REQUIRED header is base64 JSON:

curl -si -X POST https://vehcdj664efetfrsolne5umanq.srv.us/v1/verify/quote -H 'content-type: application/json' -d '{}' \
  | grep -i '^payment-required:' | cut -d' ' -f2 | tr -d '\r' | base64 -d \
  | jq '.accepts[0] | {scheme, network, amount, payTo}'

amount is in USDC base units (6 decimals), so 10000 is US$0.01.

3. Check a quote

Put the cited URL and the quote, exactly as the LLM gave it, in a file:

cat > body.json <<'EOF'
{ "url": "https://www.iana.org/help/example-domains", "quote": "These domains may be used as illustrative examples in documents" }
EOF

Pay with any x402 v2 client: it reads the offer from step 2, signs it and sends the same request again with a PAYMENT-SIGNATURE header. One x402 payment step by step shows this with plain fetch, and the MCP server does it for you. Save the answer as answer.json for the steps below.

A free trial is on: send the header quoteproof-trial: 1 with a paid route and no payment, and the call runs without charge, 5 calls per IP address per UTC day and 200 a day across all callers. Trial receipts have tier "trial" and payment null. Over the limit you get 429 trial_exhausted with Retry-After. A trial call to verify/citations, verify/quotes or check/links covers at most 3 citations, quotes or URLs; a larger batch is not run as a trial but answered with the normal 402 offer, details.reason trial_too_large.

On the trial, the same check runs from curl:

curl -s -X POST https://vehcdj664efetfrsolne5umanq.srv.us/v1/verify/quote -H 'content-type: application/json' \
  -H 'quoteproof-trial: 1' -d @body.json > answer.json
jq '{match: .result.match, score: .result.score, context: .result.context, kind: .page.content_kind, tier}' answer.json

4. Read the answer

Read page.content_kind first, then result.match:

content_kindmatchWhat it means
realexactThe quoted words are on the page.
realfuzzyA close match. Compare context with the quote: a word may have been changed or two sentences joined.
realnoneThe quote is not on the page our fetcher received. Do not cite it to this source.
bot_wall, js_shell, paywall, http_erroranyThe page could not be read. The quote is unchecked, not false.

If the LLM paraphrased rather than quoted, send "match": "passages" with the claim as quote. You get the 3 passages that share most of its words, as evidence to read, not a verdict. Details: Verify a quote.

5. Keep the receipt

The receipt field is a compact JWS. Check it with the free verify route:

jq '{receipt}' answer.json \
  | curl -s -X POST https://vehcdj664efetfrsolne5umanq.srv.us/v1/receipt/verify -H 'content-type: application/json' -d @- | jq .valid

Or check it offline with our single-file checker: Verify receipts offline.

With MCP

The same check is the MCP tool attestpage_verify_quote, with the body from step 3 as its arguments. To use it from an MCP client with nothing to install, add the remote endpoint:

{
  "mcpServers": {
    "attestpage": { "type": "http", "url": "https://vehcdj664efetfrsolne5umanq.srv.us/mcp" }
  }
}

Or run the local server, which pays from your own wallet key within limits you set: MCP server.

One call to the remote endpoint with curl. _meta["attestpage/trial"] set to false asks for the payment offer rather than a trial call, so nothing is charged:

curl -s -X POST https://vehcdj664efetfrsolne5umanq.srv.us/mcp -H 'content-type: application/json' -d @- <<'EOF' \
  | jq '.result.structuredContent.accepts[0] | {scheme, network, amount}'
{ "jsonrpc": "2.0", "id": 1, "method": "tools/call",
  "params": { "name": "attestpage_verify_quote",
    "arguments": { "url": "https://www.iana.org/help/example-domains", "quote": "These domains may be used as illustrative examples in documents" },
    "_meta": { "attestpage/trial": false } } }
EOF
{
  "scheme": "exact",
  "network": "eip155:84532",
  "amount": "10000"
}

The result has isError: true and the x402 payment requirements in structuredContent, with the same amount as step 2. Sign one of accepts, put the payload in _meta["x402/payment"] and call again: structuredContent is then the same JSON as answer.json, and _meta["x402/payment-response"] holds the settlement.

Questions

How much does one check cost?

US$0.01 per quote with POST /v1/verify/quote. To check up to 10 quotes from one answer in one call, POST /v1/verify/citations costs US$0.10 per batch: Verify citations.

Does an exact match mean the quoted claim is right?

No. It means those words were on the page our fetcher received at that time. Whether the page itself is right is a separate question.

Is a call charged if the page will not load?

Only answers below 400 are charged. A request that fails validation, a host name that does not resolve and a blocked URL are never charged. A page that answers with a 404 or a bot wall is charged, because that result is what the call checks; content_kind says so. Every case is in Payments and Errors.