Jobs & Queue
The async job lifecycle: webhooks (recommended), polling, and the job object.
Every extraction is a job. Creating one returns instantly with the job already in pending, and the work happens in a queue behind the scenes. You get the result by receiving a webhook (recommended) or by polling the job. This design means a slow or large document never blocks your request, and nothing is silently dropped. A job always ends in completed or failed.
Lifecycle
POST /jobs/create returns the full job object, the same shape as GET /jobs/:jobId/get, already in pending, with model, target, and the hold populated. output and the final token usage fill in once it finishes.
webhook_url and let Veralens push the result the moment the job finishes. It is lower latency, costs you no extra requests, and takes load off both your app and the API. Reach for polling only when you genuinely can't receive a webhook: a local script, a notebook, a one-off.Webhooks (recommended)
Pass a webhook_url when creating the job and Veralens will POST the result to it as soon as the job finishes. Webhooks require API-key auth. From a dashboard session, webhook_url returns 400 invalid_input.
Delivery payload. The body is one of:
For success, data is the parsed result (already an object for json targets, a string for markdown/plaintext). An error delivery means the job ended failed and its hold was refunded. It carries no reason.
Headers. Verify authenticity before trusting a delivery:
Checking the signature. v1 is the hex HMAC SHA-256 of the string <t>.<raw body>, keyed with the secret of the API key that created the job. Compute it over the body exactly as received, before you parse it, and compare in constant time. Refuse a t older than a few minutes. If you revoke that key, its webhooks stop being delivered. A Node example is in the Quickstart.
Retries. A delivery fails when your endpoint does not reply with a 2xx within 10 seconds. Redirects are not followed and count as a failure. Veralens then retries up to 6 more times, waiting 20, 40, 80, 160, 320 and 320 seconds before each try. URLs that point to a private or local network address are never called.
Two rules for a robust handler:
- Acknowledge fast, process after. Return
200immediately, then do the work. A slow handler looks like a failure and triggers retries. - Be idempotent on
job_id. A retry can deliver the same event twice; dedupe so you never double-process.
Polling (fallback)
When you can't receive a webhook, fetch the job until status is no longer pending. Poll every 2 to 3 seconds. GET /jobs/:jobId/get allows 30 requests a minute per key, so polling every second hits 429 after 30 seconds. See Rate limits.
The same in Python, with requests:
Billing per job
Creating a job places an estimated hold on your balance. When the job completes, the hold settles to the actual token cost, which can be higher or lower than the hold. If it fails, the hold is refunded in full. The final usage.cost on the job is what you were charged. See Pricing & Funds.
Listing and traceability
Use GET /jobs/list to page through past jobs, filter by status or source, or find a job by id with q. Every job keeps its target, engine, token usage, and cost, so you can audit exactly what each extraction did and what it cost.