Skip to main content
Every key delivered in a file.enrichment.success payload, with the type of its value and a short example. For delivery and signature verification, see Webhooks.

How to read this page

Nested keys are written as paths. file_info.mimetype means a mimetype key inside the file_info object. A [] means the key holds an array, so modules[].module_id is the module_id of each entry in modules. Types are described plainly: string, number, boolean, object, array, and null. Two qualifiers matter:
Where a key is marked “may be absent or null”, do not distinguish the two. Both forms occur, and checking for only one will break on the other.
Keys are added over time. Ignore any key you do not recognise rather than rejecting the payload.

Top level

event_id is the same on every redelivery of an event, which makes it the right value for recognising a duplicate. Treat it as an opaque string.
version is "2", a payload schema version rather than a semantic version. Compare it exactly rather than parsing it.
case_label and file_label are human-readable labels for the case and file. file_label falls back to the name parsed from the S3 upload key when no file label is available; case_label has no such fallback. Each field is an empty string (never null) if nothing could be resolved. They were added to notifications going forward; payloads sent before this addition do not include them.
Timestamps carry a UTC offset and microsecond precision, as in 2026-08-25T17:21:40.912430+00:00, rather than a Z suffix.

file_info

raw_metadata holds whatever metadata the file itself carried, so its keys depend on the file type. The three shapes below share no keys, so check mimetype before reading it.

Images

metadata.tags is free-form: its keys are whatever the file carried, so read the ones you care about by name and expect the rest to vary between files. The c2pa group appears only when the file carries a content credentials manifest.

PDFs

Word documents

analysis_metadata

Raw output from each step of the analysis. Every key below is always present, and is null when that step does not apply to the file, so an image has no pdf_structure and a PDF has no ela.

ela

Error Level Analysis, which looks for uneven compression across an image.

thumbnail

barcode_results

For barcode types that encode personal data, value is redacted and the readable content appears in fields instead.

ocr

Content read from the file, and the entities recognised in it. classifications[].custom_guess is filled in when category is "Other". The available categories depend on the document classes configured for your organisation. Entities, in key_persons, key_organizations, key_locations and key_reference_numbers: raw_ocr_text is filled in when a reading correction was applied, and holds the original text. legible is false when the value could not be read confidently from the image. Dates, in key_dates:
An unread date component is not evidence. When precision is "month" or "year", the finer parts of date_value are placeholders. When legible is false or year_inferred is true, the named component was not read from the document. A check that depends on such a component is unverifiable rather than passing: an illegible expiry year never means “not expired”.

pdf_structure

dominant_font and dominant_size each pair a value with its occurrence count. font_usage is keyed by font name and size_usage by point size written as a string. document_summary.error appears instead of the other keys when the PDF has no text layer.

annotations

results

The report written for a reviewer.
results.overall_risk_score and every severity are title-case, as in "High" and "Informational". Compare them exactly.
results.findings holds only the findings that fired, summarised for a reviewer: source_analysis matches a modules[].module_id. custom_alert_type is filled in when alert_type is "OTHER".

modules

One entry per part of the analysis that ran. Which modules appear depends on the file type, its content, and the modules enabled for your organisation, so both the length and the order of this array vary between analyses.
Look modules up by module_id, and findings by alert_type. Do not read either array by position.
When modules[].error is set, that module did not complete. Its findings are absent rather than clean, and a caveats entry will normally say so. modules[].findings holds one entry for every check the module ran, whether or not it fired:
Filter on found being true to get the alerts that actually triggered. The entries where found is false are the record of what was checked and came back clean, which is useful evidence in itself.
Values of module_id you may see include content_verification, manipulation_detection, document_consistency, software_anomalies, reverse_search_findings, pdf_structure_anomaly, barcode_analysis, reference_validation and ela_fraud_detection. Read results.modules_run rather than assuming a fixed set.

Evidence

Findings are backed by two kinds of evidence, which carry different weight. search_evidence is web research, so it corroborates. verification_evidence is a direct check against an authoritative registry or API, so it confirms or contradicts. Keep them distinct when you display them.

search_evidence

verification_evidence

is_valid has three states. true means confirmed and false means contradicted, but null means could not be verified, which is not the same as invalid. It usually means the authoritative source was unreachable or does not cover the subject, and a caveats entry will normally say so. Presenting null as a negative result will mislead your reviewers.
outputs holds fields specific to whichever source answered, so its keys vary with provider. attests states in one line what a verdict from that source actually proves. extracted is the value as read from the document, before it was normalised into subject.

Tracing a finding back to its evidence

The values in a finding’s evidence_refs point into its own module’s evidence:
  • q1.1 matches a results[].result_id in that module’s search_evidence. The number after the dot starts at 1, and matches the [1] markers in that query’s answer.
  • v1 matches a checks[].check_id in that module’s verification_evidence.
An empty evidence_refs on a finding that fired means it rests on the file’s own metadata rather than on external evidence.

Cross-module summaries

The same evidence rolled up across modules, so you can show an overview without walking every module. resolved counts checks that got an authoritative answer. failed counts those that could not be verified, which is the is_valid of null case above. Each entry under per_module holds queries, results and cited_result_ids, or checks, in the same shapes as above.

artifacts

Files produced by the analysis, given as storage paths rather than URLs. Exchange the file_id for a short-lived signed URL with Get Asset URL, passing the matching asset_type.

integrity_signals

A summary of the forensic verdict, so you can route a file without walking every module. Each boolean has three states:
Do not treat null as false. “We did not determine this” and “we determined this is not the case” carry very different weight in a fraud decision.

caveats

Limits on how far an analysis should be trusted, such as an authoritative source being unreachable or text being hard to read. Always present; an empty array means no caveats apply. Caveats sit alongside the findings rather than being findings themselves.
A critical caveat on a low-risk analysis is the case worth surfacing: it means the clean verdict itself is not dependable.
type is an open list, so handle values beyond the examples above gracefully. scope_ref names whatever the caveat attaches to, such as a check_id.

Reserved fields

Some keys arrive in the payload but are not part of the published contract. They exist for Veridox diagnostics, may change without notice, and should be ignored:
This list is not exhaustive, which is why it is worth ignoring keys you do not recognise rather than rejecting the payload.