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 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 request
Format
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.
LimitWindowReset
100 requestsper API key24 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

FieldTypeRequiredDescription
filefilerequiredPDF, JPG, or PNG. Max 20 MB.
metadatastringoptionalJSON 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

ValueMeaning
uploadedFile received, queued for processing
processingAI extraction in progress
extractedFields extracted, computing decision
decidedComplete — fields and decision available
failedProcessing 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

ValueConfidence rangeMeaning
auto_approve≥ 0.85High confidence extraction, no anomalies detected
review0.40 – 0.84Medium confidence — human review recommended
reject< 0.40 or duplicateLow 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

AttemptDelayCondition
1ImmediateAlways
23 secondsNon-2xx or network error
39 secondsNon-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.
HTTPerrorMeaning
400missing_fileNo file was attached to the request
400invalid_file_typeFile type not supported. Use PDF, JPG, or PNG
400file_too_largeFile exceeds 20 MB limit
400invalid_metadataThe metadata field is not valid JSON
401missing_api_keyX-API-Key header not present
401invalid_api_keyKey does not exist or has been revoked
404document_not_foundDocument ID does not exist for this account
409not_readyDocument is still processing — retry after polling
429rate_limit_exceeded100 requests/day limit reached
500storage_errorFile could not be saved on the server
500analysis_missingAnalysis record not found — contact support
Error response shape
{
  "error":  "invalid_file_type",
  "detail": "Accepted: PDF, JPG, PNG"
}