DocuVision Pro API
Extract financial data from receipts, invoices, and documents. Get vendor, amount, currency, date, and an automatic approve/review/reject decision — all via a simple REST API.
Base URL
All API requests must be made to
All API requests must be made to
https://api.en-globalventures.com
Quick Start
Shell
# 1. Upload a document curl -X POST https://api.en-globalventures.com/v1/documents \ -H "X-API-Key: dvp_your_key_here" \ -F "file=@invoice.pdf" # 2. Poll until decided curl https://api.en-globalventures.com/v1/documents/doc_abc123 \ -H "X-API-Key: dvp_your_key_here" # 3. Get the decision curl https://api.en-globalventures.com/v1/documents/doc_abc123/decision \ -H "X-API-Key: dvp_your_key_here"
Authentication
All API requests require an API key passed in the
X-API-Key request header. Keys are issued per user account by the platform admin.Header
string
X-API-Key: dvp_xxxxxxxxxxxxx — required on every requestFormat
string
Keys are prefixed with
dvp_ followed by 40 hex characters. Keys are hashed server-side and cannot be retrieved after creation.Limit
integer
One active key per user account. Contact support to rotate or revoke.
Security: Never expose API keys in client-side code or public repositories. Treat them like passwords.
Rate Limits
API usage is limited per key on a 24-hour rolling window.
| Limit | Window | Reset |
|---|---|---|
| 100 requests | per API key | 24 hours from first request in window |
When exceeded, the API returns 429 with a reset_in_minutes field indicating when the window resets.
{
"error": "rate_limit_exceeded",
"limit": 100,
"reset_in_minutes": 847
}
Upload a Document
Submit a document for AI processing. Returns immediately with a
document_id. Processing happens asynchronously — poll the status endpoint until status is decided.
POST
/v1/documents
Upload & start processing
Request — multipart/form-data
| Field | Type | Required | Description |
|---|---|---|---|
| file | file | required | PDF, JPG, or PNG. Max 20 MB. |
| metadata | string | optional | JSON string with arbitrary key/value pairs attached to the document. |
Response 202 Accepted
{
"document_id": "doc_5ebf608f6c11bc2b",
"status": "uploaded"
}
Example
curl -X POST https://api.en-globalventures.com/v1/documents \ -H "X-API-Key: dvp_your_key" \ -F "file=@invoice.pdf" \ -F 'metadata={"reference":"INV-2026-001"}'
import requests response = requests.post( "https://api.en-globalventures.com/v1/documents", headers={"X-API-Key": "dvp_your_key"}, files={"file": open("invoice.pdf", "rb")}, data={"metadata": '{"reference":"INV-2026-001"}'} ) doc_id = response.json()["document_id"]
const FormData = require('form-data'); const fs = require('fs'); const form = new FormData(); form.append('file', fs.createReadStream('invoice.pdf')); const res = await fetch('https://api.en-globalventures.com/v1/documents', { method: 'POST', headers: { 'X-API-Key': 'dvp_your_key', ...form.getHeaders() }, body: form }); const { document_id } = await res.json();
Get Document Status
Poll this endpoint after uploading a document. When
status is decided and progress is 100, the fields and decision endpoints are ready.
GET
/v1/documents/{id}
Status poll
Response 200 OK
{
"document_id": "doc_5ebf608f6c11bc2b",
"status": "decided",
"progress": 100,
"created_at": "2026-05-25T20:57:04.547Z"
}
Status Values
| Value | Meaning |
|---|---|
| uploaded | File received, queued for processing |
| processing | AI extraction in progress |
| extracted | Fields extracted, computing decision |
| decided | Complete — fields and decision available |
| failed | Processing error — retry with a valid document |
Polling interval: We recommend polling every 2–5 seconds. Most documents complete in under 15 seconds.
Get Extracted Fields
Returns the structured financial data extracted from the document. Available when
status is extracted or decided. Returns 409 if the document is still processing.
GET
/v1/documents/{id}/fields
Extracted financial data
Response 200 OK
{
"vendor": "שופרסל",
"total": 156.72,
"currency": "ILS",
"date": "2026-05-21",
"payment_method": "card"
}
Fields
vendor
string|null
Merchant or supplier name. Supports Hebrew, Arabic, Russian, and 50+ languages.
total
number|null
Total amount due or paid, as a float.
currency
string|null
ISO 4217 currency code:
USD, ILS, EUR, GBP, etc.date
string|null
Document date in
YYYY-MM-DD format.payment_method
string|null
card, cash, bank-transfer, paypal, or null if not detected.Get Decision
Returns the AI-generated financial decision for the document. Available only when
status is decided.
GET
/v1/documents/{id}/decision
Auto-approve / review / reject
Response 200 OK
{
"decision": "auto_approve",
"confidence": 0.930,
"duplicate": false
}
Decision Values
| Value | Confidence range | Meaning |
|---|---|---|
| auto_approve | ≥ 0.85 | High confidence extraction, no anomalies detected |
| review | 0.40 – 0.84 | Medium confidence — human review recommended |
| reject | < 0.40 or duplicate | Low confidence or duplicate document detected |
decision
string
One of
auto_approve, review, or reject.confidence
number
Extraction confidence score from
0.000 to 1.000.duplicate
boolean
true if an identical document was previously processed for this account.Webhooks
DocuVision Pro sends a
POST request to your endpoint when any document reaches decided status — regardless of whether it was uploaded via the API or the dashboard UI.
Global event model: Webhooks fire for all documents. If you mix dashboard uploads (manual) and API uploads (automated), you receive a unified event stream from a single webhook endpoint.
Setup
Webhook endpoints are registered per user account by the platform admin. Contact api@en-globalventures.com with your endpoint URL to get started.
Retry Policy
| Attempt | Delay | Condition |
|---|---|---|
| 1 | Immediate | Always |
| 2 | 3 seconds | Non-2xx or network error |
| 3 | 9 seconds | Non-2xx or network error |
If all 3 attempts fail, the delivery is logged as failed. Your endpoint should respond with a 2xx status code within 10 seconds.
Event Schema
Every webhook delivery sends a JSON body with this structure.
{
"event": "document.completed",
"document_id": "doc_5ebf608f6c11bc2b",
"analysis_id": 42,
"timestamp": "2026-05-25T20:57:18.000Z",
"data": {
"vendor": "שופרסל",
"total": 156.72,
"currency": "ILS",
"confidence": 0.91,
"decision": "auto_approve"
}
}
event
string
Always
document.completed in v1.document_id
string
API document ID (
doc_xxx) or analysis_N for dashboard uploads.analysis_id
integer
Internal analysis record ID — use to correlate with dashboard history.
timestamp
string
ISO 8601 UTC timestamp of when the event was fired.
data
object
Summary of extracted fields and decision. Full details available via the API endpoints.
Signature Verification
Every webhook request includes an
X-DocuVision-Signature header. Verify it to confirm the request is from DocuVision Pro.Header
X-DocuVision-Signature: sha256=a4d2e1f3b8c7...
import hmac, hashlib def verify_signature(secret: str, body: bytes, header: str) -> bool: expected = "sha256=" + hmac.new( secret.encode(), body, hashlib.sha256 ).hexdigest() return hmac.compare_digest(expected, header) # In your Flask/FastAPI handler: sig = request.headers["X-DocuVision-Signature"] valid = verify_signature(WEBHOOK_SECRET, request.data, sig) if not valid: return "Unauthorized", 401
const crypto = require('crypto'); function verifySignature(secret, rawBody, header) { const expected = 'sha256=' + crypto .createHmac('sha256', secret) .update(rawBody) .digest('hex'); return crypto.timingSafeEqual( Buffer.from(expected), Buffer.from(header) ); } // In your Express handler (use raw body middleware): app.post('/webhook', express.raw({type: '*/*'}), (req, res) => { const valid = verifySignature( process.env.WEBHOOK_SECRET, req.body, req.headers['x-docuvision-signature'] ); if (!valid) return res.status(401).send('Unauthorized'); // process event... res.status(200).send('OK'); });
JSON Schema
Full schema for the document decision response object.
{
"$schema": "http://json-schema.org/draft-07/schema",
"title": "DocumentDecision",
"type": "object",
"properties": {
"document_id": { "type": "string", "pattern": "^doc_[0-9a-f]{16}$" },
"status": { "type": "string", "enum": ["uploaded","processing","extracted","decided","failed"] },
"progress": { "type": "integer", "minimum": 0, "maximum": 100 },
"fields": {
"type": "object",
"properties": {
"vendor": { "type": ["string","null"] },
"total": { "type": ["number","null"] },
"currency": { "type": ["string","null"], "pattern": "^[A-Z]{3}$" },
"date": { "type": ["string","null"], "format": "date" },
"payment_method": { "type": ["string","null"], "enum": ["card","cash","bank-transfer","paypal",null] }
}
},
"decision": {
"type": "object",
"properties": {
"decision": { "type": "string", "enum": ["auto_approve","review","reject"] },
"confidence": { "type": "number", "minimum": 0, "maximum": 1 },
"duplicate": { "type": "boolean" }
}
}
}
}
Error Codes
All errors return a JSON body with an
error field and an optional detail field.| HTTP | error | Meaning |
|---|---|---|
| 400 | missing_file | No file was attached to the request |
| 400 | invalid_file_type | File type not supported. Use PDF, JPG, or PNG |
| 400 | file_too_large | File exceeds 20 MB limit |
| 400 | invalid_metadata | The metadata field is not valid JSON |
| 401 | missing_api_key | X-API-Key header not present |
| 401 | invalid_api_key | Key does not exist or has been revoked |
| 404 | document_not_found | Document ID does not exist for this account |
| 409 | not_ready | Document is still processing — retry after polling |
| 429 | rate_limit_exceeded | 100 requests/day limit reached |
| 500 | storage_error | File could not be saved on the server |
| 500 | analysis_missing | Analysis record not found — contact support |
Error response shape
{
"error": "invalid_file_type",
"detail": "Accepted: PDF, JPG, PNG"
}