Verify a quote against text you hold
Last updated: 2026-10-13
POST /v1/verify/text-quote checks a quote against text the caller already has: a file it read, a tool result, a document. Nothing is fetched, so there are no robots, DNS or bot-wall failures. The answer is exact, fuzzy or none, with a score, offsets and context, under a signed receipt. Price: US$0.005 per call.
Use it when the source is already in hand. To check a quote against a live web page, use Verify a quote, which fetches the page.
Request
{
"text": "Refunds are paid within 14 days of purchase, to the card that was used.",
"quote": "refunds are paid within 14 days",
"match": "fuzzy",
"case_sensitive": false
}
| Field | Required | Meaning |
|---|---|---|
text | yes | the source text, as sent: a non-empty string of at most 50,000 characters (code points) and 64 KB of UTF-8 |
quote | yes | the quote, at most 1,000 characters after normalisation |
start, end | no | both or neither: a slice of text to check, in characters (code points), 0-based, end exclusive, at most 1,000 characters |
match | no | fuzzy (default) also accepts small differences; exact needs the same text after normalisation; passages treats the quote as a paraphrased claim and returns the passages of the text that share its words (not with start and end) |
case_sensitive | no | default false; must be false with passages |
threshold | no | fuzzy similarity needed, 0.5 to 1, default 0.9 |
url is refused: this route never fetches. Every field is checked before payment, so a bad request is answered with 400 and not charged.
Offsets
Two coordinate systems, named differently:
startandendin the request are raw code-point offsets intotextas sent. With them, only that slice is matched, so the answer is whether the text at those offsets says the quote.result.declaredechoes them withslice_sha256(the hash of the raw slice) andslice_matches.result.startandresult.endin a search (no offsets sent) are normalised: offsets into the text after normalising (curly quotes, spaces and case folding for matching, as onverify/quote).normalised_sha256is the hash of that normalised text.
Response
{
"result": {
"match": "fuzzy", "score": 0.972, "start": 0, "end": 34,
"context": "Refunds are paid within 14 days of purchase",
"occurrences": 1, "normalised_sha256": "…",
"source": { "kind": "supplied", "text_sha256": "…", "code_points": 79 }
},
"injection_flags": [],
"advice": "The supplied text contains a close match to this quote, with small differences. This says nothing about where the text came from.",
"receipt": "eyJ…",
"tier": "paid"
}
injection_flagslists instruction-like text found in the supplied text. Agents paste untrusted output, so read them.- The receipt is the caller's claim: it attests the hash of the text (
source.text_sha256) and the match, not that the text came from any particular site.
Errors
A 400 with invalid_request covers: an unknown field (including url), a missing or empty text or quote, start or end alone, a non-integer or negative offset, start not below end or end past the text (reason offset_out_of_range), a slice over 1,000 characters, text over 50,000 characters, a lone surrogate in text or quote, and offsets with match passages. A body over 64 KB gets 413. A fuzzy match too costly for the matcher gets 422 match_too_costly, not charged.