For the complete documentation index, see llms.txt. This page is also available as Markdown.
Connections

Webhook payloads

The completion callbacks, their payloads, and how to verify them.

Polling a slow job is wasteful when the platform can tell you the moment it finishes. Webhooks are the push half of the API: you register an HTTPS endpoint once, and every completed extraction, classification and generation arrives as a signed POST.

This page covers the contract — how to verify a delivery and what each payload contains. For delivery monitoring, retry behaviour and the operational view, see Webhooks & Integrations.

Configuring an endpoint

Webhook endpoints are configured in the portal, not through the API.

  1. Sign in as Admin or Owner.

  2. Go to Settings → Edit Account Information.

  3. Enter your endpoint in Webhook URL and save.

The same panel holds your Webhook Signing Key (whk_…), revealed with Reveal / Copy by account owners. You need it to verify signatures.

Endpoints are account-wide: every matching event goes to every configured URL. The one exception is Generation, whose request accepts a per-job webhookUrl — extraction and classification requests do not.

Verifying a delivery

Every request carries an x-signature header: the HMAC-SHA256 of the raw request body, keyed with your signing key, hex-encoded.

const crypto = require('crypto');

const secret    = process.env.WEBHOOK_PRIVATE_KEY;
const signature = req.headers['x-signature'];
const payload   = JSON.stringify(req.body);

const hmac   = crypto.createHmac('sha256', secret);
const digest = hmac.update(payload).digest('hex');

if (signature === digest) {
    // Request is authentic
}

Two practical notes on the example above. Compare digests with a constant-time comparison (crypto.timingSafeEqual) rather than === in production. And verify against the raw body exactly as received — re-serialising with JSON.stringify after your framework has parsed it can reorder keys and invalidate an otherwise valid signature.

Handling duplicates

Every payload carries an eventId. Deliveries retry, so the same event can arrive more than once.

Record eventId values you have processed and discard repeats. Make the handler idempotent rather than assuming exactly-once delivery — retries are a normal part of the mechanism, not an error condition.

Payload types

All payloads share _id, status, metadata and eventId. Beyond that the shape depends on what finished.

Document extraction — the default

Batch extraction — webhookType: batch_extraction

A summary-level update for a batch job rather than a per-document result.

Property extraction — webhookType: propertyExtraction

Sent when property-specific data is extracted, such as Form 8825.

Document generation

Carries a signed downloadUrl for the finished file.

Document classification

Sent when a classification group job completes.

Group fields

Some fields appear only for multi-document jobs, and knowing when they are absent matters as much as knowing what they mean.

Field
Present when

extractionGroupId, extractionGroupIndex, extractionGroupTotal

Multi-extraction is enabled — PDF, Excel or ZIP files containing several documents or triggers. extractionGroupId links the parts; index and total let you track progress

classificationGroupId, classificationGroupIndex, classificationGroupTotal

Only when a ZIP is uploaded for classification. Standard PDF and Excel classification requests do not carry them

Use Index and Total to decide when a set is complete rather than assuming a delivery order.

Delivery status on the record

An extraction record carries a webhookStatus object:

Last updated