{"openapi":"3.1.0","info":{"title":"ProofFetch Agent API","version":"0.2.0","contact":{"name":"Bryan","email":"bryan@tryneverclosed.com"},"description":"Evidence-bearing public web extraction with a free preflight and Stripe MPP paid fulfillment.","x-guidance":"ProofFetch returns the cited text of one public web page. Start free with POST https://prooffetch.steellantern.com/v1/preflight {\"url\":\"https://example.com/\"} (fetchability, hashes and a short preview). For the full text, POST https://prooffetch.steellantern.com/v1/evidence {\"url\":\"...\",\"idempotencyKey\":\"<22-128 random chars>\"}: pay the 402 Stripe MPP challenge ($0.50 buys this page plus a key holding 49 more), or send Authorization: Bearer <key> from POST https://prooffetch.steellantern.com/v1/keys/free (free) or the $5 card pack. Reuse the same idempotencyKey on retries. Cite paragraphs by their ids."},"servers":[{"url":"https://prooffetch.steellantern.com"}],"x-service-info":{"categories":["web-data","agent-security","research"],"docs":{"llms":"https://prooffetch.steellantern.com/llms.txt","offer":"https://prooffetch.steellantern.com/offer","quickstart":"https://prooffetch.steellantern.com/connect"},"status":"available"},"paths":{"/v1/preflight":{"get":{"operationId":"proofFetchPreflightGet","summary":"Same free preflight as POST, for browsers and simple clients.","parameters":[{"name":"url","in":"query","required":true,"schema":{"type":"string","format":"uri","maxLength":2048}},{"name":"maxChars","in":"query","required":false,"schema":{"type":"integer","minimum":1000,"maximum":50000,"default":30000}}],"responses":{"200":{"description":"Fetch and extraction preflight with a free text preview (preview.paragraphs, about the first 1,000 characters).","content":{"application/json":{"schema":{"type":"object","required":["schema","finalUrl","integrity","preview"],"properties":{"schema":{"type":"string"},"retrievedAt":{"type":"string","format":"date-time"},"requestedUrl":{"type":"string","format":"uri"},"finalUrl":{"type":"string","format":"uri"},"redirects":{"type":"array","items":{"type":"object"}},"http":{"type":"object","properties":{"status":{"type":"integer"},"contentType":{"type":"string"},"etag":{"type":["string","null"]},"lastModified":{"type":["string","null"]},"bytes":{"type":"integer"}}},"integrity":{"type":"object","properties":{"rawSha256":{"type":"string","pattern":"^[a-f0-9]{64}$"},"contentSha256":{"type":"string","pattern":"^[a-f0-9]{64}$"}}},"security":{"type":"object","description":"Prompt-injection indicators found in the page text (a signal, not proof)."},"document":{"type":"object","properties":{"title":{"type":["string","null"]},"paragraphCount":{"type":"integer"}}},"preview":{"type":"object","properties":{"paragraphs":{"type":"array","items":{"type":"object","required":["id","text"],"properties":{"id":{"type":"string","description":"Stable paragraph id such as p1, used for citations."},"text":{"type":"string"}}}}}},"paidFulfillment":{"type":"object"}}}}}},"400":{"description":"Invalid or forbidden URL.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Stable machine-readable code."},"message":{"type":"string","description":"Plain-language explanation and next step."},"example":{"type":"object","description":"A valid request body, on input errors."},"docs":{"type":"string"}}}}}},"429":{"description":"Free preflight rate limit exceeded.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Stable machine-readable code."},"message":{"type":"string","description":"Plain-language explanation and next step."},"example":{"type":"object","description":"A valid request body, on input errors."},"docs":{"type":"string"}}}}}}},"security":[]},"post":{"operationId":"proofFetchPreflight","summary":"Inspect a public URL without receiving its extracted text.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["url"],"additionalProperties":false,"properties":{"url":{"type":"string","format":"uri","maxLength":2048,"description":"Public HTTP(S) document URL. No credentials, private networks, authenticated pages or browser rendering.","examples":["https://example.com/"]},"maxChars":{"type":"integer","minimum":1000,"maximum":50000,"default":30000,"description":"Maximum normalized characters to extract. Free preflight returns metadata plus a preview of about the first 1,000 characters.","examples":[30000]}}}}}},"responses":{"200":{"description":"Fetch and extraction preflight with a free text preview (preview.paragraphs, about the first 1,000 characters).","content":{"application/json":{"schema":{"type":"object","required":["schema","finalUrl","integrity","preview"],"properties":{"schema":{"type":"string"},"retrievedAt":{"type":"string","format":"date-time"},"requestedUrl":{"type":"string","format":"uri"},"finalUrl":{"type":"string","format":"uri"},"redirects":{"type":"array","items":{"type":"object"}},"http":{"type":"object","properties":{"status":{"type":"integer"},"contentType":{"type":"string"},"etag":{"type":["string","null"]},"lastModified":{"type":["string","null"]},"bytes":{"type":"integer"}}},"integrity":{"type":"object","properties":{"rawSha256":{"type":"string","pattern":"^[a-f0-9]{64}$"},"contentSha256":{"type":"string","pattern":"^[a-f0-9]{64}$"}}},"security":{"type":"object","description":"Prompt-injection indicators found in the page text (a signal, not proof)."},"document":{"type":"object","properties":{"title":{"type":["string","null"]},"paragraphCount":{"type":"integer"}}},"preview":{"type":"object","properties":{"paragraphs":{"type":"array","items":{"type":"object","required":["id","text"],"properties":{"id":{"type":"string","description":"Stable paragraph id such as p1, used for citations."},"text":{"type":"string"}}}}}},"paidFulfillment":{"type":"object"}}}}}},"400":{"description":"Invalid or forbidden URL, or malformed request.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Stable machine-readable code."},"message":{"type":"string","description":"Plain-language explanation and next step."},"example":{"type":"object","description":"A valid request body, on input errors."},"docs":{"type":"string"}}}}}},"413":{"description":"Request body or upstream page too large (request_too_large, response_too_large).","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Stable machine-readable code."},"message":{"type":"string","description":"Plain-language explanation and next step."},"example":{"type":"object","description":"A valid request body, on input errors."},"docs":{"type":"string"}}}}}},"415":{"description":"The page uses an unsupported content type (content_type_unsupported).","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Stable machine-readable code."},"message":{"type":"string","description":"Plain-language explanation and next step."},"example":{"type":"object","description":"A valid request body, on input errors."},"docs":{"type":"string"}}}}}},"422":{"description":"The public resource could not be fetched or extracted (for example upstream_http_404).","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Stable machine-readable code."},"message":{"type":"string","description":"Plain-language explanation and next step."},"example":{"type":"object","description":"A valid request body, on input errors."},"docs":{"type":"string"}}}}}},"429":{"description":"Free preflight rate limit exceeded (free_rate_limit_exceeded).","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Stable machine-readable code."},"message":{"type":"string","description":"Plain-language explanation and next step."},"example":{"type":"object","description":"A valid request body, on input errors."},"docs":{"type":"string"}}}}}},"502":{"description":"Upstream fetch failed (upstream_timeout, upstream_unreachable, redirect_location_missing).","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Stable machine-readable code."},"message":{"type":"string","description":"Plain-language explanation and next step."},"example":{"type":"object","description":"A valid request body, on input errors."},"docs":{"type":"string"}}}}}}},"security":[]}},"/v1/evidence":{"post":{"operationId":"proofFetchEvidence","summary":"Buy cited web evidence at $0.01 a page: one prepaid credit from a ProofFetch key, or a $0.50 Stripe MPP payment that returns this page plus a key holding 49 more.","description":"The upstream resource is fetched and extracted successfully before the server issues a payment challenge. Alternatively send Authorization: Bearer <ProofFetch key> to use one prepaid credit instead of an MPP payment; 401 credit_key_invalid or 402 credits_exhausted if the key cannot pay. A free key (POST /v1/keys/free) works the same way for its 25 free extractions; when they are used up the answer is 402 free_credits_exhausted with a link to buy the paid pack.","x-payment-info":{"price":{"mode":"fixed","currency":"USD","amount":"0.50"},"protocols":[{"mpp":{"method":"stripe","intent":"charge","currency":"usd"}}],"offers":[{"amount":"50","currency":"usd","intent":"charge","method":"stripe","description":"Fetches a public web resource and returns paragraph-addressable content, SHA-256 integrity receipts, provenance metadata, and transparent prompt-injection indicators."}]},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["url","idempotencyKey"],"additionalProperties":false,"properties":{"url":{"type":"string","format":"uri","maxLength":2048,"description":"Public HTTP(S) document URL. No credentials, private networks, authenticated pages or browser rendering.","examples":["https://example.com/"]},"maxChars":{"type":"integer","minimum":1000,"maximum":50000,"default":30000,"description":"Maximum normalized characters to extract. Free preflight returns metadata plus a preview of about the first 1,000 characters.","examples":[30000]},"idempotencyKey":{"type":"string","pattern":"^[A-Za-z0-9_-]{22,128}$","description":"High-entropy caller-generated retry and recovery key."}}}}}},"responses":{"200":{"description":"Paid cited evidence with Payment-Receipt header.","content":{"application/json":{"schema":{"type":"object","required":["schema","finalUrl","document","integrity"],"properties":{"schema":{"type":"string"},"retrievedAt":{"type":"string","format":"date-time"},"requestedUrl":{"type":"string","format":"uri"},"finalUrl":{"type":"string","format":"uri"},"redirects":{"type":"array","items":{"type":"object"}},"http":{"type":"object","properties":{"status":{"type":"integer"},"contentType":{"type":"string"},"etag":{"type":["string","null"]},"lastModified":{"type":["string","null"]},"bytes":{"type":"integer"}}},"integrity":{"type":"object","properties":{"rawSha256":{"type":"string","pattern":"^[a-f0-9]{64}$"},"contentSha256":{"type":"string","pattern":"^[a-f0-9]{64}$"}}},"security":{"type":"object","description":"Prompt-injection indicators found in the page text (a signal, not proof)."},"document":{"type":"object","properties":{"title":{"type":["string","null"]},"paragraphCount":{"type":"integer"},"paragraphs":{"type":"array","items":{"type":"object","required":["id","text"],"properties":{"id":{"type":"string","description":"Stable paragraph id such as p1, used for citations."},"text":{"type":"string"}}}},"contentText":{"type":"string","description":"The text with [p1] style markers for citation."}}},"commerce":{"type":"object","description":"sku, price, request and content hashes, and the payment receipt."},"callBundle":{"type":"object","description":"After an MPP payment: a key holding the remaining extractions of the 50 bought, shown in this response only."}}}}}},"400":{"description":"Invalid or forbidden URL, malformed request, or invalid idempotency key.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Stable machine-readable code."},"message":{"type":"string","description":"Plain-language explanation and next step."},"example":{"type":"object","description":"A valid request body, on input errors."},"docs":{"type":"string"}}}}}},"402":{"description":"Stripe MPP payment challenge."},"409":{"description":"idempotency_key_conflict, idempotency_credential_conflict, or fulfillment_in_progress (retry after the Retry-After header, 120 seconds).","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Stable machine-readable code."},"message":{"type":"string","description":"Plain-language explanation and next step."},"example":{"type":"object","description":"A valid request body, on input errors."},"docs":{"type":"string"}}}}}},"413":{"description":"Request body or upstream page too large (request_too_large, response_too_large); no payment challenge was issued.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Stable machine-readable code."},"message":{"type":"string","description":"Plain-language explanation and next step."},"example":{"type":"object","description":"A valid request body, on input errors."},"docs":{"type":"string"}}}}}},"415":{"description":"The page uses an unsupported content type (content_type_unsupported); no payment challenge was issued.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Stable machine-readable code."},"message":{"type":"string","description":"Plain-language explanation and next step."},"example":{"type":"object","description":"A valid request body, on input errors."},"docs":{"type":"string"}}}}}},"422":{"description":"The public resource could not be extracted; no payment challenge was issued.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Stable machine-readable code."},"message":{"type":"string","description":"Plain-language explanation and next step."},"example":{"type":"object","description":"A valid request body, on input errors."},"docs":{"type":"string"}}}}}},"429":{"description":"Unpaid request rate limit exceeded (free_rate_limit_exceeded). Requests carrying a payment credential are not limited.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Stable machine-readable code."},"message":{"type":"string","description":"Plain-language explanation and next step."},"example":{"type":"object","description":"A valid request body, on input errors."},"docs":{"type":"string"}}}}}},"500":{"description":"Fulfillment failed after payment was attempted (evidence_fulfillment_failed). Retry the identical request with its original idempotency key and payment credential; do not create a new key.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Stable machine-readable code."},"message":{"type":"string","description":"Plain-language explanation and next step."},"example":{"type":"object","description":"A valid request body, on input errors."},"docs":{"type":"string"}}}}}},"502":{"description":"Upstream fetch failed (upstream_timeout, upstream_unreachable, redirect_location_missing); no payment challenge was issued.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Stable machine-readable code."},"message":{"type":"string","description":"Plain-language explanation and next step."},"example":{"type":"object","description":"A valid request body, on input errors."},"docs":{"type":"string"}}}}}},"503":{"description":"Paid fulfillment has not launched.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Stable machine-readable code."},"message":{"type":"string","description":"Plain-language explanation and next step."},"example":{"type":"object","description":"A valid request body, on input errors."},"docs":{"type":"string"}}}}}}},"security":[]}},"/v1/support":{"post":{"operationId":"proofFetchOpenSupportCase","summary":"Open a privacy-preserving technical or payment support case.","description":"Returns a one-time access token. Save it; the service stores only its SHA-256 hash.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["message"],"properties":{"message":{"type":"string","minLength":20,"maxLength":1200,"description":"Non-sensitive payment or technical issue. Do not include credentials, payment credentials, email addresses, or phone numbers."},"requestSha256":{"type":"string","pattern":"^[a-f0-9]{64}$"},"contentSha256":{"type":"string","pattern":"^[a-f0-9]{64}$"},"paymentReference":{"type":"string","pattern":"^[A-Za-z0-9_-]{3,128}$"}}}}}},"responses":{"201":{"description":"Support case opened; response includes case ID and access token.","content":{"application/json":{"schema":{"type":"object","properties":{"caseId":{"type":"string"},"accessToken":{"type":"string","description":"Shown once."}}}}}},"400":{"description":"Invalid, oversize, or sensitive-data-containing request."},"429":{"description":"Support intake rate limit exceeded."}},"security":[]}},"/v1/credits":{"get":{"operationId":"proofFetchCredits","summary":"Remaining prepaid extraction credits for a ProofFetch key.","security":[{"prepaidKey":[]}],"responses":{"200":{"description":"kind (free or paid), keyPrefix, creditsTotal and creditsRemaining.","content":{"application/json":{"schema":{"type":"object","properties":{"kind":{"type":"string","enum":["free","paid"]},"keyPrefix":{"type":"string"},"creditsTotal":{"type":"integer"},"creditsRemaining":{"type":"integer"}}}}}},"401":{"description":"Missing or invalid key (credit_key_invalid)."}}}},"/v1/keys/free":{"post":{"operationId":"proofFetchFreeKey","summary":"Get a free ProofFetch key holding 25 full extractions. No card, no request body.","description":"The key is in the response once; only its SHA-256 hash is stored. One free key per network per month (checked against a one-way hash of the network address, never the raw IP), and at most 200 free keys a day across all users. Free credits are separate from paid credits.","responses":{"201":{"description":"key, kind (\"free\"), credits, use, balance and whenUsedUp.","content":{"application/json":{"schema":{"type":"object","required":["key","credits"],"properties":{"key":{"type":"string","description":"Shown once."},"kind":{"type":"string","const":"free"},"credits":{"type":"integer"},"notice":{"type":"string"},"use":{"type":"string"},"balance":{"type":"string","format":"uri"},"whenUsedUp":{"type":"string"}}}}}},"400":{"description":"The network address could not be read (free_key_network_unknown)."},"429":{"description":"This network already has a free key this month (free_key_network_used), today's free keys are all given out (free_key_daily_cap), or too many requests (free_rate_limit_exceeded)."}},"security":[]}}},"components":{"securitySchemes":{"prepaidKey":{"type":"apiKey","in":"header","name":"Authorization","description":"Sent as Authorization: Bearer <key>. A ProofFetch key bought with a card (500 extractions for $5.00) at https://prooffetch.steellantern.com/#buy."}}}}