VERINODE|API

Verinode Developer

Core concepts

Conventions that hold across every endpoint.

#Base URL and formats

Base URLhttps://api.verinode.ai/v1
IDsUUID strings.
TimestampsISO 8601 UTC.
MoneyDecimal strings ("18450.00"), never floats.
EnumsEvery enum value ships a humanized _label sibling on reads.

#Pagination

List endpoints are cursor-paginated. Pass ?limit= (1–100, default 25) and follow next_cursor:

GET /v1/jobs?limit=50
→ { "data": [...], "next_cursor": "…", "has_more": true, "synced_through": null }
GET /v1/jobs?cursor=<next_cursor>

The cursor is a keyset over (updated_at, id). Pass next_cursor back verbatim — don't parse or construct one. See Reading data for incremental sync.

#Idempotency

Idempotency-Key is honored on exactly four endpoints: POST /v1/documents, /v1/jobs, /v1/clients, and /v1/webhook-endpoints. On those, a retry replays the first response instead of re-executing it — no second extraction, no second Intelligence Unit charge, no duplicate record. Reuse a key with a different body and you get 422 idempotency_key_reuse rather than the earlier record's response: replaying there would silently drop your second write. Generate the key per payload, not per worker.

The header is ignored on POST /v1/events, /v1/events/batch, and /v1/exports. Sending it there does nothing at all:

#Rate limits and request IDs

Every authenticated response carries RateLimit-Limit / -Remaining / -Reset. Requests rejected before the key resolves — 401, 403 insufficient_scope, and the pre-auth per-address 429 — carry none, because there's no operator whose quota we could report. Exceeding a limit returns 429 with Retry-After.

Limits are hourly, per operator, per endpoint:

300/hrPOST /v1/documents, /v1/jobs, /v1/clients
5,000/hrPOST /v1/events
500/hrPOST /v1/events/batch (calls, not events — 1,000 events each)
600/hrList reads (/v1/jobs, /v1/vendors, /v1/clients), /v1/ping
1,000/hrSingle-record reads (/v1/jobs/{id} etc.), /v1/ingestions/{id}
20/hrPOST /v1/exports (and 4/day)
60/hrWebhook endpoint create/delete, export download

A separate pre-auth ceiling applies per IP address before any key is read; a normal integration never meets it.

Every response — including errors — carries a Verinode-Request-Id. Quote it in any support conversation.

#Where you can call it from

Server-side only. The API returns no CORS headers, so a browser fetch cannot call it from a web page. That's deliberate: an API key in frontend code is a leaked credential. Call it from your backend.