Developer Docs
Introduction
DocVerify provides a forensic document analysis engine that detects digital tampering and forgery in images. The API accepts image files and returns a detailed analysis including trust scores, anomaly detection, metadata extraction, and optional AI-generated review.
What's Supported
Base URL
https://docverify.app
Authentication
All API and MCP endpoints accept three credential forms, all on the same URLs: your API key in the X-API-Key header, your API key as Authorization: Bearer <api_key> (the industry default — what most SDKs do), or an OAuth bearer token from the MCP sign-in flow as Authorization: Bearer <oauth_token>. Generate your API key from the Admin Dashboard under the API Keys tab. API keys always start with sk_live_.
Billing
Every analyze request is billed against your credit balance. Pick a monthly subscription (Dev starts at $10/month for 50 credits) to get started. Active subscribers can buy mid-cycle top-up packs from the billing dashboard if they exhaust their monthly allowance early. Requests with no credits return HTTP 402 with a purchase_url to /admin/billing.
# Option 1 — X-API-Key header curl -X POST https://docverify.app/api/analyze \ -H "X-API-Key: sk_live_..." \ -F "file=@document.jpg" # Option 2 — Authorization: Bearer (API key or OAuth token) curl -X POST https://docverify.app/api/analyze \ -H "Authorization: Bearer sk_live_..." \ -F "file=@document.jpg"
Keep your API key secret.Never expose it in client-side code or public repositories. Revoke and regenerate compromised keys immediately from the Admin Dashboard.
Analyze Document
Submits a document for multi-model forensic analysis. Four equivalent ways to attach the file: multipart upload, raw binary stream, JSON with a fetch URL, or JSON with base64. Pick whichever fits your runtime — they all produce the same analysis.
Option A — Multipart upload (recommended for shells / browsers)
curl -X POST https://docverify.app/api/analyze \ -H "X-API-Key: YOUR_API_KEY" \ -F "file=@invoice.jpg" \ -F "models=default" \ -F "include_heatmap=true"
Option B — Raw binary stream (application/octet-stream)
No multipart envelope, no base64 inflation — just the file bytes on the wire. Pass the mime type via the Content-Type header (or ?mime= if you must send application/octet-stream).
# Native mime — Content-Type IS the file type curl -X POST "https://docverify.app/api/analyze?include_heatmap=true" \ -H "X-API-Key: YOUR_API_KEY" \ -H "Content-Type: image/jpeg" \ --data-binary @invoice.jpg # Generic stream — declare mime explicitly curl -X POST "https://docverify.app/api/analyze?mime=application/pdf" \ -H "X-API-Key: YOUR_API_KEY" \ -H "Content-Type: application/octet-stream" \ -H "X-File-Name: contract.pdf" \ --data-binary @contract.pdf
Option C — JSON with a fetch URL
Best for files already in S3, GCS, or any presigned/public URL. The server streams the bytes for you — max 50 MB, 20 s timeout.
curl -X POST https://docverify.app/api/analyze \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com/signed/invoice.jpg",
"include_heatmap": true,
"ai_review": true
}'Option D — JSON with base64 (legacy)
Use when your runtime can't send raw bytes (browsers without FormData, some JSON-only LLM tool harnesses). Base64 inflates payloads ~33% — prefer Options A–C.
# Encode then send
B64=$(base64 -i invoice.jpg)
curl -X POST https://docverify.app/api/analyze \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d "{
\"imageDataUrl\": \"data:image/jpeg;base64,$B64\",
\"include_heatmap\": true
}"Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
| file | File | — | Multipart only. The image or PDF to analyze. |
| (request body) | bytes | — | For application/octet-stream or image/* — the raw file bytes. |
| url | string | — | JSON only. Public or presigned URL we will fetch (max 50 MB, 20s). |
| imageDataUrl | string | — | JSON only. Base64 data URL (data:mime;base64,...). |
| imageBase64 | string | — | JSON only. Raw base64 of the file. |
| filename | string | auto | Optional. Sets the filename used in retention + logs. |
| ?mime / X-File-Type | string | — | Required for application/octet-stream so the server knows the file type. |
| X-File-Name | string | auto | Optional filename hint when streaming raw bytes. |
| models | string | default | Targeted forensic model suite. default = DocVerify Core Forensics. |
| include_heatmap | boolean | false | Include a high-fidelity forensic heatmap in the response. |
| include_traditional | boolean | true | Include standard signal scores (ELA, Ghost, Noise). |
| include_metadata | boolean | true | Include Deep EXIF and file metadata analysis. |
| ai_review | boolean | true | Include Intelligence Engine visual forensic analysis. |
Response (200 OK)
{
"result": {
/* forensic analysis output from the model */
},
"billing": {
"cost_type": "free_tier", // or "token"
"free_limit": 10,
"free_used": 1,
"free_remaining": 9,
"paid_used": 0,
"token_balance": 50
}
}AI Agent Workflows
AI Agent Workflows are AI pipelines you configure in the Admin Dashboard. Each workflow has a custom system prompt, schema, and optional tool integrations (Google Search, URL context, DocVerify analysis). Once created, execute an agent via the API with your documents.
Setup
- Go to Admin Dashboard → AI Agent Workflows
- Create an agent — define its name, system prompt, input/output schema, and enabled tools
- Copy the Agent ID from the dashboard
- Call /api/agent/execute with your API key and Agent ID
Execute a configured AI Agent Workflow against one or more documents (up to 10 per request).
Request Body (application/json)
{
"agentId": "YOUR_AGENT_ID",
"documents": [
"data:image/jpeg;base64,/9j/4AAQ...",
"data:image/png;base64,iVBORw0K..."
],
"input": {
/* optional: extra fields matching your agent's input schema */
},
"debug": false
}Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| agentId | string | Yes | ID of the AI Agent Workflow to execute (from Admin Dashboard). |
| documents | string[] | Yes | Array of base64 data URLs. Max 10 documents per request. |
| input | object | No | Extra key/value pairs passed to the agent matching its input schema. |
| debug | boolean | No | If true, includes raw tool_calls in response. Default: false. |
Response (200 OK)
{
"result": { /* parsed output matching your agent's output schema */ },
"raw_response": "...",
"docverify_results": [ /* per-document forensic analysis, if agent has DocVerify enabled */ ],
"parsing_errors": null,
"token_usage": {
"input_tokens": 1240,
"output_tokens": 312,
"total_tokens": 1552,
"token_cost": 1.2,
"docverify_cost": 2,
"total_cost": 3.2
},
"billing": {
"cost_type": "token",
"credit_cost": 3.2,
"free_limit": 10,
"free_used": 10,
"free_remaining": 0,
"paid_used": 1,
"token_balance": 46.8
}
}ID Verification
Start a passport or ID document check with a 30 second liveness challenge. The flow returns a reasonable-assurance identity signal for consented user verification. It is not a regulated KYC service.
MCP Servers
DocVerify exposes separate MCP servers so agents can enable only the tool surface they need.
https://docverify.app/api/mcphttps://docverify.app/api/mcp/id-verifyID Verification Tools
- start_id_verification starts a session and returns the hosted verifier UI resource plus a ChatGPT Apps card.
- check_id_verification polls the final verdict by session ID.
- compare_faces compares two face images directly.
Integration Flow
- start_id_verification creates a short-lived verification session from a consented ID document image.
- The user completes the hosted browser flow, including camera permission and the issued liveness challenge.
- check_id_verification polls the server for status (e.g. passed) and the stored verdict by sessionId.
- For privacy and legal terms, see the linked Privacy Policy and Terms of Service from the Verify ID page.
UI Host Support
The ID-verification MCP tool returns an MCP UI resource with the secure hosted verification URL for clients that support MCP Apps / UI resources. Claude and other MCP Apps hosts can render the verification page as a sandboxed iframe or expose the external URL fallback.
ChatGPT support includes OAuth plus a native Apps SDK inline card registered with openai/outputTemplate. The card shows the session details and opens the DocVerify-hosted camera flow so camera and microphone permissions stay reliable.
MCP Client Config
{
"mcpServers": {
"docverify-id": {
"url": "https://docverify.app/api/mcp/id-verify",
"headers": {
"X-API-Key": "sk_live_..."
}
}
}
}All three credential forms work on the MCP URLs: send X-API-Key (Claude Code, Cursor, and other API-key based MCP clients), or Authorization: Bearer sk_live_... with your API key, or Authorization: Bearer <oauth_token> from the OAuth flow. ChatGPT picks the OAuth path automatically: add the MCP server in ChatGPT and complete the sign-in prompt. Add both https://docverify.app/api/mcp and https://docverify.app/api/mcp/id-verify if you want both document forensics and ID verification.
MCP Payload Formats
| Tool | Input | Supported formats | Notes |
|---|---|---|---|
| analyze_document | document | public/presigned URL or data URL | Forensics MCP does not receive raw binary blocks today; use URL/data URL. REST /api/analyze supports multipart and raw binary. |
| start_id_verification | passportImage | public/presigned URL or data URL | Use JPEG or PNG ID document images. Prefer the hosted flow for end-user capture. |
| compare_faces | image1, image2 | public/presigned URLs or data URLs | Paid-only direct comparison for consented images. |
| verifyIdStart REST | passportDataUrl | base64 data URL only | Current REST fallback format: data:image/jpeg;base64,... |
| verifyIdSubmit REST | passportDataUrl, videoDataUrl, frameDataUrls | base64 data URLs only | Current REST fallback format. Total decoded payload max is 50 MB. |
| verifyIdStatus REST | sessionId | query or JSON body | GET or POST with X-API-Key. Authoritative poll for outcome; same data model as check_id_verification MCP tool. |
| verifyIdReceipt REST | receipt | query or JSON body | GET or POST. No API key required; validates the signed receipt and returns the decoded claims. |
| Receipt JWKS | none | GET /.well-known/docverify-id-receipts/jwks.json | Public RS256 verification keys for offline JWT/JWS validation. |
Video and Compression Requirements
- Accepted liveness video MIME types: video/webm and video/mp4.
- Use a short browser-recorded clip from the user completing the issued challenge.
- The public REST fallback accepts videos up to 15 MB and a 50 MB total decoded submit payload.
- Prefer the hosted UI unless you have a server-to-server flow that can collect equivalent consented liveness media.
Base64 vs Binary
The document analysis REST API supports multipart files, raw binary streams, URLs, and base64 JSON. ID verification's current public REST fallback uses JSON data URLs for the ID image and liveness evidence.
Binary multipart support is not exposed on verifyIdStart or verifyIdSubmit today.
REST Flow
# 1. Start a session with an ID document image
curl -X POST https://us-central1-docverify-655d6.cloudfunctions.net/verifyIdStart \
-H "X-API-Key: sk_live_..." \
-H "Content-Type: application/json" \
-d '{"passportDataUrl": "data:image/jpeg;base64,..."}'
# 2. Submit the recorded liveness media
curl -X POST https://us-central1-docverify-655d6.cloudfunctions.net/verifyIdSubmit \
-H "X-API-Key: sk_live_..." \
-H "Content-Type: application/json" \
-d '{
"sessionId": "...",
"challengeToken": "...",
"passportDataUrl": "data:image/jpeg;base64,...",
"videoDataUrl": "data:video/webm;codecs=vp9,opus;base64,...",
"frameDataUrls": ["data:image/jpeg;base64,..."]
}'
# 3. (Optional) Poll outcome by session — same API key, must own the session
curl -X GET "https://us-central1-docverify-655d6.cloudfunctions.net/verifyIdStatus?sessionId=..." \
-H "X-API-Key: sk_live_..."
# 4. Validate a signed receipt — no API key required
curl -X POST https://us-central1-docverify-655d6.cloudfunctions.net/verifyIdReceipt \
-H "Content-Type: application/json" \
-d '{"receipt": "eyJhbGciOiJSUzI1NiIs..."}'
# Public keys for offline verification
curl https://docverify.app/.well-known/docverify-id-receipts/jwks.jsonThe hosted MCP UI performs this browser-side capture and submit automatically. Server-to-server callers should only use this REST flow if they can collect equivalent consented liveness media.
Response Notes
- verifyIdSubmit returns a receipt string (RS256-signed JWT/JWS, about 24h validity) plus the full verdict. It is issued for both pass and fail outcomes.
- To check the signed receipt without an API key, call verifyIdReceipt or verify offline with the public JWKS at /.well-known/docverify-id-receipts/jwks.json.
- With your API key, use verifyIdStatus or MCP check_id_verification to confirm what the server currently records for a session.
- Responses also include attempt limits and remaining attempts where applicable.
- Results are probabilistic and should be reviewed by a human before any high-impact decision.
- ID verification media is not retained for Free-Tier training; it is handled according to the Privacy Policy linked from the Verify ID page.
Error Handling
All errors return JSON with an error string and status_code field matching the HTTP status.
{
"error": "Insufficient token balance. Purchase more credits.",
"status_code": 402,
"purchase_url": "https://docverify.app/admin?tab=billing"
}| Code | Meaning | When it happens |
|---|---|---|
| 200 | OK | Analysis completed successfully. |
| 400 | Bad Request | Missing required field, invalid format, PDF submitted, or max document limit exceeded. |
| 401 | Unauthorized | Missing or invalid credentials. Send X-API-Key or Authorization: Bearer <token>. |
| 402 | Payment Required | No active credits. Subscribe at /admin/billing (active subscribers can also add a mid-cycle top-up pack). Includes purchase_url. |
| 403 | Forbidden | API key does not own the requested agent. |
| 404 | Not Found | The specified agentId does not exist. |
| 405 | Method Not Allowed | Request method is not POST. |
| 415 | Unsupported Media Type | Use multipart/form-data, application/octet-stream, image/*, application/pdf, or application/json. |
| 429 | Too Many Requests | Upstream AI provider quota exceeded. Retry with exponential backoff. |
| 500 | Internal Server Error | Unexpected error in the analysis engine. |
| 503 | Service Unavailable | Upstream AI provider is temporarily unavailable. |