> This page is for version v2026-02-09 (default).
> For other versions, use one of these documentation indexes:
> - v2026-02-09 (default): https://docs.extend.ai/2026-02-09/llms.txt
> - v2025-04-21: https://docs.extend.ai/2025-04-21/llms.txt
> - v2024-12-23: https://docs.extend.ai/2024-12-23/llms.txt

> ## Documentation Index
> Fetch the complete documentation index at: https://docs.extend.ai/llms.txt
> Use this file to discover all available pages before exploring further.
>
> ## API version
> The current API version is `2026-02-09`, served at the site root (no version prefix in URLs).
> If this page URL contains `/2025-04-21/` or `/2024-12-23/`, you are reading an older API version.
> Prefer the current docs at https://docs.extend.ai/llms.txt unless the user explicitly needs that older version.
> Do not treat older-version pages as the source of truth for new integrations.

# Verify Response Format

> Every field on a verify run: statuses, output.riskLevel and summary, the signal object and its riskAssessment, the six evidence types (value_comparison, validation, inventory, history, structural_pattern, model_prediction), and evidence locations.

A verify run returns a document-level risk level, a summary, and the detected signals with their evidence. This page explains every field. The result is written once when the run completes and never recomputed, so what you read is what the run found at the time.

---

## Response structure

A processed run looks like this (one signal shown).

```json
{
  "object": "verify_run",
  "id": "vr_xK9mLPqRtN3vS8wF5hB2cQ",
  "file": {
    "object": "file",
    "id": "file_GzKUy0VDhHscv7tweODYb",
    "name": "invoice.pdf",
    "type": "PDF",
    "parentFileId": null,
    "metadata": { "pageCount": 1 },
    "createdAt": "2026-09-25T14:03:11.000Z",
    "updatedAt": "2026-09-25T14:03:11.000Z"
  },
  "status": "PROCESSED",
  "output": {
    "riskLevel": "HIGH",
    "summary": "The invoice total was covered with an opaque box and retyped in a different font.",
    "signals": [
      {
        "id": "vs_3f1j6I1gsw5k96xFiCnkM",
        "type": "PDF_LAYERS_TEXT_AND_FORMS",
        "riskAssessment": { "type": "LEVEL", "level": "HIGH" },
        "summary": "An opaque rectangle was drawn over the total and new text was drawn on top of it.",
        "evidence": [
          {
            "evidenceId": "local.text_overlay_or_masking:001",
            "type": "structural_pattern",
            "data": {
              "code": "OPAQUE_MASK_FOLLOWED_BY_TEXT",
              "components": [
                { "role": "MASK", "locationIds": ["loc_1"] },
                { "role": "REPLACEMENT_TEXT", "locationIds": ["loc_1"] }
              ]
            },
            "locations": [
              {
                "locationId": "loc_1",
                "page": { "number": 1, "width": 612, "height": 792 },
                "boundingBox": { "left": 325.4, "top": 262.976, "right": 360.66, "bottom": 273.215 }
              }
            ]
          }
        ]
      }
    ]
  },
  "failureReason": null,
  "failureMessage": null,
  "metadata": { "customerDocumentId": "inv-20419" },
  "metrics": { "processingTimeMs": 3124, "pageCount": 1 },
  "config": {
    "engine": "verify_agentic",
    "engineVersion": "0.1.0",
    "advancedOptions": { "requireParsing": true }
  },
  "usage": null,
  "source": "API",
  "sourceId": "apireq_Xj8mK2pL9nR4vT7qY5wZ",
  "createdAt": "2026-09-25T14:03:12.000Z",
  "updatedAt": "2026-09-25T14:03:15.000Z"
}
```

### Top-level fields

