Skip to content

Webhooks

Webhooks let Infinite Audience tell your application when asynchronous work is ready. Your workflow moves on immediately—no polling loop required.

Event Use it when
segment.ready A file match or segment build completed
segment.failed A file match or segment build needs attention
delivery.completed An export or destination delivery completed
delivery.failed A delivery needs attention
  1. Add webhook_url to one request for a one-off callback.
  2. Set an organization URL with PUT /v1/settings/webhook for a shared default.
  3. Create a durable subscription when an app should receive selected event types across the account.
Terminal window
curl -X POST https://api.infiniteaudience.ai/v1/webhook-subscriptions \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"target_url":"https://your-app.example.com/webhooks/infinite-audience",
"events":["segment.ready","segment.failed","delivery.completed","delivery.failed"]
}'

Copy the returned secret into your secret manager when it appears. Like an API key, its plaintext is shown once.

Every event uses a consistent envelope:

{
"id": "evt_1a2b3c",
"type": "segment.ready",
"created_at": "2026-08-26T18:04:12.000Z",
"api_version": "2026-08-06",
"org_id": "org_xyz",
"subject": {"kind":"segment","id":"seg_abc123","name":"Spring customers"},
"data": {"status":"completed","match_count":1200000},
"links": {}
}

Use type to route the event, subject to identify the work, and data for the event-specific result. Treat additional fields as compatible additions.

Each request includes X-IA-Timestamp and X-IA-Signature. Compute HMAC-SHA256(secret, "{timestamp}.{raw_body}"), prefix the hex digest with v1=, compare in constant time, and reject timestamps older than five minutes.

import { createHmac, timingSafeEqual } from 'crypto';
export function verify(rawBody: Buffer, timestamp: string, signature: string, secret: string) {
const age = Math.abs(Math.floor(Date.now() / 1000) - Number(timestamp));
if (!Number.isFinite(age) || age > 300) return false;
const expected = Buffer.from(`v1=${createHmac('sha256', secret).update(`${timestamp}.${rawBody}`).digest('hex')}`);
const received = Buffer.from(signature);
return expected.length === received.length && timingSafeEqual(expected, received);
}

Use this fixed test vector to confirm that your HMAC code produces the same signature before you connect a live endpoint:

Secret: whsec_test
Timestamp: 1700000000
Raw body: {"id":"evt_test","type":"segment.ready"}
Expected signature: v1=665cf5f9d7444181e6ea95771d98ec6865abff200494207281ce9e3041e7b35b

The timestamp is intentionally fixed for repeatable testing, so test the signature calculation separately from your five-minute freshness check.

Return a 2xx response quickly, then queue slower work. Infinite Audience retries timeouts, 408, 429, and 5xx responses up to 10 total attempts; 410 Gone ends delivery for that endpoint.