---
title: "certificate.timestamped"
method: POST
path: "certificate.timestamped"
---

# certificate.timestamped

`POST certificate.timestamped` (webhook)

Fires when a covered verification's qualified timestamp lands, minutes after verification.completed. If you publish automatically, publish on this event: the warranty covers a publication that FOLLOWS the timestamp, and verification.completed fires while the qualified timestamp is still pending.

## Payload

- WebhookPayload: Body the customer's endpoint receives for a verification event. One envelope for every event: ``event``, ``event_id`` (the same on every retry: deduplicate on it), ``task_id`` (pollable on ``GET /verify/status/{task_id}``), ``verification_id`` once the verification exists, ``status``, and the body polling returns at that moment under ``verification``. Keys a payload does not carry are absent, not null. Always signed with HMAC-SHA256 over the raw body bytes; signature rides in the ``X-Lenz-Signature: sha256=<hex>`` header, and the version the body was built in in ``X-Lenz-API-Version``. A webhook follows the version of the request that asked for it; version ``2026-05-13`` sends the earlier flat body (``result`` / ``needs_input`` / ``error`` beside ``task_id``, no ``event_id``). The ``attempt`` field is 1-indexed and includes the initial delivery, so values run 1 through 4 (initial + 3 retries).
  - `event` string, required
  - `event_id` string, required
  - `task_id` string, required
  - `verification_id` string, nullable
  - `batch_id` string, nullable
  - `review_id` string, nullable
  - `status` string, required
  - `verification` StatusOut: Body of ``GET /verify/status/{task_id}``. Five shapes keyed on ``status``, and only the fields belonging to the current one are present —``processing`` carries ``progress``, ``needs_input`` carries ``reason``, ``claims`` and ``hint``, ``completed`` carries ``result``, ``failed`` carries ``failure``, and ``cancelled`` (the run was stopped with ``POST /verify/{task_id}/cancel``) carries nothing more: it was not charged and has no verification. Branch on ``status`` and read the fields for that branch; absent is meaningful, so do not treat a missing key as an empty one. ``task_id`` is echoed on every shape, so a caller polling several verifications in one loop can tell the replies apart without threading the id through their own call site.
    - `status` 'processing' | 'needs_input' | 'completed' | 'failed' | 'cancelled', required
    - `task_id` string, required
    - `progress` ProgressOut: Where a running verification has got to. Advisory — never results. ``step`` is a closed set, so it is safe to switch on. ``index`` is the 1-based stage position (0 while ``starting``) out of ``total``; read ``total`` off the response rather than hard-coding it, since stages may be added. ``index`` is stage POSITION, not elapsed work: the stages are uneven, so a client rendering it as a bar will see it sit on ``research`` for roughly half the run. ``elapsed_seconds`` is a measurement of how long the run has been going, never an estimate of what is left.
      - `step` 'starting' | 'framing' | 'research' | 'debate' | 'adjudication' | 'conclusion', required
      - `index` integer, required
      - `total` integer, required
      - `elapsed_seconds` integer, required
      - `poll_after_seconds` integer, required
    - `reason` 'multi_claim', nullable
    - `claims` ClaimOptionOut[], nullable
      - `claim` string, required
      - `domain` string
      - `text` string: Sent only to callers on `2026-05-13`; use `claim`.
    - `result` ClaimDetailOut: Full verification report. Slim top-level (verdict + confidence + lenz_score + sources). Audit detail (panel reasoning, debate, individual panelist assessments) lives under ``audit``. Same field vocabulary as ``VerificationListItemOut`` (list view) and ``AssessClaimOut`` (fast verdict). A consumer that branches on ``verdict`` or ``confidence`` reads the same field name regardless of which endpoint produced the payload.
      - `verification_id` string, required
      - `claim` string, required
      - `visibility` string
      - `depth` string
      - `domain` string
      - `entities` EntityRef[]
        - `name` string, required
        - `qid` string, nullable
      - `presumed_intent` string
      - `verdict` string: `True`, `Mostly True`, `Mixed`, `Mostly False` or `False`, or `No Public Record`: Lenz found no public record that settles the claim, which does not make it false. It has no `lenz_score` (null), a `confidence`, and is never warranted. Version `2026-05-13` never receives it: it reads such a run as a failure (`research_empty` when no source was found, else `research_insufficient`).
      - `confidence` string
      - `lenz_score` integer, nullable: 1-10; null for `No Public Record`.
      - `key_finding` string
      - `executive_summary` string
      - `warnings` string[]
      - `suggested_rewrite` string, nullable: A suggested rewrite of `claim` that this verification's findings support, to use in place of the original sentence. It has not been verified itself: before using it, review it or run it through `/verify`. `null` for a true claim, when no correction is established, and on verifications that predate the field. On every verification, single or listed; not on `/assess` rows.
      - `created_at` string
      - `completed_at` string: When the verification finished (ISO 8601). Always set on a completed verification; a rerun moves it. API version `2026-05-13` sends `modified_at` instead: this time, but only when it falls on a later UTC calendar day than `created_at`, else null.
      - `sources` SourceOut[]
        - `source_name` string
        - `title` string
        - `url` string
        - `snippet` string: The sentence(s) quoted from the source page, verbatim and in the page's own language, with ` … ` between separate passages. A few sources carry no verified quote — for those it is the surrounding passage instead, which may run longer and contain line breaks.
        - `snippet_language` string, nullable: The language of `snippet` (the source page's own language) as an ISO 639-1 code (e.g. `uk`, `pt`), when it is not English; null for English or when unknown. The verdict's own language is `language`.
        - `date` string
      - `audit` AuditOut: Audit / explainability block — for callers that need to show their work. ``panel_agreement`` is derived from the panel: ``unanimous`` (all agree), ``majority`` (score spread <= 2), or ``split`` — over every reviewer that voted, so a panel that called in Reviewers D and E is counted whole. For "No Public Record" it counts the no-record votes (``unanimous`` when every voting reviewer voted no-record, ``majority`` when most did), and is ``''`` when no panel voted (decided by research alone); its debate is empty.
        - `adjudication_summary` string
        - `assessments` AssessmentOut[]
          - `panelist_name` string
          - `focus_area` string
          - `score` number, nullable
          - `reasoning` string
          - `warnings` string[]
        - `debate_pro` DebateSideOut: One side of the debate (pro or con). Nested under ``audit``.
          - `role` string
          - `argument` string
          - `rebuttal` string
        - `debate_con` DebateSideOut: One side of the debate (pro or con). Nested under ``audit``.
          - `role` string
          - `argument` string
          - `rebuttal` string
        - `panel_agreement` string
      - `language` string, required
      - `coverage` CoverageOut: Whether this verdict carries a warranty, and if not, why not. Present only when covered verification is enabled. It describes the pair (this account, this analysis), not the analysis alone: two accounts can hold two certificates over one cached verdict, so the block one customer sees is never the block another sees. ``reasons`` is empty exactly when ``status`` is not ``uncovered``. The vocabulary is closed and deliberately smaller than the set of rules behind the decision: ``plan`` and ``depth`` are actionable, ``account`` means the account turned certificates off (Pro and Scale), ``verdict`` is a product rule callers design around, ``quality`` covers everything a caller can neither act on nor define, and ``withdrawn`` / ``issue_failed`` are statements about Lenz rather than about the caller's claim.
        - `status` 'covered' | 'uncovered' | 'pending_timestamp'
        - `reasons` string[]
        - `certificate_id` string, nullable
        - `certificate_url` string, nullable
        - `as_of` string, nullable
        - `currency` string
        - `cap` integer
        - `aggregate` integer
        - `terms_version` 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
    - `hint` string, nullable
  - `coverage` CoverageOut: Whether this verdict carries a warranty, and if not, why not. Present only when covered verification is enabled. It describes the pair (this account, this analysis), not the analysis alone: two accounts can hold two certificates over one cached verdict, so the block one customer sees is never the block another sees. ``reasons`` is empty exactly when ``status`` is not ``uncovered``. The vocabulary is closed and deliberately smaller than the set of rules behind the decision: ``plan`` and ``depth`` are actionable, ``account`` means the account turned certificates off (Pro and Scale), ``verdict`` is a product rule callers design around, ``quality`` covers everything a caller can neither act on nor define, and ``withdrawn`` / ``issue_failed`` are statements about Lenz rather than about the caller's claim.
    - `status` 'covered' | 'uncovered' | 'pending_timestamp'
    - `reasons` string[]
    - `certificate_id` string, nullable
    - `certificate_url` string, nullable
    - `as_of` string, nullable
    - `currency` string
    - `cap` integer
    - `aggregate` integer
    - `terms_version` string
  - `attempt` integer, required
  - `delivered_at` string, required

## Acknowledgement `2XX`

Your endpoint should return 2xx within 5 seconds. Non-2xx triggers retries at 10s / 60s / 600s (3 retries after the initial delivery, 4 attempts total).

---

[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)
