Webhooks
Webhooks are the push half of the async model: instead
of polling a resource until its status is terminal, register an HTTPS endpoint
and Intuizi calls you the moment an audience, activation or cohort completes
or fails. The payload carries the same object the matching GET endpoint
returns, so no follow-up read is needed.
Registration is in the console
Webhook endpoints are created, edited, rotated, paused and deleted in the Intuizi console only, under My Organization > Webhooks. There is no write API: a webhook endpoint is durable organization configuration holding a signing secret, and an API token must never be able to silently retarget where your completion events are pushed.
The API exposes exactly one read,
GET /api/v2/webhooks/index, so an
integration can confirm from code that a subscription exists and which event
types it covers. The signing secret never appears in any API response.
When you create an endpoint you choose:
- the URL - must be
https://, on the default port, using a public hostname (IP addresses, private hosts and redirecting URLs are rejected), - the event types it subscribes to (see the catalog below),
- and you receive the signing secret exactly once, at creation. Store it immediately; afterwards only a masked fragment is shown. Rotating generates a new secret (also shown once) and keeps the old one valid for 24 hours so you can switch without dropping events.
Event catalog
Six event types, each sent once a resource has finished. 104 Completed is
the only successful lifecycle state - 105 DataStreaming happens before
it, so there is deliberately no “delivering” event, and no progress events.
| Event type | Fires when | data is the object returned by |
|---|---|---|
audience.completed | an audience or lookalike reaches lifecycle status 104 Completed | Get Audience |
audience.failed | an audience or lookalike fails: it stops at 107 Additional Info or reaches a 4xx lifecycle error status, including the 400 a cancelled lookalike ends at | Get Audience |
activation.completed | an activation reaches lifecycle status 104 Completed | Get Activation |
activation.failed | an activation fails: it stops at 107 Additional Info or reaches a 4xx lifecycle error status | Get Activation |
cohort.completed | a cohort reaches status 4 Completed | Get Cohort |
cohort.failed | a cohort reaches status 5 Not Available: the import failed | Get Cohort |
Four catalog notes:
- Lookalikes are audiences. A completed lookalike arrives as
audience.completedwithdata.is_lookalikeset totrue- filter on that field if you handle them differently. 107Additional Info is a failure. A build that stops at107sends the sameaudience.failedoractivation.failedevent as a4xxerror state. Readdata.status.idto tell them apart. The payload carries only the status id and name, and Audience Manager shows the reason.- Cohorts use their own status scale (
1-5), not the1xxlifecycle. See Status Codes. - Every failure sends an event. Besides
107and the4xxstates, that covers a Lookalike Model run you cancel, which ends at400Error and sendsaudience.failed, and a failed cohort import, which ends at5Not Available and sendscohort.failed. A poll is only the fallback for a delivery that exhausts its retries - see Webhooks or polling?.
A webhook.test event can also be sent from the console at any time to
exercise your receiver; it is delivered regardless of your subscriptions and
its data is a small fixed object, not a resource.
The delivery
Every delivery is an HTTPS POST to your URL with these headers:
Content-Type: application/json
User-Agent: Intuizi-Webhooks/1
Intuizi-Event-Id: evt_01K9Z4F0J6R8QW3T5Y7B2N4M6C
Intuizi-Event-Type: audience.completed
Intuizi-Delivery-Id: dlv_01K9Z4F0J8H2V5X7C9E1G3J5L7
Intuizi-Delivery-Attempt: 1
Intuizi-Signature: t=1774102711,v1=8f3c...e91aand this body:
{
"schema_version": 1,
"id": "evt_01K9Z4F0J6R8QW3T5Y7B2N4M6C",
"type": "audience.completed",
"created_at": "2026-07-21T14:05:11Z",
"company_id": 55,
"data": { }
}datais the resource object exactly as the matchingGETreturns it - the object itself, not the single-elementdataarray the GET envelope wraps it in. Field-level schemas are on the Webhooks API page.- Payloads are additive: new fields can appear in
datawithout aschema_versionbump, so your consumer must tolerate and ignore fields it does not recognize rather than rejecting the delivery.eligibilityandtotalswere added to the audience object on 2026-08-23. ididentifies the logical event. It is identical across retries and across all of your endpoints that receive the same event.- The envelope
created_atis RFC 3339 UTC (2026-07-21T14:05:11Z). Note the timestamps insidedatause the API’sY-m-d H:i:sformat - they are different fields with different formats.
Respond with any 2xx status within 10 seconds. The response body is ignored
(at most a short snippet is kept for the console delivery log). Redirects are
not followed - a 3xx counts as a failed delivery.
Verifying the signature
Every delivery is signed with your endpoint’s secret so you can prove it came
from Intuizi and was not altered. The Intuizi-Signature header carries a unix
timestamp and one or more HMAC-SHA256 signatures over "{t}.{raw_body}":
Intuizi-Signature: t=1774102711,v1=8f3c...e91aTo verify:
- Read
tand eachv1value from the header. - Compute
HMAC_SHA256(secret, t + "." + raw_body)over the raw request body bytes (before any JSON parsing). - Compare against each
v1using a constant-time comparison. Accept if any matches. - Reject if
tis more than 5 minutes from your current time - this bounds replay of a captured delivery.
During the 24 hours after a secret rotation the header carries two v1
values (new secret first, then old), so a receiver holding either secret keeps
verifying. Code samples in four languages are on the
Webhooks API page.
Delivery semantics
- At-least-once. A delivery can arrive more than once (for example when
your server processed it but the response was lost). Deduplicate on
Intuizi-Event-Idand make your handler idempotent. - Ordering is not guaranteed across events. Use the resource id and status
inside
data, not arrival order. - Retries. A failed delivery (non-
2xx, timeout, or connection error) is retried up to 6 times over roughly 8.5 hours, with growing gaps (about 1 minute, then 5, 25, 2 hours, 6 hours after the first attempt).Intuizi-Delivery-Attempttells you which attempt you are seeing. - Auto-disable. After 20 consecutive exhausted deliveries the endpoint is disabled automatically and its creator is notified in the console. Re-enabling is a console action and resets the failure counter.
- The delivery log for each endpoint (status, attempts, response code, response snippet) is visible in the console next to the endpoint.
Webhooks or polling?
Use webhooks as the primary completion signal - they remove the wasted request
budget and the discovery latency of polling. Keep a low-frequency poll (or an
on-demand GET) as the fallback for the rare delivery that exhausts its
retries: webhooks are a notification channel, not a source of truth. The
resource itself, read via GET, is always the source of truth.