Integrate
Webhooks
Get an event when a batch finishes, and verify it came from Anyrow.
Instead of polling a batch, register a webhook: when an extraction finishes, Anyrow posts an event to your HTTPS endpoint, signed with a secret only you and Anyrow know. Webhooks belong to an organization and need a plan that includes them.
EventsLink to section
| Event | When |
|---|---|
batch.complete | Every file in the batch was extracted |
batch.partial | Some files were extracted, some failed |
batch.failed | The batch produced no rows |
ping | You asked for a test delivery |
The body is JSON:
{ "api_version": "2026-03-01", "batch_id": "batch_01h5a3g8k9m2n4p6q8r0t2v4x6", "project_id": "proj_01h5a3g8k9m2n4p6q8r0t2v4x6", "status": "complete", "total_rows": 12, "duration_ms": 8421}Register your endpointLink to section
The response carries the webhook's signing
secret(whsec_...). Store it; it isn't shown again.curl -X POST "https://api.anyrow.ai/v1/organizations/$ORG_ID/webhooks" \ -H "Authorization: ApiKey $ANYROW_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "url": "https://example.com/hooks/anyrow", "events": ["batch.complete", "batch.failed"] }'Verify each deliveryLink to section
Deliveries follow the Standard Webhooks (opens in a new tab) spec. Three headers come with each one:
Header Holds webhook-idThe delivery's id, the same on every retry: use it to skip duplicates webhook-timestampWhen it was sent, in Unix seconds webhook-signaturev1,<base64>: an HMAC-SHA256 of{id}.{timestamp}.{body}Compute the signature over the raw body with your secret (base64-decoded, without
whsec_), compare it in constant time, and reject deliveries older than a few minutes. Any Standard Webhooks library does all of it:import { Webhook } from "standardwebhooks"const webhook = new Webhook(process.env.ANYROW_WEBHOOK_SECRET!.replace(/^whsec_/, ""))export async function POST(request: Request) { const body = await request.text() const event = webhook.verify(body, Object.fromEntries(request.headers)) // throws if forged // handle event.batch_id, event.status ... return new Response(null, { status: 204 })}Answer fastLink to section
Return a
2xxwithin 30 seconds, and do slow work after answering.
RetriesLink to section
A delivery that times out or gets a 5xx, 408 or 429 is retried up to 6 times, after 1
second, 5 seconds, 30 seconds, 5 minutes, 30 minutes and 2 hours. A Retry-After header on your
429 or 503 is honored (up to a day). Any other 4xx isn't retried. After 10 failed
deliveries in a row the webhook is disabled and you get a notification.
Test and rotateLink to section
- Send a test event to check your endpoint; it sends
ping. - Rotate the secret if it leaks. For 24 hours after a
rotation each delivery is signed with both secrets (two values in
webhook-signature), so you can deploy the new one without dropping events. - Deliveries lists recent attempts, with the status and body your endpoint returned.