# Document forensics
Source: https://docs.file.ai/verify/forensics

> Run checks on a stored file for signs of editing, AI generation, reuse and hidden content.

fileForensics

# Document forensics

Copy pageCopy page

Run checks on a stored file for signs of editing, AI generation, reuse and hidden content.

Copy pageCopy page

Reference for fileForensics runs: endpoints, request rules, statuses, every detector and the errors you can get. For what fileForensics is and how it’s metered, see the [overview](/forensics/overview). For a first run end to end, see the [quickstart](/quickstart/forensics).

## 

[​

](#how-it-works)

How it works

A run checks a file that is already stored in your workspace, identified by its `file_id`, so there is no upload in the request. Each result appears under `forensics.<key>` once that detector has reported, and the [file checks](#file-checks) appear under `checks.<key>`.

1

Start a run

`POST /v1/forensics` returns `202` with a `run_id`, `status: "queued"` and a `poll_url`. Runs started at upload with `enabledProducts: ["FILE_FORENSICS"]` run all 55 checks; read them with `GET /v1/forensics/files/{file_id}`.

2

Poll

`GET /v1/forensics/runs/{run_id}` until `status` is `complete` or `error`. Web presence can take up to about 180 seconds.

3

Retry if stuck

A run still `queued` or `running` after about 6 minutes is stuck. `POST /v1/forensics/runs/{run_id}/retry` re-runs the same file and `spec_filter` under a **new** `run_id`, which is the one to poll. The original run then reports `error`.

4

Clean up

`DELETE /v1/forensics/runs/{run_id}` once you have the result. The file itself is not affected.

Forensics runs are not jobs: they do not appear on `GET /v1/jobs/{job_id}` and have no callback. See [Async jobs](/api/async-jobs#forensics-runs) for how they compare with other async work.

## 

[​

](#endpoints)

Endpoints

Endpoint

What it does

`POST /v1/forensics`

Start a run. JSON body: `file_id`, `spec_filter`.

`GET /v1/forensics/runs/{run_id}`

Get a run’s status and results.

`GET /v1/forensics/files/{file_id}`

Get the newest run for a file, whether it was started at upload or with `POST /v1/forensics`. `404` if the file has no run.

`POST /v1/forensics/runs/{run_id}/retry`

Re-run with the same file and `spec_filter`. No body. Returns a new `run_id`.

`DELETE /v1/forensics/runs/{run_id}`

Delete the run. Afterwards, GET, retry and DELETE on it return `404`.

## 

[​

](#request)

Request

Field

Rules

`file_id`

Required. The public `fileId` of a stored file, up to 128 characters. Unknown files are a `404`.

`spec_filter`

Required. A non-empty array of unique detector keys from [Detectors](#detectors). An unknown or repeated key is a `422`.

`spec_filter` is required so that a detector added later cannot silently change what an existing integration runs.

## 

[​

](#response)

Response

Field

Meaning

`run_id`, `file_id`, `spec_filter`, `created_at`

The run and what it checks.

`status`

Run status. See [Run status](#run-status).

`poll_url`

The `GET /v1/forensics/runs/{run_id}` URL for this run. Returned when the run starts.

`forensics.<key>`

One result per detector in `spec_filter`, keyed by detector. Results appear as each detector reports.

`forensics.<key>.status`

See [Detector status](#detector-status).

`forensics.<key>.value`

A one-line summary, such as `"AI-generated: false"`. Other fields are detector-specific.

`forensics.web_presence.web_presence`

The combined web-presence boolean. Absent when the run reached no conclusion.

`checks.<key>`

The 18 [file checks](#file-checks). Present only when `spec_filter` includes at least one forensic check; then all 18 run, whatever else `spec_filter` says.

`mapping.layout_parse`

The [layout parse](#detectors), present only when `spec_filter` includes `layout_parse`.

### 

[​

](#run-status)

Run status

`status`

Meaning

`queued`

Waiting to start.

`running`

In progress. Results appear as each detector reports.

`complete`

Final. Read the results under `forensics`.

`error`

Final. The run failed, or was replaced by a retry.

### 

[​

](#detector-status)

Detector status

Every detector result has a `status`, and usually a one-line `value`. Route on each detector’s status, not the run’s: a `complete` run can still contain an `issue`.

`status`

Meaning

`none`

Nothing found.

`issue`

Something to review.

`found`

Information reported, not a problem. For example, `magic_byte` when the file signature matches its type, `revision_history` when the file has later saves, `heatmap`, and most file checks.

`skip`

Doesn’t apply to this file. `value` usually says why.

`error`

The detector failed.

For `web_presence`, the combined `web_presence` boolean is absent when the run reached no conclusion (still running, `skip` or `error`). Do not read a missing value as “not found on the web”.

## 

[​

](#detectors)

Detectors

Key

What it checks

`web_presence`

Whether the image appears on the web, from file metadata (`layer1`) and a reverse-image search (`layer2`).

`ai_gen_detection`

AI-generated image

`ai_text_detection`

AI-generated text

`ai_pdf_detection`

AI-generated PDF

`ai_office_detection`

AI-generated Office document

`copy_move`

Copied-and-moved (cloned) regions

`exact_duplicate`

Exact duplicate of a previously seen file

`provenance_credentials`

Content credentials (C2PA)

`generation_toolchain`

Creation tools inferred from metadata

`producer_divergence`

Different producers across pages

`encryption_permissions`

Encryption and permissions

`active_content`

Active content, such as scripts and launch actions

`digital_signature`

Digital signature

`attachments`

Embedded attachments

`revision_history`

Revision history

`magic_byte`

File signature vs declared type

`polyglot`

Polyglot file (valid as more than one format)

`trailing_data`

Data after the end of the file

`entropy`

Entropy anomalies

`heatmap`

Where the image classifier looked (an attention map, not a verdict). Runs on image files; `skip` for images inside a document.

`document_integrity_decisions`

The 17 [integrity questions](#integrity-questions) and their overall decision.

`layout_parse`

Optional. The file’s elements with their positions, returned under `mapping.layout_parse` instead of `forensics`. Not counted as a check.

The MCP tool `run_file_forensics` accepts the same keys. See [MCP tools](/mcp/tools#forensics).

### 

[​

](#file-checks)

File checks

File checks describe the file rather than judge it. They come back under `checks.<key>` on every run whose `spec_filter` includes at least one forensic check, using the same statuses. Most report `found` when there is something to describe, or `none` when there isn’t. A few report `issue` when something is worth a look, such as blank pages, skewed or low-resolution scans, or timestamps that disagree.

Key

What it reports

`file_metadata`

Document metadata

`fingerprint`

File hashes

`text_layer`

Whether pages have a text layer

`producer_metadata`

The producing application

`timestamps`

Creation and modification times

`gps`

GPS location in image metadata

`outline`

Bookmarks and outline

`form_fields`

Interactive form fields

`links`

Links in the file

`fonts`

Fonts used

`page_rotation`

Rotated pages

`language`

Language of the text

`resolution`

Page image resolution

`skew`

Skewed scans

`image_quality`

Image quality

`blank_pages`

Blank pages

`page_numbering`

Page numbering

`barcodes`

QR codes and barcodes, decoded

### 

[​

](#integrity-questions)

Integrity questions

`document_integrity_decisions` asks 17 fixed questions about whether the content holds together. Each answer is under `decisions`, with a `class` of `signal`, `no_signal` or `insufficient_evidence`.

Answered from

Questions

The file’s text and metadata (10)

Content consistency, metadata consistency, timeline consistency, provenance and integrity claims, structural completeness, typography within comparable roles, visible versus embedded content, authorization and conditions, meaningful change from a prior version, interpretation of the other forensic results

Page images (6)

Handwritten alterations, local visual discontinuities, page assembly, obscured or covered content, visible evidence of stated requirements, repeated distinctive visual content

The file’s signatures, checked locally (1)

Cryptographic integrity of signatures and revisions

`final_decision` combines the answers and sets the detector’s result:

`status`

`value`

Meaning

`issue`

`review_recommended`

Something is worth a reviewer’s attention. Not a fraud verdict.

`none`

`no_signal`

The questions found nothing inconsistent. Not proof the file is authentic.

`skip`

`incomplete_evidence`

The answers weren’t enough to decide, for example because some questions couldn’t be answered for this file.

A question can go unanswered, for example when the file has no page images or no signature. Its `class` is then `insufficient_evidence`, or `null` when no answer came back. When the integrity questions aren’t enabled, `document_integrity_decisions` reports `skip`, and its `value` says the check is disabled.

## 

[​

](#errors)

Errors

Status

When

`404`

Unknown file or run, a deleted run, or a run the forensics service no longer holds.

`422`

Invalid body, a file with no stored content to analyze, or (on retry) a file that is no longer available.

`502`

The forensics service returned an error or was unreachable.

`503`

fileForensics is not configured.

See [Errors](/api/errors) for the response format.

## 

[​

](#related)

Related

## Forensics quickstart

Run your first check end to end.

## KYC checks

Choose detectors per document and route on the result.

## Uploads

Store a file and get its `fileId`.

## MCP tools

Run fileForensics from an AI assistant.

[Previous](/quickstart/forensics)[

Claim evidence pack

Check every file in a claim with fileForensics, extract the forms with fileScout, and combine the findings into one routing decision.

Next

](/examples/claim-evidence-pack)

⌘I

## On this page

Back to top

*   [How it works](#how-it-works)
*   [Endpoints](#endpoints)
*   [Request](#request)
*   [Response](#response)
    *   [Run status](#run-status)
    *   [Detector status](#detector-status)
*   [Detectors](#detectors)
    *   [File checks](#file-checks)
    *   [Integrity questions](#integrity-questions)
*   [Errors](#errors)
*   [Related](#related)
