Infinite Audience Webhooks API
**Outbound webhook notifications** — the platform POSTs to your endpoint when async operations finish. **Events fired:** | Event | Trigger | |---|---| | `segment.ready` | Async segment build succeeded (matched, similarity, propensity) | | `segment.failed` | Async segment build failed | | `delivery.completed` | File export/download ready | | `delivery.failed` | File export/download failed | `integration.enrichment.blocked` fires when a run is refused on billing grounds — the account's budget ceiling or balance would be exceeded — and is delivered org-wide like the events above. OAuth partnerships may additionally subscribe their own grant to `integration.enrichment.prepared`, `integration.enrichment.failed`, `integration.file.ready`, and `integration.file.failed`. Those callbacks are delivered only to the owning grant's subscription and never to the org-wide webhook. **URL precedence** — per-request `webhook_url` > org-configured URL (Settings) > no dispatch. If an individual API request includes `webhook_url`, that URL is used for that call only; the org-level URL is not called. Omitting `webhook_url` on a request falls back to the org URL. **Payload shape** — every dispatch (org-configured URL, per-request `webhook_url`, and durable subscriptions alike) sends the same canonical envelope: `{id, type, created_at, api_version, org_id, subject, data, links}`. `type` is the event name (e.g. `segment.ready`); `subject` identifies what the event is about (`{kind, id, name}`); `data` carries `status` plus event-specific fields — see each event below for its exact shape. **Signing** — every outbound dispatch is signed. The signing secret is platform-generated — you never supply one — and shown to you exactly once: in the response of `PUT /v1/settings/webhook` (the first time a webhook is configured) or `POST /v1/settings/webhook/secret` (rotate), or in the response of `POST /v1/webhook-subscriptions` for a durable subscription. Verifying is optional; every dispatch includes: ``` X-IA-Timestamp: X-IA-Signature: v1= ``` computed as `HMAC-SHA256(secret, "{timestamp}.{raw-request-body}")`. To verify: reject if `timestamp` is more than 300 seconds old, then recompute the HMAC over the exact raw request body bytes and compare with `crypto.timingSafeEqual` (or equivalent) — never compare against a re-serialized/re-parsed body, since re-serialization is not guaranteed to produce identical bytes.