Fileverity API docs
Analyses
Create image and document analyses, wait for the result with Prefer: wait or poll, cancel, download the PDF report and read the report object and verification page.
An analysis is one image or document check. It checks one uploaded file with fvimg-2 (images) or fvdoc-3 (documents). Upload the file first (see Files), then create the analysis.
For a product overview with a request and a response, see the AI image detection API and Document fraud detection API.
Create an analysis
POST /analyses returns the analysis object. The price is reserved when the analysis is created and released if it fails or is canceled.
| Field | Type | Required | Description |
|---|---|---|---|
model | string | Yes | fvimg-2 or fvdoc-3, or a snapshot ID such as fvimg-2-2026-10-30. |
file | string | Yes | ID of an uploaded file. |
metadata | object | No | Up to 16 string pairs. Keys up to 40 characters, values up to 500. Returned on the analysis and in webhooks. |
options.password | string | No | Password of an encrypted document, up to 256 characters. |
options.locale | string | No | Language of document findings: en, fr, de, es, zh, vi or ar. Default en. |
curl https://api.fileverity.com/v1/analyses \ -H "Authorization: Bearer $FILEVERITY_API_KEY" \ -H "Content-Type: application/json" \ -H "Idempotency-Key: 0e5f6a64-52c2-4b36-9d0d-6f3d2f4c9a10" \ -d '{"model": "fvdoc-3", "file": "file_Pw3mY6zB8Hk2pQ4vN9sL1xR7", "metadata": {"order_id": "A-10492"}}'const response = await fetch("https://api.fileverity.com/v1/analyses", { method: "POST", headers: { Authorization: "Bearer " + process.env.FILEVERITY_API_KEY, "Content-Type": "application/json", "Idempotency-Key": crypto.randomUUID(), }, body: JSON.stringify({ model: "fvdoc-3", file: file.id, metadata: { order_id: "A-10492" } }),});const analysis = await response.json();import osimport uuidimport requests response = requests.post( "https://api.fileverity.com/v1/analyses", headers={ "Authorization": "Bearer " + os.environ["FILEVERITY_API_KEY"], "Idempotency-Key": str(uuid.uuid4()), }, json={"model": "fvdoc-3", "file": file["id"], "metadata": {"order_id": "A-10492"}},)analysis = response.json()Wait, poll or use webhooks
Create returns 202 with status: processing. You have three ways to get the result:
- Wait. Send
Prefer: wait=N, where N is up to 60 seconds. The request is held until the analysis finishes or N seconds pass. A finished analysis returns200; otherwise you still get202. The response headerpreference-applied: wait=Nconfirms the wait. - Poll. Call
GET /analyses/{id}every few seconds untilstatusis no longerprocessing. - Webhook. Subscribe to
analysis.completedandanalysis.failedand fetch the analysis when the event arrives. See Webhooks.
let analysis = created;while (analysis.status === "processing") { await new Promise((resolve) => setTimeout(resolve, 3000)); const response = await fetch("https://api.fileverity.com/v1/analyses/" + analysis.id, { headers: { Authorization: "Bearer " + process.env.FILEVERITY_API_KEY }, }); analysis = await response.json();}import time analysis = createdwhile analysis["status"] == "processing": time.sleep(3) analysis = requests.get("https://api.fileverity.com/v1/analyses/" + analysis["id"], headers=headers).json(){ "id": "an_8Hk2pQ4vN9sL1xR7cW3mY6zB", "object": "analysis", "created": 1793700120, "model": "fvdoc-3-2026-11-03", "livemode": true, "status": "processing", "file": { "name": "contract.pdf", "bytes": 18874368, "format": "pdf" }, "report_id": null, "report_url": null, "summary": null, "result": null, "error": null, "progress": { "stage": "queued", "done": 0, "total": 0, "position": 1 }, "usage": { "amount": 599, "currency": "usd", "funding": "balance" }, "metadata": { "order_id": "A-10492" }, "completed_at": null, "expires_at": null}While an analysis is processing, progress.stage is one of queued, reading, analyzing or reporting, and position is the queue position while the stage is queued. Documents can be queued. Waiting is optional for documents and can end before the result is ready, so always handle 202.
When the service is busy
When capacity is busy, POST /analyses returns 503 with the code service_unavailable and a retry-after header. You are not charged. Wait the number of seconds in retry-after, then retry with the same Idempotency-Key so the retry can never run a check twice. For the best throughput, run image analyses one after another instead of in parallel.
async function create(body, key) { for (let attempt = 0; attempt < 5; attempt++) { const response = await fetch("https://api.fileverity.com/v1/analyses", { method: "POST", headers: { Authorization: "Bearer " + process.env.FILEVERITY_API_KEY, "Content-Type": "application/json", "Idempotency-Key": key }, body: JSON.stringify(body), }); if (response.status !== 503) return response; const wait = Number(response.headers.get("retry-after")) || 15; await new Promise((resolve) => setTimeout(resolve, wait * 1000)); } throw new Error("Service busy");}import time def create(body, key): for attempt in range(5): response = requests.post("https://api.fileverity.com/v1/analyses", headers={**headers, "Idempotency-Key": key}, json=body) if response.status_code != 503: return response time.sleep(int(response.headers.get("retry-after", 15))) raise RuntimeError("Service busy")Statuses
| Status | Meaning |
|---|---|
processing | The analysis is running. result is null. |
succeeded | The result is ready. report_id, report_url, summary and result are set. |
failed | The analysis could not be completed. error holds the code and message. You were not charged. |
canceled | You canceled it. error.code is canceled. You were not charged. |
{ "id": "an_8Hk2pQ4vN9sL1xR7cW3mY6zB", "object": "analysis", "created": 1793700120, "model": "fvimg-2-2026-10-30", "livemode": true, "status": "failed", "file": { "name": "claim-photo.jpg", "bytes": 2481920, "format": "jpeg" }, "report_id": null, "report_url": null, "summary": null, "result": null, "error": { "code": "analysis_failed", "message": "The analysis could not be completed. You were not charged; retry it, and contact support with the request ID if it fails again." }, "progress": null, "usage": { "amount": 0, "currency": "usd", "funding": null }, "metadata": null, "completed_at": 1793700135, "expires_at": null}The report object
A succeeded analysis carries the same report that the website, the PDF and the verification page show.
| Field | Description |
|---|---|
report_id | Report ID, FV-XXXX-XXXX-XXXX. |
report_url | Public verification page for the report. Anyone with the link can check the report ID, the file fingerprint and the timestamp against the record, without an account. |
summary | The short verdict. See below. |
result.report | The full report. result.report.schema is fileverity.report/1 for images and fileverity.docpro/1 for documents. |
result.stamped_at | Unix timestamp of the RFC 3161 timestamp issued for the report, or null. |
usage | amount charged in cents (0 for free-start checks and failures), currency and funding (trial or balance). |
metadata | The metadata you sent, or null. |
expires_at | Unix timestamp after which result is removed. Results are kept for 7 days. |
{ "id": "an_8Hk2pQ4vN9sL1xR7cW3mY6zB", "object": "analysis", "created": 1793700120, "model": "fvimg-2-2026-10-30", "livemode": true, "status": "succeeded", "file": { "name": "claim-photo.jpg", "bytes": 2481920, "format": "jpeg" }, "report_id": "FV-7K2M-9QXD-4T8R", "report_url": "https://fileverity.com/verify/FV-7K2M-9QXD-4T8R", "summary": { "level": "L2", "assessment": "authentic_untouched", "action": "accept", "ai": "very_low", "edit": "none" }, "result": { "report": { "schema": "fileverity.report/1", "id": "FV-7K2M-9QXD-4T8R" }, "stamped_at": 1793700130 }, "error": null, "progress": null, "usage": { "amount": 199, "currency": "usd", "funding": "balance" }, "metadata": { "order_id": "A-10492" }, "completed_at": 1793700131, "expires_at": 1794304931}The report object is shortened above; the real one holds the complete findings.
The summary is the stable, machine-readable verdict. result.report is the full report that the website and the PDF render. Its structure follows the schema named in result.report.schema. Within the same schema version, listed fields keep their name and meaning, and new fields can be added, so ignore fields you do not recognize.
Image summary
| Field | Values |
|---|---|
level | L0 Undetermined, L1 Source verified, L2 No anomalies found, L3 Needs manual review, L4 Highly suspicious, L5 Strong evidence against authenticity. |
action | accept, review, reject, resubmit |
assessment | authentic_untouched, authentic_locally_edited, ai_generated, undetermined |
ai | labelled, very_likely, suspected, undecided, low, very_low, not_evaluated |
edit | detected, suspected, suspected_record, review, generative, minor, none, not_applicable, not_evaluated |
Document summary
| Field | Description |
|---|---|
kind | Always docpro. |
level | L0 Undetermined, L1 Source verified, L2 No signs of tampering, L3 Needs manual review, L4 High risk, L5 Problems established. |
action | accept, note (check the AI content marked in the report against your policy), review, reject or resubmit. |
reason | The finding or condition behind the level, for example clean, incomplete or a finding ID, or null. |
findings | IDs of the findings that matter. |
pages, images | Pages in the document and embedded photos examined. |
text | The verdict on the document's text (ai_generated, mixed, human, inconclusive), or null when text was not evaluated. |
strong | true when a listed finding is strong. Absent otherwise. |
{ "id": "an_Zc4vB7nP1sK8tL3wR6yQm2Xa", "object": "analysis", "created": 1793700300, "model": "fvdoc-3-2026-11-03", "livemode": true, "status": "succeeded", "file": { "name": "contract.pdf", "bytes": 18874368, "format": "pdf" }, "report_id": "FV-3PXH-6WQ2-8NDC", "report_url": "https://fileverity.com/verify/FV-3PXH-6WQ2-8NDC", "summary": { "kind": "docpro", "level": "L3", "action": "review", "reason": null, "findings": [], "pages": 12, "images": 3, "text": "human" }, "result": { "report": { "schema": "fileverity.docpro/1", "id": "FV-3PXH-6WQ2-8NDC" }, "stamped_at": 1793700340 }, "error": null, "progress": null, "usage": { "amount": 599, "currency": "usd", "funding": "balance" }, "metadata": null, "completed_at": 1793700341, "expires_at": 1794305141}Image report fields
result.report of an image analysis. Nested objects are listed in the API reference.
| Field | Type | Required | Description |
|---|---|---|---|
schema | "fileverity.report/1" | Yes | |
id | string | Yes | Report ID, FV-XXXX-XXXX-XXXX. |
sample | true | No | Present on the fixed sample reports that test keys return. |
issuedAt | string | No | When the report was issued, ISO 8601 in UTC. Format date-time. |
issuer | object | No | Who issued the report. |
file | object | No | The checked image. |
pro | object | No | The verdict. The same values as summary, with reason. |
score | integer or null | No | Authenticity score from 0 to 100 in steps of 5: how strongly the evidence supports the image as an authentic, unedited capture. null when not evaluated. |
confidence | one of "high", "medium", "low" | No | How much this file allows the analysis to establish. Low confidence usually reflects the file itself, such as low resolution or heavy compression. |
questions | object | No | The three questions the report answers. |
generator | object or null | No | The AI generator named for the image, or null. |
regions | array of object | No | Flagged regions, in pixels of the displayed image. |
provenance | object | No | What the file's own records say about its origin. |
digest | string | No | Fingerprint of the report content, used by the verification page. |
Document report fields
result.report of a document analysis.
| Field | Type | Required | Description |
|---|---|---|---|
schema | "fileverity.docpro/1" | Yes | |
id | string | Yes | Report ID, FV-XXXX-XXXX-XXXX. |
sample | true | No | Present on the fixed sample reports that test keys return. |
issuedAt | string | No | When the report was issued, ISO 8601 in UTC. Format date-time. |
receivedAt | string | No | When the file was received, ISO 8601 in UTC. Format date-time. |
issuer | object | No | Who issued the report. |
file | object | No | The checked document. |
level | one of "L0", "L1", "L2", "L3", "L4", "L5" | No | Risk level, L0 to L5. |
action | one of "accept", "note", "review", "reject", "resubmit" | No | |
reason | string or null | No | The finding or condition behind the level. |
findings | array of object | No | The findings behind the level, each with the pages and embedded photos it refers to. |
text | object | No | The result for the document's text. |
images | array of object | No | The embedded photos and graphics, numbered in document order. |
structure | object or null | No | The edit history of the file, or null when it was not examined. |
provenance | object | No | What the file's own records say about its origin. |
digest | string | No | Fingerprint of the report content, used by the verification page. |
Retrieve, list and cancel
GET /analyses/{id}returns the analysis, with its result while it is kept.GET /analyseslists analyses of the workspace, newest first.limitis 1 to 100 (default 20),typefilters byimageordocument, andstarting_aftertakes the previous page'snext_cursor. List items never includeresult.POST /analyses/{id}/cancelcancels a document analysis that is still processing and releases its charge. Image analyses cannot be canceled; a late or finished cancel returnsnot_cancelable.
curl "https://api.fileverity.com/v1/analyses?limit=20&type=document" \ -H "Authorization: Bearer $FILEVERITY_API_KEY" curl -X POST https://api.fileverity.com/v1/analyses/an_8Hk2pQ4vN9sL1xR7cW3mY6zB/cancel \ -H "Authorization: Bearer $FILEVERITY_API_KEY"PDF report
GET /analyses/{id}/report.pdf downloads the sealed PDF report of a succeeded analysis while its result is kept. Add ?locale= with en, fr, de, es, zh, vi or ar (default en). Send the Authorization header; the response is application/pdf.
curl "https://api.fileverity.com/v1/analyses/an_8Hk2pQ4vN9sL1xR7cW3mY6zB/report.pdf?locale=en" \ -H "Authorization: Bearer $FILEVERITY_API_KEY" \ -o Fileverity-FV-7K2M-9QXD-4T8R.pdfFor documents, page images and text excerpts are kept for 3 hours after the check. After that the PDF omits them, and the response header x-evidence-included is false. Download the PDF when the analysis finishes if you need it to include the evidence.
Errors
| Code | Status | Cause |
|---|---|---|
file_not_found | 400 | The file ID is unknown, expired or already used, or the upload to upload.url has not finished yet. |
model_not_found | 404 | Unknown model. |
invalid_parameter | 400 | A field is missing, mistyped or unknown. Text models belong to POST /text/detections. |
unsupported_file, invalid_file | 415, 422 | The file format is not supported for the model, or the file is damaged. |
file_too_large, too_many_pixels, too_many_pages, document_too_long | 413 | A size limit was exceeded. |
password_required, wrong_password | 422 | The document is encrypted. Send options.password. |
not_examinable | 422 | The document has nothing that can be examined. Not charged. |
insufficient_balance, spend_limit_reached | 402 | The balance or the key's monthly limit cannot cover the price. |
service_unavailable, analysis_failed | 503, 502 | A temporary failure or busy capacity. Not charged; retry. service_unavailable carries a retry-after header. See When the service is busy. |
unsupported_media_type | 415 | The body is not sent as application/json. |
idempotency_mismatch, idempotency_in_progress | 409 | The Idempotency-Key was used with a different body, or its first request is still running. See Idempotency. |
not_cancelable | 409 | Only documents that are still processing can be canceled. |
Some failures happen after the analysis is created, for example when a model cannot finish. They set status: failed and error on the analysis instead of failing the create call, and the analysis.failed webhook fires. See Errors.