---
title: "Assess"
method: POST
path: "/api/v1/assess"
tags: ["Assess"]
---

# Assess

`POST /api/v1/assess`

## Request

- Base URL: `https://lenz.io`
- URL: `https://lenz.io/api/v1/assess`
- Auth: HTTP bearer

Fast verdict via a 3-model panel (sync, ~10-25s).

Escalation contract: a ``claims[].claim`` text POSTed back verbatim to
``/verify`` within 24 hours is verified as-is — in normal operation it
does not return ``needs_input`` and its wording is not rewritten.

Two input forms, one response shape::

    claim / text  ─► ONE text. Lenz reads the claims in it, and each becomes a
                     row, up to 20 a call; the rest go back, unchecked and
                     free, in ``more_claims``.
    claims[]      ─► a LIST of up to 20 items, each one claim. One row per item, same order.
                     A compound item is assessed on its primary reading and
                     the rest is listed in that row's ``more_claims``.

The list form is the batch rung of the extract → assess → verify ladder:
one ``/assess`` call answers up to 20 of ``/extract``'s claims (it finds up
to 100) in about the time a single call takes, because every item is
assessed in parallel.

A verdict can be served from memory: a completed ``/verify`` of the exact
same claim text, or a prior ``/assess`` of it, within the last hour,
whichever account ran it — the verdict is a function of the input.
``verification_url`` is set only when the caller could read that
verification by id.

Billing: 1 credit per row that carries a verdict; error rows are free; a
duplicate item is a second row and a second credit (the panel runs once).

**Versions.** 200: `2026-10-11` receives `AssessOut`, `2026-05-13` receives `AssessOutLegacy`; 422: `2026-10-11` receives `ValidationErrorOut`, `2026-05-13` receives `ValidationErrorOutLegacy`; default: `2026-10-11` receives `ErrorOut`, `2026-05-13` receives `ErrorOutLegacy`.

## Headers

- `X-Lenz-API-Version` string

## Request body

- AssessIn: Request body for ``POST /assess``. Two forms. ``claim`` (or its alias ``text``) is ONE text: read once and expanded, so every claim found in it becomes a row (up to 20, one credit each; a text that makes more lists the rest in ``more_claims``). ``claims`` is a list of up to 20 items: exactly one row per item, in order — the batch rung of the extract → assess → verify ladder. Sending both is a 422.
  - `claim` string, nullable: The claim to check. A statement in natural language; several claims in one string are split and handled separately.
  - `text` string: Accepted alias for `claim`. Send one or the other; `text` is used when it has content.
  - `claims` string[], nullable: A list of up to 20 — one verdict row each, in order. Use this for the claims `/extract` returned; each item is one claim (≤2000 chars), not a document. Mutually exclusive with `claim`.
  - `language` string: ISO 639-1 code for the language of the verdict rows. Omitted: English. `auto`: detected from the submitted text (the same rule as lenz.io: a supported language, or English when the text is short, English or in a language we do not answer in). A code always wins. Responses carry the code that was used, never `auto`. With `claims`, `auto` picks ONE language for the whole request: the language more than half of the items of at least 20 letters agree on, else English; for a list in mixed languages send a code.
  - `suggest_rewrite` boolean: Also write `suggested_rewrite` on each row: the claim with its wrong part corrected, for a claim the check found False or Mostly False with high confidence. Off by default. It costs no extra credit and works in both forms, per row. The rewrite comes from the quick check's reasoning and is not itself verified: review it, or run it through `/verify`, before using it.

## Response `200`

OK

