AttestPage · Docs · Pricing · OpenAPI · llms.txt

How it works

Last updated: 2026-10-10

How AttestPage fetches a page, what each content_kind verdict means, and what a signed receipt records about the fetch.

The fetcher

When a route reads a page, our fetcher requests the URL you sent:

Pages are not stored. The text is extracted, hashed, matched, and dropped when the response is sent.

content_kind

Every page result has one content_kind, from automated rules over the status, headers and text. They can be wrong; signals lists the clues behind each verdict.

content_kindMeaning
realThe page loaded and looks like real content.
bot_wallThe site served a bot challenge to our fetcher. Do not treat this as the page's content.
js_shellThe page needs JavaScript to show its content; the text we read is mostly empty scaffolding.
paywallThe page appears to be behind a paywall or login; the text may be a teaser only.
emptyThe page loaded but has little or no readable text.
off_siteThe URL redirected to a different site; the content is from that site. In check/links, off_site_error: true marks one whose site answers 4xx/5xx.
http_errorError status, or a connection problem (signals such as outcome_dns_error, outcome_connect_error).
unsupported_typeNot HTML, text, JSON or a readable PDF, so not read. A PDF we could not read has the signal pdf and one of pdf_encrypted (needs a password), pdf_invalid (damaged or not a PDF), pdf_over_budget (needs more memory than we allow), pdf_timeout or pdf_out_of_memory.
pdfcheck/links only: a live PDF link (status 2xx, application/pdf, same site), not read. In check/links an unread link with a 4xx/5xx status is http_error and one redirected to another site is off_site (with off_site_error: true if that site answers 4xx/5xx).
robots_disallowedrobots.txt or an opt-out disallows our fetcher.
timeoutThe site did not answer in time.
too_largeOver the 2 MB cap, so not read in full.

injection_flags

Patterns often used for prompt injection, found in the page text: instruction_override, role_reassignment, prompt_markers, prompt_extraction, addresses_ai, command_execution, exfiltration_request, plus hidden_instructions when a match is in text a browser does not show. They are flags, not a verdict. An empty list means none of our patterns matched.

Receipts

Every paid answer carries a receipt: a compact JWS signed with Ed25519 (alg EdDSA, typ attestpage-evidence+jws). The key id is https://still-rapids-9yt7.here.now/.well-known/jwks.json#ap-<thumbprint>, where https://still-rapids-9yt7.here.now is the fixed issuer address (it stays the same when the service address changes); the public keys are at /.well-known/jwks.json and /.well-known/did.json.

Payload fields (version 1):

FieldMeaning
vschema version, 1
isshttps://still-rapids-9yt7.here.now
iatsigning time, Unix seconds
kindquote, quotes, citations, document, fetch, links, packages or attest
request_sha256SHA-256 of your request body as canonical JSON
quote_sha256SHA-256 of the quote (quote receipts)
url, final_url, http_status, content_kindwhat was requested and what came back
content_sha256SHA-256 of the full extracted text
raw_sha256SHA-256 of the body bytes as received
retrieved_atwhen the page was fetched
server_ipthe vetted IP address our fetcher connected to for the final response (the site's address, not yours)
tlsthe site's certificate on the final response over HTTPS: cert_sha256 (SHA-256 of the DER certificate), issuer, subject (each up to 1,024 bytes), valid_from, valid_to; null over plain HTTP
headersthese response headers when the site sent them: date, last-modified, etag, content-type, content-length (each up to 512 bytes)
resultthe route's result (match, signals, per-link results, per-page and per-citation results, or attestation)
tierpaid, trial or sample
paymentpaid calls: rail, network, asset, amount, payer, payment_id (L402: payer null, payment_hash and preimage); otherwise null

server_ip, tls and headers are on fetch and quote receipts and on each entry of a links receipt and each page of a citations receipt. They are null when no response came back, and always null on an edge server, which cannot pin the connection to an IP or read the certificate. Those byte caps count the value as UTF-8 once JSON-encoded (a " or \ counts 2, a CJK character 3); a longer value is cut on a whole character and ends with …. Receipts issued before these fields existed do not have them and still verify.

A receipt records what our fetcher saw at that time. Pages change, and a page can show different content to different visitors. It does not show that anything the page says is correct.

Check receipts with POST /v1/receipt/verify or offline.