Webhook Events Reference
This page lists every event you can subscribe to, grouped by the entity that changed, with an example delivery for each payload shape.
For the delivery envelope format, property scoping, and signature verification, see Webhooks Overview.
Payload Shape
The envelope is the same for every event. Only data changes:
{
"id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"event": "audience_member.created",
"created_at": "2026-08-12T14:32:00+00:00",
"property": "magazine",
"data": { ... }
}
For every event except ping, data is a single JSON:API resource
object:
| Key | Description |
|---|---|
id | The record's identifier. |
type | The resource type, fixed per event group (for example audience_members). |
attributes | The record's fields. This is the part that differs between the shapes documented below. |
meta | Present only where noted below. Carries information about the record rather than its content. |
Events that share a shape share an example. All twenty-three subscribable events
resolve to one of eight shapes, plus ping.
The envelope's created_at, and any field the platform explicitly formats
(entitlement started_at and ended_at, and the ping's created_at), use an
offset — 2026-08-12T14:32:00+00:00. Record timestamps inside attributes use
the microsecond form — 2026-08-12T14:32:00.000000Z. Both are UTC and both
parse as ISO 8601; parse them, don't string-compare them.
Payloads are additive. A future release can add attributes, and data may carry
extra top-level keys such as relationships depending on how the record was
loaded when the event fired. Read the keys you need and ignore the rest.
Audience Member
These events fire when an audience member record is created, updated, or deleted.
| Event | Trigger |
|---|---|
audience_member.created | Fired when a new audience member is created. |
audience_member.updated | Fired when an audience member is updated (excludes activity-only changes). |
audience_member.deleted | Fired when an audience member is deleted. |
audience_member.updated is not fired for activity-only changes such as
last_active_at updates. It fires only when meaningful profile data changes.
meta inside attributes holds the member's raw meta values, keyed by meta key
and sorted alphabetically. Every value is a string, including numbers and
booleans. For the tenant-defined subset of these values, subscribe to the
user attribute events instead.
{
"id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"event": "audience_member.created",
"created_at": "2026-08-12T14:32:00+00:00",
"property": "magazine",
"data": {
"id": "9d5c1f2a-8b3e-4a17-9f6d-2c4b8e1a7d30",
"type": "audience_members",
"attributes": {
"name": "Jane Doe",
"email_verified": true,
"meta": {
"newsletter_opt_in": "1",
"postal_code": "90210"
},
"created_at": "2026-08-12T14:32:00.000000Z",
"updated_at": "2026-08-12T14:32:00.000000Z"
}
}
}
External Profile
External profiles store data from third-party providers (such as a CRM or identity provider) attached to a member.
| Event | Trigger |
|---|---|
audience_member.external_profile.created | Fired when an external profile is added to a member. |
audience_member.external_profile.updated | Fired when an external profile is updated. |
audience_member.external_profile.deleted | Fired when an external profile is removed. |
attributes is the provider's stored payload verbatim, so its keys are whatever
that provider supplies — the example below is illustrative, not a schema. Record
timestamps are under meta rather than attributes, because attributes is
entirely provider-controlled.
For the same reason, neither the member nor the provider name is in the payload:
data.id identifies the profile row, so key your records on it. If you need the
member, subscribe to the user attribute events as well — any
user attribute configured to read from this provider is re-synced when the
profile changes, and those events do carry audience_member_id.
{
"id": "b9f1c7d2-4a8e-4b03-9c15-6d2e8f3a1b47",
"event": "audience_member.external_profile.updated",
"created_at": "2026-08-12T14:35:12+00:00",
"property": "magazine",
"data": {
"id": "3f1b9c04-6d2e-4c8a-b5f7-1a9e3d7c2b48",
"type": "audience_member_external_profiles",
"attributes": {
"contact_id": "C-0031982",
"membership_level": "sustainer",
"lifetime_giving": 240,
"tags": ["donor", "event-attendee"]
},
"meta": {
"created_at": "2026-07-02T09:14:05.000000Z",
"updated_at": "2026-08-12T14:35:12.000000Z"
}
}
}
Foreign Key
Foreign keys link an audience member to an identifier in an external system (for example, a CRM contact ID or a subscriber ID in your publishing platform).
| Event | Trigger |
|---|---|
audience_member.foreign_key.created | Fired when a foreign key is attached to a member. |
audience_member.foreign_key.updated | Fired when a foreign key is updated. |
audience_member.foreign_key.deleted | Fired when a foreign key is removed. |
The payload carries the key and value pair but not the member it belongs to,
so key your records on data.id.
{
"id": "c1d4e8a2-7b39-4f65-8a02-3e9c5b1d7f84",
"event": "audience_member.foreign_key.created",
"created_at": "2026-08-12T14:36:40+00:00",
"property": "magazine",
"data": {
"id": "7e2a5c81-9d34-4b6f-a017-8c3e2f9b5d60",
"type": "audience_member_foreign_keys",
"attributes": {
"key": "contact_id",
"value": "C-0031982",
"created_at": "2026-08-12T14:36:40.000000Z",
"updated_at": "2026-08-12T14:36:40.000000Z"
}
}
}
User Attribute
User attributes are the tenant-defined profile fields configured in the admin. These events fire only for keys defined in the tenant's user attribute registry — internal and unmapped member meta keys are ignored.
| Event | Trigger |
|---|---|
audience_member.user_attribute.created | Fired when a user attribute value is set on a member for the first time. |
audience_member.user_attribute.updated | Fired when a user attribute value changes. |
audience_member.user_attribute.deleted | Fired when a user attribute value is removed from a member. |
slug is the attribute's slug from the registry, and value is always a string
regardless of the attribute's configured type. Unlike every other shape on this
page, id is a numeric string rather than a UUID — it identifies the stored
value, not the attribute definition, so key your own records on
audience_member_id plus slug.
{
"id": "a48f2d19-6c05-4e73-b8d1-9f27a3e5c064",
"event": "audience_member.user_attribute.updated",
"created_at": "2026-08-12T14:38:02+00:00",
"property": "magazine",
"data": {
"id": "1842",
"type": "audience_member_user_attributes",
"attributes": {
"audience_member_id": "9d5c1f2a-8b3e-4a17-9f6d-2c4b8e1a7d30",
"slug": "newsletter_opt_in",
"value": "1"
}
}
}
Entitlement
Entitlement events fire when a member's access to a product changes.
| Event | Trigger |
|---|---|
entitlement.created | Fired when an entitlement is granted. |
entitlement.updated | Fired when an entitlement is updated. |
entitlement.deleted | Fired when an entitlement is deleted. |
is_active is computed from started_at and ended_at at the moment the event
fired: an entitlement is active once started_at has passed and until
ended_at does. A null ended_at means indefinite access. Revoking an
entitlement sets ended_at and fires entitlement.updated, not
entitlement.deleted.
The entitlement's id is repeated inside attributes as well as at the top of
data. The member and the product are not in the payload — key your records
on the entitlement id, and read the member and product from the API when you
need them.
{
"id": "d7c93b15-2e48-4a06-91f5-7b3c8d2e6a19",
"event": "entitlement.created",
"created_at": "2026-08-12T14:40:18+00:00",
"property": "magazine",
"data": {
"id": "c8e40a72-5d16-4f39-8b2c-1e7a9d4f3b05",
"type": "entitlements",
"attributes": {
"id": "c8e40a72-5d16-4f39-8b2c-1e7a9d4f3b05",
"started_at": "2026-08-12T00:00:00+00:00",
"ended_at": null,
"note": "Granted by support",
"is_active": true,
"created_at": "2026-08-12T14:40:18.000000Z",
"updated_at": "2026-08-12T14:40:18.000000Z"
}
}
}
Purchase
Purchase events fire when a member's purchase is created or changes (for
example, a refund). Purchases are not hard-deleted, so there is no
purchase.deleted event.
| Event | Trigger |
|---|---|
purchase.created | Fired when a purchase is created. |
purchase.updated | Fired when a purchase is updated (for example, refunded). |
status is one of pending, completed, failed, or refunded. amount is
an integer in the currency's smallest unit — 999 with a currency of usd
means $9.99. The provider_* fields are the payment provider's own identifiers.
A purchase is created as pending, and an anonymous checkout is created with a
null audience_member_id and entitlement_id; both are filled in when the
payment is fulfilled. Expect every purchase.created to be followed by a
purchase.updated that carries the settled record.
{
"id": "e2a6f483-9c71-4d50-b8e3-4f1a7c9d2b60",
"event": "purchase.updated",
"created_at": "2026-08-12T14:42:55+00:00",
"property": "magazine",
"data": {
"id": "7a1e5b39-4c82-4067-9d1f-3b8e2a6c5d40",
"type": "purchase_webhooks",
"attributes": {
"id": "7a1e5b39-4c82-4067-9d1f-3b8e2a6c5d40",
"audience_member_id": "9d5c1f2a-8b3e-4a17-9f6d-2c4b8e1a7d30",
"device_session_id": "5b2f8c14-7a63-4e09-8d25-1f9c3b7a2e58",
"plan_id": "e91d4a07-3b56-4c82-9f14-6d2e8a5c1b73",
"entitlement_id": "c8e40a72-5d16-4f39-8b2c-1e7a9d4f3b05",
"provider": "stripe",
"provider_session_id": "cs_test_a1b2c3d4e5f6",
"provider_payment_id": "pi_3Q1a2b3c4d5e6f7g",
"provider_refund_id": null,
"status": "completed",
"amount": 999,
"currency": "usd",
"metadata": null,
"return_url": "https://acme.com/thank-you",
"created_at": "2026-08-12T14:41:03.000000Z",
"updated_at": "2026-08-12T14:42:55.000000Z"
}
}
}
Interaction
Interaction events fire when an interaction is created, updated, or deleted.
| Event | Trigger |
|---|---|
interaction.created | Fired when an interaction is created. |
interaction.updated | Fired when an interaction is updated. |
interaction.deleted | Fired when an interaction is deleted. |
status is draft or published. actions is the interaction's ordered
action list; every entry has a type, and the remaining keys depend on it.
Interactions are soft-deleted, so interaction.deleted carries the record with
deleted_at set rather than omitting it.
{
"id": "f5b81e27-6a94-4c13-8d70-2e9f4a1c6b38",
"event": "interaction.updated",
"created_at": "2026-08-12T14:45:20+00:00",
"property": null,
"data": {
"id": "2c9e7f14-8b05-4a63-91d8-5f3a2e7c4b19",
"type": "interaction_webhooks",
"attributes": {
"id": "2c9e7f14-8b05-4a63-91d8-5f3a2e7c4b19",
"title": "Sustainer Upsell",
"slug": "sustainer-upsell",
"status": "published",
"actions": [
{
"type": "template",
"template_id": "8d1f4a92-3c67-4b05-a2e8-7f9c1d5b3a26",
"target_selector": "#article-body",
"field_values": [
{
"slug": "headline",
"value": "Support independent reporting"
}
],
"placement_method": "before",
"truncation_unit": null,
"truncation_count": null,
"truncation_style": null,
"delay_type": null,
"delay_value": null,
"delay_scroll_unit": null,
"delay_scroll_selector": null
}
],
"created_at": "2026-08-01T10:02:44.000000Z",
"updated_at": "2026-08-12T14:45:20.000000Z",
"deleted_at": null
}
}
}
Template
Template events fire when a template is created, updated, or deleted.
| Event | Trigger |
|---|---|
template.created | Fired when a template is created. |
template.updated | Fired when a template is updated. |
template.deleted | Fired when a template is deleted. |
The payload includes the template's full html, js, and css bodies, so
template deliveries are the largest ones Allegro sends. fields describes the
template's field definitions, and the sync_source and github_* fields are
populated only for templates kept in sync with a Git repository. Templates are
soft-deleted, so template.deleted carries the record with deleted_at set.
{
"id": "0a3d9c76-4e18-4b52-8f01-6c7a2e9d5b34",
"event": "template.updated",
"created_at": "2026-08-12T14:48:07+00:00",
"property": null,
"data": {
"id": "8d1f4a92-3c67-4b05-a2e8-7f9c1d5b3a26",
"type": "template_webhooks",
"attributes": {
"id": "8d1f4a92-3c67-4b05-a2e8-7f9c1d5b3a26",
"title": "Sustainer Banner",
"slug": "sustainer-banner",
"status": "published",
"html": "<div class=\"banner\"><h2>{{ headline }}</h2></div>",
"js": "",
"css": ".banner { padding: 1rem; }",
"fields": [
{
"slug": "headline",
"description": "Banner headline",
"type": "text"
}
],
"external_css_urls": [],
"created_at": "2026-07-28T16:20:11.000000Z",
"updated_at": "2026-08-12T14:48:07.000000Z",
"deleted_at": null,
"sync_source": "github",
"github_path": "templates/sustainer-banner.html",
"github_sha": "9f2c1d7e8a3b4c5d6e7f8091a2b3c4d5e6f70819",
"github_commit_sha": "1a2b3c4d5e6f708192a3b4c5d6e7f8091a2b3c4d",
"synced_at": "2026-08-12T14:48:07.000000Z"
}
}
}
System
| Event | Trigger |
|---|---|
ping | A test event sent when an active webhook is created. |
ping is not subscribable — it is sent automatically and cannot be selected
when configuring event subscriptions.
The ping is the one delivery whose data is not a JSON:API resource object.
It echoes the webhook's own id, subscribed events, and created_at. Pings
ignore property scoping and, because webhooks are created from the organization
dashboard, normally carry property: null.
{
"id": "6d0f8a13-2b47-4e95-8c26-1a3f7d9b5e02",
"event": "ping",
"created_at": "2026-08-12T14:30:00+00:00",
"property": null,
"data": {
"id": "4b7e1c29-8d53-4a06-9f18-2e6c5b3a7d94",
"events": ["audience_member.created", "entitlement.created"],
"created_at": "2026-08-12T14:29:58+00:00"
}
}
Adding New Events
The subscribable event list is generated from the event registry in the platform. New event types registered there become immediately available in the webhook subscription UI and in this reference.
Related
- Webhooks Overview — creating webhooks, property scoping, delivery envelope, signature verification, and retries
- Properties — property hosts and the request context
that populates the envelope's
propertyfield - Entitlements — how entitlements and products work
- Audience Members — member profiles and data