Skip to Content
WebhooksOverview

Webhooks — Overview

Webhooks are how Inferio tells your server when extraction starts, progresses, and lands. You register an endpoint at request-creation time (or set a global default in the dashboard); we POST signed JSON the moment each lifecycle event fires.

The three events

Every request emits the same three events, in order:

EventWhenFields you’d act on
ocr.request.createdRight after POST /api/v1/ocr/requests acceptsrequest_id, total_images, created_at
ocr.document.processingPer-page, when the LLM picks it updocument_id, source_url
ocr.document.completedPer-page, when extraction lands (success OR rejected)fields, confidence, status

Most downstream pipelines only need to wire ocr.document.completed — that’s the canonical “extraction done, act on it” event.

Payload envelope

// POST $webhook_url // Headers: // X-Inferio-Signature: t=1735634283,v1=4f5a89e2b1d2c8f3... // X-Inferio-Event: ocr.document.completed // X-Inferio-Delivery: whd_8a7c2e0fa912 // Content-Type: application/json { "event": "ocr.document.completed", "delivery_id": "whd_8a7c2e0fa912", "occurred_at": "2026-04-30T03:18:06.421Z", "merchant_id": "merchant_abc123", "request_id": "req_3fa1c4e2b9d1", "document_id": "doc_8a7c2e0fa912", "status": "completed", "fields": { /* extracted fields per document_type schema */ }, "confidence": { /* per-field 0.0–1.0 scores */ } }

Delivery guarantees

  • At-least-once. If your endpoint times out or returns non-2xx, Inferio retries with exponential backoff (6 attempts over ~24h: 30s, 2m, 10m, 1h, 6h, 24h).
  • Idempotent. Dedupe on delivery_id — the same delivery_id may arrive multiple times across the retry window.
  • Ordered per document_id, not globally. A multi-page request can have pages complete out of order — don’t assume page 1 fires before page 2.

After 6 failed attempts, deliveries land in the dead-letter outbox. Replay them from the dashboard or via POST /api/v1/ocr/webhooks/deliveries/{id}/replay.

Configuring endpoints

Two options:

Per-request (one-off integrations)

Pass webhook_url in the request body:

curl -X POST https://api-dev.inferio.xyz/api/v1/ocr/requests \ -H "Authorization: Bearer $INFERIO_TOKEN" \ -H "X-Merchant-ID: $MERCHANT_ID" \ -H "Content-Type: application/json" \ -d '{ "session_id": "f47ac10b-…", "document_type": "trade_invoice_jp", "webhook_url": "https://yourdomain.com/webhooks/inferio" }'

Global default (production)

Dashboard → Settings → Webhooks → Add endpoint.

  • Set a URL — must be HTTPS
  • Pick event types to subscribe (default: all three)
  • The dashboard shows you the whsec_ signing secret — copy it immediately; you can’t see it again after closing the dialog

Requests that don’t specify webhook_url inherit the global default. Requests that DO specify one override the default for that request only.

Test ping

Every endpoint has a Send test event button in the dashboard. It fires a synthetic ocr.document.completed with deterministic fixture data so you can verify your signature + JSON parsing without burning a real OCR credit.

Next