- AssessOut: Response body for ``POST /assess``. ``status`` is ``ok`` when at least one row carries a verdict (other rows may have failed), ``no_checkable_claim`` when no claim in the input could be checked against public evidence (every row, or the single text), and ``error`` when no row carries a verdict for another reason. A single text with no checkable claim answers ``claims: []`` with the reason in ``failure`` (the same block a failed row carries); ``failure`` is ``null`` otherwise.
  - `status` 'ok' | 'no_checkable_claim' | 'error', required
  - `claims` AssessClaimOut[]
    - `claim` string, required
    - `language` string, required
    - `status` 'completed' | 'failed', required
    - `verdict` 'True' | 'Mostly True' | 'Mixed' | 'Mostly False' | 'False' | 'No Public Record', nullable
    - `confidence` 'low' | 'medium' | 'high', nullable
    - `verification_url` string, nullable
    - `rationale` string, nullable
    - `dissent` string, nullable: Deprecated: always null.
    - `searched_pages` SearchedPageOut[]: Pages looked at while assessing this claim, as title and link.
      - `title` string, required
      - `url` string, required
    - `suggested_rewrite` string, nullable
    - `more_claims` string[]
    - `failure` FailureOut: Why an item failed, and what to do next. The same block everywhere an item fails: a verification, an /assess row, a review, a review's claim rows and citation checks. ``code`` is what failed, ``detail`` one sentence on it (the same sentence for the same code on every endpoint), ``hint`` what to send next (null when there is nothing to change), ``failure_class`` why, ``retryable`` whether sending the same request again can succeed, ``docs_url`` where that class is explained. API version ``2026-05-13`` sends each endpoint's earlier fields instead (flat ``error`` / ``failure_reason`` on a verification, ``error_code`` / ``hint`` on an /assess row, ``failure.failure_reason`` on a review).
      - `code` string, required: What failed, one vocabulary everywhere: `no_checkable_claim`, `page_unreadable`, `upstream_unavailable`, `internal`, `cancelled`, `no_citations`, `insufficient_credits` (a verification only ever says the first, the third, the fourth and `cancelled`). Branch on `retryable` for whether to resend, and on the input codes for what to say; fall through on a value you do not know. `no_checkable_claim`: no claim in the input could be checked against public evidence (an opinion, a forecast, a claim about a private person, a statement whose only source is unidentified; on a review, also claims found that could not be traced back to the text); `hint` says which. `page_unreadable`: the link /review was sent could not be read. Version `2026-05-13` spells `no_checkable_claim` as `no_claim` (/assess, /review) or `not_a_claim` (/extract, a verification), and keeps the earlier causes as codes (`timeout`, `framing_failed`, `assessment_failed`, `citation_check_failed`, `invalid_input`).
      - `detail` string, required: The cause, in one sentence (out of time, no row could be assessed, ...); the same sentence for the same cause everywhere.
      - `hint` string, nullable: What to send next; null when there is nothing to change.
      - `failure_class` 'upstream_unavailable' | 'invalid_input' | 'cancelled' | 'internal', required
      - `retryable` boolean, required
      - `docs_url` string, nullable, required
    - `identified_claims` string[]: Sent only to callers on `2026-05-13`; use `more_claims`.
  - `failure` FailureOut: Why an item failed, and what to do next. The same block everywhere an item fails: a verification, an /assess row, a review, a review's claim rows and citation checks. ``code`` is what failed, ``detail`` one sentence on it (the same sentence for the same code on every endpoint), ``hint`` what to send next (null when there is nothing to change), ``failure_class`` why, ``retryable`` whether sending the same request again can succeed, ``docs_url`` where that class is explained. API version ``2026-05-13`` sends each endpoint's earlier fields instead (flat ``error`` / ``failure_reason`` on a verification, ``error_code`` / ``hint`` on an /assess row, ``failure.failure_reason`` on a review).
    - `code` string, required: What failed, one vocabulary everywhere: `no_checkable_claim`, `page_unreadable`, `upstream_unavailable`, `internal`, `cancelled`, `no_citations`, `insufficient_credits` (a verification only ever says the first, the third, the fourth and `cancelled`). Branch on `retryable` for whether to resend, and on the input codes for what to say; fall through on a value you do not know. `no_checkable_claim`: no claim in the input could be checked against public evidence (an opinion, a forecast, a claim about a private person, a statement whose only source is unidentified; on a review, also claims found that could not be traced back to the text); `hint` says which. `page_unreadable`: the link /review was sent could not be read. Version `2026-05-13` spells `no_checkable_claim` as `no_claim` (/assess, /review) or `not_a_claim` (/extract, a verification), and keeps the earlier causes as codes (`timeout`, `framing_failed`, `assessment_failed`, `citation_check_failed`, `invalid_input`).
    - `detail` string, required: The cause, in one sentence (out of time, no row could be assessed, ...); the same sentence for the same cause everywhere.
    - `hint` string, nullable: What to send next; null when there is nothing to change.
    - `failure_class` 'upstream_unavailable' | 'invalid_input' | 'cancelled' | 'internal', required
    - `retryable` boolean, required
    - `docs_url` string, nullable, required
  - `more_claims` string[]: Claims found in a single `text` past the ones checked: one call checks at most 20, ranked most check-worthy first. Not checked and not charged; send them as `claims` (up to 20 a call) to check them. Always `[]` for the `claims` list form.

## Other responses

- `422`: A field to fix
- `default`: An error

---

[API](https://skmtc.dev/lenz/apis/lenz-ai-fact-checking-api.md) · [All operations](https://skmtc.dev/lenz/apis/lenz-ai-fact-checking-api/llms.txt) · [OpenAPI document](https://skmtc.dev/lenz/apis/lenz-ai-fact-checking-api/revisions/6150947324bf?raw)
