# fledgify proof > Prove, from a stranger's vantage, that a stranger can actually pay for an offer at a public URL. Read only: it never buys, never enters a card, never submits a form. A proof runs 15 checks in three groups (reachable, buyable, honest) and returns one verdict per check plus an overall verdict. It attests to what was observed, at a time, from a vantage. It never attests to the seller's honesty. ## Verdicts - PROVEN: observed, and true. - NOT_PROVEN: observed, and false. The reason says exactly what failed. - NOT_CHECKED: could not be observed. The reason names what blocked it. It is never a pass; do not report it as one. - Overall: PROVEN only when every check is PROVEN; NOT_PROVEN when any check is NOT_PROVEN; otherwise NOT_CHECKED. ## Call it - HTTP: GET https://proof.fledgify.com/v0/proof?url= returns the report as JSON. url is the only parameter this door reads. Percent encode it, and any other query parameter, such as a tracking tag a shared link picked up, is ignored. If you substitute the URL raw instead, so the value still contains "://", everything after url= is taken as the offer URL exactly as you wrote it, which is how a raw & inside your URL survives; a percent escape in a raw URL is yours and is passed through untouched. Headers on the answers from /v0/proof, /v0/proof.txt, /p/ and the redirect from /prove: x-fledgify-verdict, x-fledgify-record, x-fledgify-cache, retry-after, link. x-fledgify-cache is HIT, MISS or RECORD. retry-after is sent only with a 429 or a 503. link is RFC 8288 rel="alternate" pointing at the record as JSON, and is absent whenever the answer being served is already that JSON. That is GET /p/.json, and any GET /p/ that negotiates to JSON, which is what happens unless the Accept header asks for HTML. All 5 are in access-control-expose-headers, so a browser agent on another origin can read them. The MCP answer carries none of them; over MCP the same facts are in the structured content. - Text: GET https://proof.fledgify.com/v0/proof.txt?url= - MCP: POST https://proof.fledgify.com/mcp (streamable HTTP, stateless). One tool, "proof", input { "url": string }, returns structured content matching the report schema. A refused call (bad URL, over a limit) is isError with the reason and no verdict. The mcp-protocol-version header is optional; send it only with a version this server speaks (2025-06-18, 2025-03-26, 2024-11-05, 2024-10-07), because any other value refuses the whole call with JSON-RPC -32600. Claude Code: claude mcp add --transport http fledgify-proof https://proof.fledgify.com/mcp - Records: a fresh proof is stored immutably and its URL is in x-fledgify-record and in report.record. Reading one has four outcomes: 200, 404 when no record has that id, 500 when the bytes are stored but are not a report this version can read, and 503 with retry-after when the read did not finish. Only the 404 means the citation is not real. GET https://proof.fledgify.com/p/.json returns it exactly as observed; cite that URL rather than re-running. When the store cannot be written the report still carries the verdict, has no record field and no permanent link, and says so in its notes; branch on report.record rather than assuming it. ## Contracts - [OpenAPI 3.1](https://proof.fledgify.com/openapi.json) - [Report JSON Schema](https://proof.fledgify.com/v0/schema.json) - [About the bot, for site operators](https://proof.fledgify.com/bot) ## Limits, and what it cannot see - 10 proof requests a minute per caller, 6 per site, 30 for the whole service, counted exactly. At most 3 of a site's 6 go to any one caller, so no caller can hold a site's minute. Over a limit: 429 or 503 with retry-after. - Every request past the door counts as one of your 10 a minute, including one served from cache and one refused by the site limit. A recent proof of the same URL is served from cache: that costs the site nothing, but it still counts as one of your 10 a minute. To read a result again, fetch its record (/p/.json), which counts against no limit. - So proving many pages of one site meets your own 3 of that site's 6 first, at your 4th proof of it: the share is charged before the site bucket and is keyed on your address, so one caller alone never reaches 6. The site's 6 is keyed on the site alone, so other callers' proofs count against it too. Wait out its retry-after rather than retrying, because each refused retry also spends one of your own. - Stripe, Paddle, Lemon Squeezy and Shopify bar automated reading of their hosted checkouts, so those pages are never requested; the checks that need them are NOT_CHECKED quoting the rail. Test mode is still detected from the URL and the seller's page. - No JavaScript is executed. A price rendered only by JavaScript is invisible and reads NOT_CHECKED. - Behind a login, it reports "not reachable anonymously" and nothing stronger. - The hosted proof runs on Cloudflare, which forbids raw sockets to Cloudflare's own addresses, so nameservers on Cloudflare DNS read NOT_CHECKED on reachable.authoritative-answers from here.