Check many claims

Check up to 100 claims in one call. Results come back in the same order, one slot per claim, so a failed check never shifts the verdicts after it.

Last updated 12 September 2026

Check many claims

POST https://api.quorumtech.ch/attest/v1/attest/bulk

Check up to 100 claims in one call.

Checks a list of claims. The results array is always the same length as claims, and position i always describes claim i, so a failed check never shifts the verdicts after it. Each claim may carry its own evidence or name a batch. A claim naming a batch that has aged out fails in its own slot with batch_not_found and is not checked; the rest still run.

Spends as many claims of the daily budget as the array holds.

Use this when you already have the claims, for example one per sentence of a draft you split yourself, and want them checked in one round trip. Each entry is a full claim request: its own evidence, or a batchId, and its own options.

The results array is always the same length as claims, and position i describes claim i. A claim that fails fills its own slot with ok: false and an error, rather than being dropped, because callers map results back onto sentences by position and a dropped element would send them to edit the wrong sentence. For the same reason the call returns 200 whenever the request was well formed, even if every claim failed. Read ok before reading a verdict. INDETERMINATE lands as ok: false, so a failure to measure is never actioned as a finding.

If you have the document rather than a list of claims, prefer the draft review: extraction on the server finds the claims a writer does not perceive as claims, which is where the errors are.

{
  "claims": [
    {
      "claim": "FY2025 revenue was CHF 94.0m.",
      "evidence": [{ "id": "ev_1", "content": "Group revenue for FY2025 was CHF 94.0m, up from CHF 82.0m in the prior year." }]
    },
    {
      "claim": "Headcount grew in FY2025.",
      "evidence": [{ "id": "ev_1", "content": "Group revenue for FY2025 was CHF 94.0m, up from CHF 82.0m in the prior year." }]
    }
  ]
}

The second claim returns INSUFFICIENT_EVIDENCE: the evidence is about revenue and says nothing about headcount.

Request

A JSON body with these fields:

| Field | Type | Required | Description | | --- | --- | --- | --- | | claims | AttestRequest[] | yes | 1 to 100 items. | | claims[].claim | string | yes | The statement to check. One assertion reads best; split compound sentences. 1 to 4,000 characters. | | claims[].evidence | Evidence[] | no | The documents to check against, inline. Ids must be unique. At most 50 items. | | claims[].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_.-]+$. | | claims[].evidence[].content | string | yes | The evidence text. Total across all items is capped at 200,000 characters. | | claims[].evidence[].source | EvidenceSource | no | Where a piece of evidence came from. Shown in citations; never used to retrieve anything. | | claims[].batchId | string | no | Check against a batch loaded earlier instead of inline evidence. | | claims[].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". | | claims[].glossary | object of string | no | What the draft means by particular words. Definitions only; a glossary cannot assert that anything is true. | | claims[].reviewDate | string | no | The date the review is taken as of, so a claim about elapsed time is reproducible. At most 40 characters. | | claims[].config | object | no | | | claims[].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/bulk" \
  -H "Authorization: Bearer $QUORUM_API_KEY" \
  -H "content-type: application/json" \
  -d '{
  "claims": [
    {
      "claim": "FY2025 revenue was CHF 94.0m.",
      "evidence": [
        {
          "id": "ev_1",
          "content": "Group revenue for FY2025 was CHF 94.0m, up from CHF 82.0m in the prior year."
        }
      ]
    },
    {
      "claim": "Headcount grew in FY2025.",
      "evidence": [
        {
          "id": "ev_1",
          "content": "Group revenue for FY2025 was CHF 94.0m, up from CHF 82.0m in the prior year."
        }
      ]
    }
  ]
}'

Responses

200

Every claim was attempted. Check each result's ok before reading its verdict.

| Field | Type | Description | | --- | --- | --- | | results | BulkClaimResult[] | Same length and order as the request's claims. | | results[].index | integer | Position in the request's claims. | | results[].claim | string | | | results[].ok | boolean | | | results[].result | EvidenceModeResult or BatchModeResult | | | results[].error | object | Present when ok is false. | | results[].error.code | string | | | results[].error.message | string | | | summary | object | | | summary.total | integer | | | summary.supported | integer | | | summary.needsAttention | integer | Every checked claim whose verdict is not SUPPORTED. | | summary.failed | integer | Claims that could not be checked at all. |

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. | | 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. | | 500 | | Something failed on the server. |

Cost

Per claim in the array, one credit ($0.01) with its own evidence and two ($0.02) when it names a batch. Charged for the claims attempted; a request refused as a whole charges nothing.

Still need help?

Ask Quincy in the chat bubble below, or write to support@quorumtech.ch and we will help you directly.