VERINODE|API

Verinode Developer

Document ingestion

Push documents through the extraction pipeline.

POST /v1/documents runs the same LLM extraction as email and in-app uploads. Processing is asynchronous: you get a 202 with an ingestion id, then poll GET /v1/ingestions/{id} for the result and the extraction receipt. Requires the ingest scope.

curl -X POST https://api.verinode.ai/v1/documents \
  -H "Authorization: Bearer $KEY" -H "Idempotency-Key: $(uuidgen)" \
  -F file=@water-mitigation-invoice.pdf
→ 202 { "id": "…", "status": "processing" }

curl -H "Authorization: Bearer $KEY" https://api.verinode.ai/v1/ingestions/<id>
→ { "status": "completed", "receipt": { "document_type": "Water Mitigation Invoice",
    "saved": ["Job Costs", "Vendor"], "transforms": [...] } }

Accepts PDF, JPEG, PNG, CSV, XLSX/XLS, DOCX/DOC, TXT, up to 25 MB (413 over that, 415 for anything else). HEIC and HEIF are rejected with 415: convert to JPEG or PNG first. Rate limit: 300 documents/hour.

#Two ways to send bytes

Multipart is the simpler lane: send a file part and the filename rides along with it.

On the JSON lane, filename is required alongside content_base64 — omit it and the call fails with 400 missing_file no matter how valid the bytes are. It isn't cosmetic: the extension is how the content type gets resolved when you don't send content_type.

curl -X POST https://api.verinode.ai/v1/documents \
  -H "Authorization: Bearer $KEY" -H "content-type: application/json" \
  -d '{ "filename": "invoice.pdf",           // required
        "content_type": "application/pdf",   // optional, inferred from filename
        "content_base64": "JVBERi0xLjQK…" }'

#Polling

processing is the only non-terminal status — keep polling while you see it. It resolves to completed, failed, or canceled (the operator aborted it in the dashboard; it will never be processed, so stop polling and re-send if you still need it). The receipt shows exactly what was detected, saved, and normalized. Verinode shows its work.

#What it costs

Live keys are charged 3 Intelligence Units per document, at accept — when the 202 is returned and the document is queued, not when extraction runs and not when it succeeds. A document that extracts nothing useful, or fails outright, is not refunded. A 202 means the Intelligence Units are already spent. If your balance is exhausted the call returns 402 before anything is queued.

Because the charge lands at accept, Idempotency-Key matters more here than anywhere else: a retried POST without one is a second charge. With one, the first response replays and nothing is charged twice.

Test keys are free, but they run the same real extraction pipeline, so they're capped at 25 documents per day per sandbox — over that returns 429 sandbox_quota.