Check one claim
Check a single claim against evidence sent in the request or against a loaded batch, and get a verdict with the spans it rests on.
Last updated 12 September 2026
Check one claim
POST https://api.quorumtech.ch/attest/v1/attest
Checks a single claim against evidence passed inline, or against a batch loaded earlier with
POST /attest/v1/batch or POST /attest/v1/batches. Provide one or the other.
Spends one claim of the key's daily budget.
This is the call to start with. Send one assertion and the passages it was written from, and read the verdict, the supporting and contradicting span ids, the explanation and the provenance block. Send one assertion at a time: a compound sentence gets one verdict for the whole, which cannot say which half failed.
Provide evidence or batchId, never both. With evidence, one model call reads exactly what you sent. With a batchId from an earlier upload, Attest searches the batch for the passages that bear on the claim and returns them in cited with their text, so the citation needs no document on your side.
kind tells Attest what sort of statement it is checking. An assertion is checked against the evidence. A synthesis combines several facts. A judgement is an opinion, which evidence can inform but not settle. glossary defines what the draft means by a term and can never assert that anything is true. reviewDate fixes the date a claim about elapsed time is judged as of, so the answer is reproducible later.
{
"claim": "Revenue rose to CHF 94m and operating margin improved.",
"evidence": [
{
"id": "ev_1",
"content": "Group revenue for FY2025 was CHF 94.0m, up from CHF 82.0m in the prior year.",
"source": { "title": "FY2025 Annual Report" }
}
]
}
That example returns PARTIALLY_SUPPORTED: the revenue half holds on ev_1:0, and the margin half is unverified because the evidence says nothing about it. Change the claim to "Revenue rose to CHF 94m." for SUPPORTED.
Request
Provide either evidence or batchId. Attest never retrieves, so with neither there is nothing to judge against.
A JSON body with these fields:
| Field | Type | Required | Description |
| --- | --- | --- | --- |
| claim | string | yes | The statement to check. One assertion reads best; split compound sentences. 1 to 4,000 characters. |
| evidence | Evidence[] | no | The documents to check against, inline. Ids must be unique. At most 50 items. |
| evidence[].id | string | no | Your identifier for this item, unique within the request. Spans are cited as <id>:<ordinal>, for example ev_1:0. Assigned as ev_<n> when omitted. 1 to 64 characters. Pattern ^[A-Za-z0-9_.-]+$. |
| evidence[].content | string | yes | The evidence text. Total across all items is capped at 200,000 characters. |
| evidence[].source | EvidenceSource | no | Where a piece of evidence came from. Shown in citations; never used to retrieve anything. |
| evidence[].source.title | string | no | At most 500 characters. |
| evidence[].source.uri | string | no | At most 2,000 characters. |
| evidence[].source.author | string | no | At most 200 characters. |
| evidence[].source.publishedAt | string | no | When the source was published, in any recognisable date form. At most 64 characters. |
| evidence[].source.retrievedAt | string | no | At most 64 characters. |
| batchId | string | no | Check against a batch loaded earlier instead of inline evidence. |
| kind | assertion or synthesis or judgement | no | What kind of statement this is, which decides how it is checked. An assertion is checked against the evidence; a synthesis combines several facts; a judgement is an opinion, which evidence can inform but not settle. Default "assertion". |
| glossary | object of string | no | What the draft means by particular words. Definitions only; a glossary cannot assert that anything is true. |
| reviewDate | string | no | The date the review is taken as of, so a claim about elapsed time is reproducible. At most 40 characters. |
| config | object | no | |
| config.explain | boolean | no | Include the span-cited explanation and the audit block. Off returns the verdict alone; the spans come from the reading, so they are empty too. Default true. |
Example request
curl -X POST "https://api.quorumtech.ch/attest/v1/attest" \
-H "Authorization: Bearer $QUORUM_API_KEY" \
-H "content-type: application/json" \
-d '{
"claim": "Revenue rose to CHF 94m and operating margin improved.",
"evidence": [
{
"id": "ev_1",
"content": "Group revenue for FY2025 was CHF 94.0m, up from CHF 82.0m in the prior year.",
"source": {
"title": "FY2025 Annual Report"
}
}
]
}'
Responses
200
A verdict was produced.
Every shape below carries these fields:
| Field | Type | Description |
| --- | --- | --- |
| id | string | This verification's id. |
| verdict | SUPPORTED or PARTIALLY_SUPPORTED or INSUFFICIENT_EVIDENCE or CONTRADICTED or DISPUTED or INDETERMINATE | Always relative to the supplied evidence. SUPPORTED: consistent with the documents. PARTIALLY_SUPPORTED: part of the claim is established and part is not; the one to watch. INSUFFICIENT_EVIDENCE: the documents do not speak to it. CONTRADICTED: the documents say otherwise. DISPUTED: the documents disagree with each other. INDETERMINATE: Attest could not measure; returned with 503, never as a finding. |
| usage | Usage | What this response cost at the model provider. Zeros for a replay. |
| usage.calls | integer | Completions made. |
| usage.promptTokens | integer | Tokens sent. |
| usage.completionTokens | integer | Tokens returned. |
| usage.cachedTokens | integer | Prompt tokens served from the provider's cache. |
| usage.latencyMs | integer | Wall time waiting on the provider. |
| usage.fellBack | integer | Calls the preferred tier shed to the fallback. |
| claim | string | |
| supportingSpans | string[] | Span ids (<evidence id>:<ordinal>) that support the claim. |
| contradictingSpans | string[] | |
| degraded | string[] | Anything that could not run as designed, named. Empty on a clean run. |
| provenance | Provenance | Every version and hash that produced the answer, so it can be replayed and audited. |
| provenance.measurementHash | string | SHA-256 over the canonical claim, the evidence and the measurements. |
| provenance.policyHash | string | SHA-256 over the deterministic decision policy that produced the verdict. |
| provenance.rulesApplied | string[] | The reading rules routed to this claim. |
| provenance.promptVersion | string | |
| provenance.scoringVersion | string | |
| provenance.serviceVersion | string | |
| provenance.model | string | |
| provenance.createdAt | string (date-time) | |
| provenance.mode | evidence or batch-agent | |
| provenance.cachedFrom | string | The id of the response whose measurement this one replays; createdAt is that measurement's time. A replay runs no models and costs nothing. |
| audit.findings | string[] | |
Evidence mode result
The result of checking against inline evidence.
| Field | Type | Description |
| --- | --- | --- |
| mode | evidence | |
| explanation | object | The span-cited explanation. Null when config.explain was false. May be null. |
| explanation.axes | object of any | Per validation axis, the propositions of the claim and how each was marked, citing span ids. |
| explanation.citedSpans | string[] | |
| explanation.availableSpans | integer | |
| explanation.axesRun | string[] | |
| explanation.axesExpected | string[] | |
| audit | object | Deterministic checks over the explanation. May be null. |
| audit.referentialIntegrity | number | Share of citations that name real spans, from 0 to 1. |
| audit.explanationTrust | number | |
| audit.explanationDisagrees | boolean | True when the explanation and the verdict point different ways; the verdict stands, the explanation is flagged. |
Batch mode result
The result of checking against a loaded batch, where Attest searched the documents itself.
| Field | Type | Description |
| --- | --- | --- |
| mode | batch | |
| cited | object[] | The spans the verdict rests on, with their text and which way each cuts. |
| cited[].id | string | |
| cited[].section | string | The heading the span sits under, when the document had one. May be null. |
| cited[].text | string | |
| cited[].role | supports or contradicts | |
| explanation | object | |
| explanation.reasoning | string | |
| explanation.unverifiedAssertions | string[] | The parts of the claim nothing in the batch establishes. The actionable output. |
| explanation.searchedThoroughly | boolean | |
| explanation.trace | object[] | What was searched and read, in order. |
| explanation.trace[].tool | string | |
| explanation.trace[].input | string | |
| explanation.trace[].resultSummary | string | |
| explanation.steps | integer | |
| audit | object | |
| audit.referentialIntegrity | number | |
| batch | object | |
| batch.id | string | |
| batch.batchHash | string | |
| batch.documents | integer | |
| batch.spans | integer | |
Errors
The body is { "error": { "code", "message" } }; the full catalogue with what to do about each code is on the Errors page.
| Status | Codes | When |
| --- | --- | --- |
| 400 | | The request does not match the schema. error.issues names each failing field. |
| 401 | | The key is missing, not recognised, or revoked. |
| 402 | payment_required, credits_exhausted, remaining, needed | The workspace has no active API subscription (payment_required), or is prepaid and has no credits left for this request (credits_exhausted, with remaining and needed). Manage billing and add credits at https://developer.quorumtech.ch/billing. |
| 403 | | The key is not scoped to Attest. |
| 404 | | The batchId names no loaded batch. Batches age out; upload again. |
| 429 | rate_limited, claims_rate_limited, claim_budget_exhausted, monthly_cap_reached, cap | Over the key's requests-per-minute limit (rate_limited), its claims-per-minute ceiling (claims_rate_limited), its claims-per-day budget (claim_budget_exhausted), or, for a postpaid workspace, its monthly credit cap (monthly_cap_reached, with cap and resetsAt). Retry-After says when to try again; the daily budget resets at midnight UTC and the cap on the first of the month. |
| 502 | | The model provider behind Attest failed. Retry. |
| 503 | | Attest could not measure (INDETERMINATE), which is a server-side failure rather than a finding about the claim, or the evaluator is not configured. Never read this as a verdict. |
Cost
One credit ($0.01) with the evidence in the request, two ($0.02) against a loaded batch, explained or not. A refused or failed request charges nothing.
Related articles
Fetch a page in one call
The same work as the extract call, with the request held open until the page is done and the Markdown returned directly.
Watch an extraction
Server-sent events for one job: its state now, every change after it, and the finished page. Closes when the job does.
Read an extraction's progress
One frame of a job's state without its Markdown, for a progress bar that should not carry a page's text with every poll.
Collect an extraction
Poll a job that answered 202. Returns its state while it runs and the Markdown once it is done.
Still need help?
Ask Quincy in the chat bubble below, or write to support@quorumtech.ch and we will help you directly.