Skip to navigation

Verify Response Format

Beta

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

{
"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

FieldTypeDescription
objectstringAlways "verify_run".
idstringUnique identifier for the run (vr_...). Use it to fetch the run or cancel it.
fileobject | nullThe verified file (id, name, type, metadata.pageCount). null once the input file has been deleted.
statusstringPROCESSING, PROCESSED, FAILED, or CANCELLED. See Statuses.
outputobject | nullThe 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.
failureReason / failureMessagestring | nullMachine-readable code and human-readable message. Present when status is FAILED. See Error Handling.
metadataobject | nullThe metadata you supplied on the request.
metricsobject | nullprocessingTimeMs and pageCount (null when the page count could not be determined). Present when status is PROCESSED.
configobjectThe configuration that ran: engine, the resolved engineVersion, and advancedOptions.requireParsing (whether the document was parsed).
usageobject | nullAlways null in the current release: verify runs are not metered during the beta.
sourcestringAPI or STUDIO, depending on where the run was created.
sourceIdstring | nullFor API-created runs, the request ID of the creating request (the same value returned as requestId on errors).
createdAt / updatedAtstringISO 8601 timestamps.

Statuses

StatusMeaning
PROCESSINGThe document is being checked. This is the initial state of a run created with POST /verify_runs.
PROCESSEDChecks completed. Read output.
FAILEDThe run could not complete. Read failureReason and failureMessage; output is null.
CANCELLEDThe 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

{
"riskLevel": "HIGH",
"summary": "The invoice total was covered with an opaque box and retyped in a different font.",
"signals": [ /* ... */ ]
}
FieldTypeDescription
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.
summarystringA plain-language summary of the findings across the document, or "No fraud signals were detected." when nothing was detected.
signalsarrayDetected Public Signals only, one entry per detected category.

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.

{
"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": [ /* ... */ ]
}
FieldTypeDescription
idstringStable identifier for this detected signal (vs_...).
typestringA Public Signal category.
riskAssessmentobjectThe risk attributed to this signal. See Risk assessment.
summarystringWhat was detected, written for a reviewer.
evidencearrayThe observations behind the signal. See 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.


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:

{
"evidenceId": "meta.timestamp_conflict:001",
"type": "value_comparison",
"data": { /* schema selected by type */ },
"locations": [ /* where in the file */ ]
}
FieldDescription
evidenceIdUnique within the run. Treat it as an opaque identifier; do not parse it.
typeOne of the six evidence types below. Selects the schema of data.
dataThe observation, shaped by type.
locationsWhere the evidence is in the submitted file. May be empty when the evidence cannot be honestly localized. See 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 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 under output.signals[].evidence.

TypePurposedata fields
value_comparisonTwo or more values from the document that should agree and do not. The disagreement itself is the finding.code, values[] (each a named value)
validationA 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[]
inventoryA 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)
historyWhat 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_patternA 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_predictionA 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:

FieldDescription
nameWhat the value is, such as creation_time.
rawThe value exactly as it appears in the file.
normalizedA normalized form, such as an ISO 8601 timestamp.
locationIdsThe locations entries the value was read from.

Examples by type

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.

{
"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 } }
]
}

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

{
"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"] }
]
}
{
"evidenceId": "meta.embedded_content_or_permissions:001",
"type": "inventory",
"data": {
"code": "EMBEDDED_FILE",
"count": 2
},
"locations": [
{ "locationId": "loc_1", "objectRefs": ["4 0 R"] }
]
}

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

{
"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 } }
]
}

Both components reference the same region on the page.

{
"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 }
}
]
}

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

{
"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.

{
"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 }
}
FieldDescription
locationIdReferenced by locationIds inside data.
pageThe 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.
boundingBoxA 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.
objectRefsIndirect PDF object references such as "26 0 R". They identify objects in the file, not visible page positions.
byteRangeoffset and length measured from the beginning of the submitted file, never a derived artifact.

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, 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.

{
"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
}
FieldDescription
riskLevelThe run’s document-level risk. null until the run is PROCESSED, and null again once a zero-retention run’s result has been purged.
nextPageTokenPass 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.

Walking the result

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

For the complete schema, see the Get Verify Run API reference.