| Field                              | Type           | Description                                                                                                                                                                            |
| ---------------------------------- | -------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `object`                           | string         | Always `"verify_run"`.                                                                                                                                                                 |
| `id`                               | string         | Unique identifier for the run (`vr_...`). Use it to [fetch the run](/api-reference/endpoints/verify/get-verify-run) or [cancel it](/api-reference/endpoints/verify/cancel-verify-run). |
| `file`                             | object \| null | The verified file (`id`, `name`, `type`, `metadata.pageCount`). `null` once the input file has been deleted.                                                                           |
| `status`                           | string         | `PROCESSING`, `PROCESSED`, `FAILED`, or `CANCELLED`. See [Statuses](#statuses).                                                                                                        |
| `output`                           | object \| null | The result. Present when `status` is `PROCESSED`. For a zero-retention run it is delivered once (the sync response or the first `GET`) and purged afterwards. See [Output](#output).   |
| `failureReason` / `failureMessage` | string \| null | Machine-readable code and human-readable message. Present when `status` is `FAILED`. See [Error Handling](/verify/error-handling).                                                     |
| `metadata`                         | object \| null | The `metadata` you supplied on the request.                                                                                                                                            |
| `metrics`                          | object \| null | `processingTimeMs` and `pageCount` (`null` when the page count could not be determined). Present when `status` is `PROCESSED`.                                                         |
| `config`                           | object         | The configuration that ran: `engine`, the resolved `engineVersion`, and `advancedOptions.requireParsing` (whether the document was parsed).                                            |
| `usage`                            | object \| null | Usage consumed by this verify run. See [How Credits Work](/general/how-credits-work#verify) for pricing.                                                                               |
| `source`                           | string         | `API` or `STUDIO`, depending on where the run was created.                                                                                                                             |
| `sourceId`                         | string \| null | For API-created runs, the request ID of the creating request (the same value returned as `requestId` on errors).                                                                       |
| `createdAt` / `updatedAt`          | string         | ISO 8601 timestamps.                                                                                                                                                                   |

### Statuses

| Status       | Meaning                                                                                             |
| ------------ | --------------------------------------------------------------------------------------------------- |
| `PROCESSING` | The document is being checked. This is the initial state of a run created with `POST /verify_runs`. |
| `PROCESSED`  | Checks completed. Read `output`.                                                                    |
| `FAILED`     | The run could not complete. Read `failureReason` and `failureMessage`; `output` is `null`.          |
| `CANCELLED`  | The run was cancelled before it completed. `output` is `null`.                                      |

Runs move from `PROCESSING` to exactly one terminal state. A transient failure during processing is retried automatically while the run stays `PROCESSING`; only a final failure marks the run `FAILED`.

---

## Output

```json
{
  "riskLevel": "HIGH",
  "summary": "The invoice total was covered with an opaque box and retyped in a different font.",
  "signals": [ /* ... */ ]
}
```

| Field       | Type                              | Description                                                                                                                             |
| ----------- | --------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- |
| `riskLevel` | `"LOW"` \| `"MEDIUM"` \| `"HIGH"` | Document-level risk: the highest `riskAssessment` among the signals. `LOW` when the `signals` array is empty or the signals are benign. |
| `summary`   | string                            | A plain-language summary of the findings across the document, or `"No fraud signals were detected."` when nothing was detected.         |
| `signals`   | array                             | Detected [Public Signals](/verify/signals) only, one entry per detected category.                                                       |

> **Warning**
>
> `riskLevel` is never a claim of authenticity. `LOW` means the checks that ran found nothing. An empty `signals` array does not mean every check applied to the document, and it does not mean the document is genuine.

---

## Signal object

Each entry in `signals` is one detected category. When several checks detect something in the same category, they are combined into one signal with a single summary and the evidence from each.

```json
{
  "id": "vs_3f1j6I1gsw5k96xFiCnkM",
  "type": "PDF_LAYERS_TEXT_AND_FORMS",
  "riskAssessment": { "type": "LEVEL", "level": "HIGH" },
  "summary": "An opaque rectangle was drawn over the total and new text was drawn on top of it.",
  "evidence": [ /* ... */ ]
}
```

| Field            | Type   | Description                                                                  |
| ---------------- | ------ | ---------------------------------------------------------------------------- |
| `id`             | string | Stable identifier for this detected signal (`vs_...`).                       |
| `type`           | string | A [Public Signal](/verify/signals#signal-categories) category.               |
| `riskAssessment` | object | The risk attributed to this signal. See [Risk assessment](#risk-assessment). |
| `summary`        | string | What was detected, written for a reviewer.                                   |
| `evidence`       | array  | The observations behind the signal. See [Evidence](#evidence).               |

### Risk assessment

`riskAssessment` is a categorical grade for this signal: `{ "type": "LEVEL", "level": "LOW" | "MEDIUM" | "HIGH" }`.

The grade reflects the signal in the context of the whole document: a re-save that follows a signature is graded differently from one that precedes it. Model-based detections carry a deterministic grade from calibrated thresholds; all others are graded by an assessment model that reads every detection together. See [How signals are graded](/verify/signals#how-signals-are-graded).

---

## Evidence

Evidence is immutable detector output. It is produced by the check that detected the issue and is never rewritten by the assessment model, so you can rely on it as a record of what was measured. Every evidence item has exactly four fields:

```json
{
  "evidenceId": "meta.timestamp_conflict:001",
  "type": "value_comparison",
  "data": { /* schema selected by type */ },
  "locations": [ /* where in the file */ ]
}
```

| Field        | Description                                                                                                                            |
| ------------ | -------------------------------------------------------------------------------------------------------------------------------------- |
| `evidenceId` | Unique within the run. Treat it as an opaque identifier; do not parse it.                                                              |
| `type`       | One of the six evidence types below. Selects the schema of `data`.                                                                     |
| `data`       | The observation, shaped by `type`.                                                                                                     |
| `locations`  | Where the evidence is in the submitted file. May be empty when the evidence cannot be honestly localized. See [Locations](#locations). |

The six types are composable building blocks shared across signals, not one type per signal. A single signal may carry several evidence items of the same or different types. The `type` value is lowercase; every identifier inside `data` (each `code` and component `role`) is SCREAMING_SNAKE and additive, so handle values you do not recognise. The [Signals](/verify/signals#evidence-codes) page explains evidence codes and how to request the current list.

### Evidence types

The table summarises each type; the full schema for every variant, with each field's type and description, is rendered on the [Get Verify Run reference](/api-reference/endpoints/verify/get-verify-run#response.body.output.signals.evidence) under `output.signals[].evidence`.

| Type                 | Purpose                                                                                                                                                                                                                                                                                          | `data` fields                                                                           |
| -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------- |
| `value_comparison`   | Two or more values from the document that should agree and do not. The disagreement itself is the finding.                                                                                                                                                                                       | `code`, `values[]` (each a [named value](#named-values))                                |
| `validation`         | A rule the document was checked against and failed. Only material failures are returned; passing checks stay internal. Content checks report each finding this way, with a single `finding` value holding the agent's one-line statement and `locations` marking the quoted figures on the page. | `findings[].code`, optional `findings[].values[]`                                       |
| `inventory`          | A count of one kind of item found in the document, with the items listed where they could be read.                                                                                                                                                                                               | `code`, `count`, optional `items[]` (up to 20, each with `locationIds` and/or `values`) |
| `history`            | What happened to the document, in order. Each save, signature, and change is an event; array order is event order.                                                                                                                                                                               | `events[].code`, optional `locationIds`, `timestamp`, `actor`, `values[]`               |
| `structural_pattern` | A recognised arrangement of objects in the file, such as one drawn over another, with the part each plays.                                                                                                                                                                                       | `code`, `components[].role`, `components[].locationIds`, optional `components[].value`  |
| `model_prediction`   | A detection model supports this signal. Model identity, version, and score remain internal.                                                                                                                                                                                                      | `{}` (empty); the `locations` identify the regions that produced the prediction         |

#### Named values

`value_comparison`, `validation`, `inventory`, `history`, and `structural_pattern` can carry values read from the document. A named value operates as a non-strongly-typed key-value pair for rendering and evaluating findings:

| Field         | Description                                       |
| ------------- | ------------------------------------------------- |
| `name`        | What the value is, such as `creation_time`.       |
| `raw`         | The value exactly as it appears in the file.      |
| `normalized`  | A normalized form, such as an ISO 8601 timestamp. |
| `locationIds` | The `locations` entries the value was read from.  |

### Examples by type

#### value_comparison: backdated modification date

Creation and modification timestamps read from the PDF `/Info` dictionary. The modification date precedes the creation date. The location is a byte range in the file, not a visible page region.

```json
{
  "evidenceId": "meta.timestamp_conflict:001",
  "type": "value_comparison",
  "data": {
    "code": "DOCUMENT_LIFECYCLE_TIMESTAMPS",
    "values": [
      {
        "name": "creation_time",
        "raw": "D:20260427143703-04'00'",
        "normalized": "2026-04-27T18:37:03Z",
        "locationIds": ["loc_1"]
      },
      {
        "name": "modification_time",
        "raw": "D:20200101090000-05'00'",
        "normalized": "2020-01-01T14:00:00Z",
        "locationIds": ["loc_1"]
      }
    ]
  },
  "locations": [
    { "locationId": "loc_1", "objectRefs": ["4 0 R"], "byteRange": { "offset": 59277, "length": 270 } }
  ]
}
```

#### validation: signature no longer seals the file

Only the failed checks are returned. The location is the signature object.

```json
{
  "evidenceId": "meta.signature_invalid:001",
  "type": "validation",
  "data": {
    "findings": [
      { "code": "SIGNED_BYTES_CHANGED" },
      { "code": "TIMESTAMP_IMPRINT_MISMATCH" }
    ]
  },
  "locations": [
    { "locationId": "loc_1", "objectRefs": ["26 0 R"] }
  ]
}
```

#### inventory: embedded files

```json
{
  "evidenceId": "meta.embedded_content_or_permissions:001",
  "type": "inventory",
  "data": {
    "code": "EMBEDDED_FILE",
    "count": 2
  },
  "locations": [
    { "locationId": "loc_1", "objectRefs": ["4 0 R"] }
  ]
}
```

#### history: an incremental update after the original revision

Two ordered revisions, each anchored to a whole-file byte range.

```json
{
  "evidenceId": "meta.revision_history:001",
  "type": "history",
  "data": {
    "events": [
      { "code": "PDF_REVISION_CREATED", "locationIds": ["loc_1"] },
      { "code": "PDF_REVISION_APPENDED", "locationIds": ["loc_2"] }
    ]
  },
  "locations": [
    { "locationId": "loc_1", "byteRange": { "offset": 0, "length": 102334 } },
    { "locationId": "loc_2", "byteRange": { "offset": 102334, "length": 537 } }
  ]
}
```

#### structural_pattern: opaque mask followed by replacement text

Both components reference the same region on the page.

```json
{
  "evidenceId": "local.text_overlay_or_masking:001",
  "type": "structural_pattern",
  "data": {
    "code": "OPAQUE_MASK_FOLLOWED_BY_TEXT",
    "components": [
      { "role": "MASK", "locationIds": ["loc_1"] },
      { "role": "REPLACEMENT_TEXT", "locationIds": ["loc_1"] }
    ]
  },
  "locations": [
    {
      "locationId": "loc_1",
      "page": { "number": 1, "width": 612, "height": 792 },
      "boundingBox": { "left": 325.4, "top": 262.976, "right": 360.66, "bottom": 273.215 }
    }
  ]
}
```

#### model_prediction: manipulated image region

`data` is empty; the locations identify the regions the model flagged.

```json
{
  "evidenceId": "local.image_manipulation:001",
  "type": "model_prediction",
  "data": {},
  "locations": [
    {
      "locationId": "loc_1",
      "page": { "number": 1, "width": 612, "height": 792 },
      "boundingBox": { "left": 417.697, "top": 60.12, "right": 514.097, "bottom": 74.36 }
    }
  ]
}
```

---

## Locations

Every location carries at least one resolved locator. Detectors omit locators they cannot resolve rather than infer them, so a location may have a byte range but no page, or a PDF object reference but no bounding box.

```json
{
  "locationId": "loc_1",
  "page": { "number": 1, "width": 612, "height": 792 },
  "boundingBox": { "left": 325.4, "top": 262.976, "right": 360.66, "bottom": 273.215 },
  "objectRefs": ["84 0 R"],
  "byteRange": { "offset": 300917, "length": 751 }
}
```

| Field         | Description                                                                                                                                                                                                                                                 |
| ------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `locationId`  | Referenced by `locationIds` inside `data`.                                                                                                                                                                                                                  |
| `page`        | The page the evidence is on. `number` starts at 1, as everywhere else in the API. `width` and `height` are the page's dimensions in the box's units (PDF points for PDF pages, pixels for image submissions), and are always present when `boundingBox` is. |
| `boundingBox` | A rectangle defined by its `left`, `top`, `right`, and `bottom` edges, measured from the page's **top-left** corner. Divide by the page's `width` and `height` to get page-relative coordinates for rendering at any size.                                  |
| `objectRefs`  | Indirect PDF object references such as `"26 0 R"`. They identify objects in the file, not visible page positions.                                                                                                                                           |
| `byteRange`   | `offset` and `length` measured from the beginning of the submitted file, never a derived artifact.                                                                                                                                                          |

> **Note**
>
> Verify's `boundingBox` uses a top-left origin, which differs from the bottom-left PDF coordinate space. If you overlay Verify evidence on a page you rendered from [Parse](/parsing/response-format), scale by the page's `width` and `height` rather than assuming both use the same units.

## List summaries

`GET /verify_runs` returns run summaries rather than full runs. A summary has every top-level field of a run except `output`, and adds `riskLevel` so you can scan or filter results without fetching each run.

```json
{
  "object": "list",
  "data": [
    {
      "object": "verify_run",
      "id": "vr_xK9mLPqRtN3vS8wF5hB2cQ",
      "file": { "object": "file", "id": "file_GzKUy0VDhHscv7tweODYb", "name": "invoice.pdf", "type": "PDF", "parentFileId": null, "metadata": { "pageCount": 1 }, "createdAt": "2026-09-25T14:03:11.000Z", "updatedAt": "2026-09-25T14:03:11.000Z" },
      "status": "PROCESSED",
      "riskLevel": "HIGH",
      "failureReason": null,
      "failureMessage": null,
      "metadata": { "customerDocumentId": "inv-20419" },
      "metrics": { "processingTimeMs": 3124, "pageCount": 1 },
      "config": { "engine": "verify_agentic", "engineVersion": "0.1.0", "advancedOptions": { "requireParsing": true } },
      "usage": null,
      "source": "API",
      "sourceId": "apireq_Xj8mK2pL9nR4vT7qY5wZ",
      "createdAt": "2026-09-25T14:03:12.000Z",
      "updatedAt": "2026-09-25T14:03:15.000Z"
    }
  ],
  "nextPageToken": null
}
```

| Field           | Description                                                                                                                              |
| --------------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
| `riskLevel`     | The run's document-level risk. `null` until the run is `PROCESSED`, and `null` again once a zero-retention run's result has been purged. |
| `nextPageToken` | Pass back as `nextPageToken` to fetch the next page. Absent on the last page.                                                            |

Filter with `status`, `source`, `sourceId`, `riskLevel` (processed runs whose result has not been purged), and `fileNameContains`, which also accepts a run ID or file ID. Sort with `sortBy` (`updatedAt`, the default, or `createdAt`) and `sortDir` (`desc` by default). See the [List Verify Runs API reference](/api-reference/endpoints/verify/list-verify-runs).

## Walking the result

#### Python

```python
for signal in run.output.signals:
    print(signal.type, signal.risk_assessment.level, signal.summary)
    for item in signal.evidence:
        pages = sorted({loc.page.number for loc in item.locations if loc.page is not None})
        print(f"  {item.evidence_id} ({item.type}) on pages {pages}")
        if item.type == "validation":
            print("   codes:", [f.code for f in item.data.findings])
```

#### TypeScript

```typescript
for (const signal of run.output?.signals ?? []) {
  console.log(signal.type, signal.riskAssessment, signal.summary);
  for (const item of signal.evidence) {
    const pages = [...new Set(item.locations.flatMap((loc) => (loc.page === undefined ? [] : [loc.page.number])))];
    console.log(`  ${item.evidenceId} (${item.type}) on pages ${pages}`);
    if (item.type === "validation") {
      console.log("   codes:", item.data.findings.map((f) => f.code));
    }
  }
}
```

#### Java

```java
for (var signal : run.getOutput().get().getSignals()) {
    System.out.println(signal.getType() + " " + signal.getSummary());
    for (var item : signal.getEvidence()) {
        item.getValidation().ifPresent(validation -> {
            System.out.println("  " + validation.getEvidenceId());
            validation.getData().getFindings().forEach(f -> System.out.println("   code: " + f.getCode()));
        });
        item.getStructuralPattern().ifPresent(pattern ->
            System.out.println("  " + pattern.getEvidenceId() + " " + pattern.getData().getCode()));
    }
}
```

#### Go

```go
for _, signal := range run.Output.Signals {
	fmt.Println(signal.Type, signal.Summary)
	for _, item := range signal.Evidence {
		if v := item.Validation; v != nil {
			fmt.Println("  ", v.EvidenceID)
			for _, f := range v.Data.Findings {
				fmt.Println("    code:", f.Code)
			}
		}
		if p := item.StructuralPattern; p != nil {
			fmt.Println("  ", p.EvidenceID, p.Data.Code)
		}
	}
}
```

For the complete schema, see the [Get Verify Run API reference](/api-reference/endpoints/verify/get-verify-run).