Events
Event Subscription Events
Subscription key: event_subscription
All events on this page are delivered to the URL configured under event_subscription. This subscription covers the lifecycle of a Thrive Event: the event itself, its occurrences, and its attendees.
Every payload carries the complete current state of what it describes. Delivery is at-least-once and unordered.
Shared Objects
These objects appear throughout the payloads below. Each event section lists its own top-level fields and refers back here.
content
| Field | Type | Nullable | Description |
|---|---|---|---|
content.id |
string | No | Event ID |
content.title |
string | Yes | Event title. May be null if the lookup failed at dispatch time |
content.type |
string | Yes | Content type, always event on this subscription. May be null if the lookup failed |
content.urls |
string[] | No | Full URLs to the event on each of your configured tenant domains, can be empty if content lookup fails |
content.isDraft |
boolean | Yes | true until the event is first published, false afterwards. null on the cleanup events, where there is no longer a record to read |
user
The user who performed the action. The attendees array uses the same shape.
| Field | Type | Nullable | Description |
|---|---|---|---|
user.id |
string | No | User ID |
user.reference |
string | Yes | External reference (e.g. HR system ID) |
user.email |
string | Yes | User email address |
user.firstName |
string | Yes | User’s first name |
user.lastName |
string | Yes | User’s last name |
occurrence
A scheduled instance of an event, carried by every event that describes a live occurrence.
spacesandspacesRemainingarenullwhen the occurrence has no seat limit.nullmeans unlimited, not zero.
sessions,hostsandoccurrencesare always the complete current set. A removed entry is signalled only by its absence from the array.
| Field | Type | Nullable | Description |
|---|---|---|---|
id |
string | No | Occurrence ID |
label |
string | Yes | Occurrence label. May be null if the organiser did not set one |
timezone |
string | Yes | IANA timezone. null if the stored value does not resolve to a zone |
timezoneRaw |
string | Yes | The timezone as stored, including values timezone could not resolve |
spaces |
number | Yes | Seat limit. null if the occurrence has no limit |
spacesRemaining |
number | Yes | Seats left, floored at zero. null if the occurrence has no limit |
attendeeCount |
number | No | Users currently registered on the occurrence. Marking attendance or cancelling removes a user from this count |
sessionCount |
number | No | Number of sessions on the occurrence |
isPast |
boolean | No | true once the latest session end time has passed |
hosts |
object[] | No | Occurrence hosts, can be empty |
hosts[].id |
string | No | Host user ID |
hosts[].reference |
string | Yes | External reference (e.g. HR system ID) |
sessions |
object[] | No | The complete current set of sessions. See session below |
session
meetingMeta.meetingUrlis a joining link, as islocationwhenisWebinaristrue. Anyone holding either can enter the meeting.
| Field | Type | Nullable | Description |
|---|---|---|---|
id |
string | No | Session ID |
startDateTime |
string | No | ISO 8601 timestamp of when the session starts, in UTC |
endDateTime |
string | No | ISO 8601 timestamp of when the session ends, in UTC |
location |
string | Yes | Where the session takes place. A joining link when isWebinar is true |
isWebinar |
boolean | No | Whether the session is delivered online |
meetingMeta |
object | Yes | Online meeting details. null if no meeting is attached |
meetingMeta.provider |
string | Yes | Meeting provider (e.g. microsoftteams) |
meetingMeta.meetingId |
string | Yes | Provider meeting ID |
meetingMeta.meetingUrl |
string | Yes | Joining link |
occurrence (cleanup form)
Used by event.archived, event.deleted and event.occurrence-deleted. The underlying records no longer exist by the time these are sent, so the occurrence is described by the IDs of what it held rather than by its sessions and counts.
| Field | Type | Nullable | Description |
|---|---|---|---|
id |
string | No | Occurrence ID |
label |
string | Yes | Occurrence label. May be null if the organiser did not set one |
timezone |
string | Yes | IANA timezone. null if the stored value does not resolve to a zone |
timezoneRaw |
string | Yes | The timezone as stored, including values timezone could not resolve |
sessionIds |
string[] | No | IDs of the sessions that existed, can be empty |
sessionIdsTruncated |
boolean | No | true if the session IDs were dropped to keep the message within size limits |
attendeeRefs |
object[] | No | Users holding a booking when the occurrence was removed. Registered attendees only, with no email or name. Can be empty |
attendeeRefs[].id |
string | No | User ID |
attendeeRefs[].reference |
string | Yes | External reference (e.g. HR system ID) |
attendeeRefsTruncated |
boolean | No | true if the list was cut short to keep the message within size limits |
event.* — Event Lifecycle Events
Fired when an event is created or changes state.
Event types: event.created · event.published · event.updated · event.restored
Only
event.creatednames the user who acted. The other three are derived from signals that carry no acting user.
Edits to an unpublished draft do not fire
event.updated. Update signals are only emitted for published content.
| Field | Type | Nullable | Description |
|---|---|---|---|
eventType |
string | No | One of the 4 event types listed above |
tenantId |
string | No | Your Thrive tenant identifier |
content |
object | No | The event. See content above |
occurrences |
object[] | No | The complete current set of occurrences. See occurrence above. Can be empty on a draft with no dates scheduled |
occurrenceCount |
number | No | Number of entries in occurrences |
user |
object | Yes | User who triggered the event. Always null on event.published, event.updated and event.restored |
createdAt |
string | No | ISO 8601 timestamp of when the event occurred on the platform |
dispatchedAt |
string | No | ISO 8601 timestamp of when this webhook was dispatched |
Example payload (event.published):
{
"eventType": "event.published",
"tenantId": "eu-west-2_AbC123",
"content": {
"id": "665f1a2b3c4d5e6f70819293",
"title": "Advanced Negotiation Skills",
"type": "event",
"urls": ["https://acme.thrive.app/content/665f1a2b3c4d5e6f70819293"],
"isDraft": false
},
"occurrences": [
{
"id": "6670bb11aa22cc33dd44ee55",
"label": "London — October cohort",
"timezone": "Europe/London",
"timezoneRaw": "Europe/London",
"spaces": 24,
"spacesRemaining": 22,
"attendeeCount": 2,
"sessionCount": 1,
"isPast": false,
"hosts": [{ "id": "664a1b2c3d4e5f6071829304", "reference": "EMP-1043" }],
"sessions": [
{
"id": "6670cc22bb33dd44ee55ff66",
"startDateTime": "2026-10-14T08:30:00.000Z",
"endDateTime": "2026-10-14T12:00:00.000Z",
"location": "Kings Cross Hub, Room 4",
"isWebinar": false,
"meetingMeta": null
}
]
}
],
"occurrenceCount": 1,
"user": null,
"createdAt": "2026-08-04T09:30:00.000Z",
"dispatchedAt": "2026-08-04T09:30:01.150Z"
}
event.archived / event.deleted — Event Cleanup Events
Fired when an event is archived or deleted.
Event types: event.archived · event.deleted
event.archivedlists every occurrence the event had, including ones that have already taken place, not only the ones removed.
Neither event names the user who acted.
| Field | Type | Nullable | Description |
|---|---|---|---|
eventType |
string | No | event.archived or event.deleted |
tenantId |
string | No | Your Thrive tenant identifier |
content |
object | No | The event. See content above. content.isDraft is null |
occurrences |
object[] | No | Every occurrence the event had. See occurrence (cleanup form) above |
occurrenceCount |
number | No | Number of entries in occurrences |
user |
object | Yes | Always null on these events |
createdAt |
string | No | ISO 8601 timestamp of when the event occurred on the platform |
dispatchedAt |
string | No | ISO 8601 timestamp of when this webhook was dispatched |
Example payload (event.archived):
{
"eventType": "event.archived",
"tenantId": "eu-west-2_AbC123",
"content": {
"id": "665f1a2b3c4d5e6f70819293",
"title": "Advanced Negotiation Skills",
"type": "event",
"urls": ["https://acme.thrive.app/content/665f1a2b3c4d5e6f70819293"],
"isDraft": null
},
"occurrences": [
{
"id": "6670bb11aa22cc33dd44ee55",
"label": "London — October cohort",
"timezone": "Europe/London",
"timezoneRaw": "Europe/London",
"sessionIds": ["6670bb11aa22cc33dd44ee56", "6670bb11aa22cc33dd44ee57"],
"sessionIdsTruncated": false,
"attendeeRefs": [
{ "id": "6601aa000000000000000001", "reference": "EMP-001" },
{ "id": "6601aa000000000000000002", "reference": "EMP-002" }
],
"attendeeRefsTruncated": false
}
],
"occurrenceCount": 1,
"user": null,
"createdAt": "2026-08-04T10:00:00.000Z",
"dispatchedAt": "2026-08-04T10:00:01.200Z"
}
event.occurrence-created / event.occurrence-updated — Occurrence Events
Fired when an occurrence is added to an event, or when its label, timezone, hosts, capacity or sessions change.
Event types: event.occurrence-created · event.occurrence-updated
One edit can fire several events. Adding three occurrences at once sends three
event.occurrence-createdwebhooks.
| Field | Type | Nullable | Description |
|---|---|---|---|
eventType |
string | No | event.occurrence-created or event.occurrence-updated |
tenantId |
string | No | Your Thrive tenant identifier |
content |
object | No | The parent event. See content above |
occurrence |
object | No | The occurrence in full. See occurrence above |
user |
object | Yes | User who triggered the event |
createdAt |
string | No | ISO 8601 timestamp of when the event occurred on the platform |
dispatchedAt |
string | No | ISO 8601 timestamp of when this webhook was dispatched |
Example payload (event.occurrence-created):
{
"eventType": "event.occurrence-created",
"tenantId": "eu-west-2_AbC123",
"content": {
"id": "665f1a2b3c4d5e6f70819293",
"title": "Advanced Negotiation Skills",
"type": "event",
"urls": ["https://acme.thrive.app/content/665f1a2b3c4d5e6f70819293"],
"isDraft": false
},
"occurrence": {
"id": "6670bb11aa22cc33dd44ee55",
"label": "London — October cohort",
"timezone": "Europe/London",
"timezoneRaw": "Europe/London",
"spaces": 24,
"spacesRemaining": 22,
"attendeeCount": 2,
"sessionCount": 2,
"isPast": false,
"hosts": [{ "id": "6601aa000000000000000009", "reference": "EMP-4471" }],
"sessions": [
{
"id": "6670bb11aa22cc33dd44ee56",
"startDateTime": "2026-10-14T08:30:00.000Z",
"endDateTime": "2026-10-14T12:00:00.000Z",
"location": "Kings Cross Hub, Room 4",
"isWebinar": false,
"meetingMeta": null
},
{
"id": "6670bb11aa22cc33dd44ee57",
"startDateTime": "2026-10-21T08:30:00.000Z",
"endDateTime": "2026-10-21T10:00:00.000Z",
"location": "https://teams.microsoft.com/l/meetup-join/...",
"isWebinar": true,
"meetingMeta": {
"provider": "microsoftteams",
"meetingId": "19:meeting_abc...",
"meetingUrl": "https://teams.microsoft.com/l/meetup-join/..."
}
}
]
},
"user": {
"id": "6601aa000000000000000009",
"reference": "EMP-4471",
"email": "jane.smith@example.com",
"firstName": "Jane",
"lastName": "Smith"
},
"createdAt": "2026-08-04T09:14:02.400Z",
"dispatchedAt": "2026-08-04T09:14:03.977Z"
}
event.occurrence-deleted — Occurrence Cleanup Events
Fired when an occurrence is removed from an event.
Event types: event.occurrence-deleted
attendeeRefslists who held a booking at the moment the occurrence was removed. Someone who cancelled shortly beforehand will not appear in it.
| Field | Type | Nullable | Description |
|---|---|---|---|
eventType |
string | No | event.occurrence-deleted |
tenantId |
string | No | Your Thrive tenant identifier |
content |
object | No | The parent event. See content above. content.isDraft is null |
occurrence |
object | No | The removed occurrence. See occurrence (cleanup form) above |
user |
object | Yes | User who triggered the event |
createdAt |
string | No | ISO 8601 timestamp of when the event occurred on the platform |
dispatchedAt |
string | No | ISO 8601 timestamp of when this webhook was dispatched |
Example payload:
{
"eventType": "event.occurrence-deleted",
"tenantId": "eu-west-2_AbC123",
"content": {
"id": "665f1a2b3c4d5e6f70819293",
"title": "Advanced Negotiation Skills",
"type": "event",
"urls": ["https://acme.thrive.app/content/665f1a2b3c4d5e6f70819293"],
"isDraft": null
},
"occurrence": {
"id": "6670bb11aa22cc33dd44ee55",
"label": "London — October cohort",
"timezone": "Europe/London",
"timezoneRaw": "Europe/London",
"sessionIds": ["6670bb11aa22cc33dd44ee56", "6670bb11aa22cc33dd44ee57"],
"sessionIdsTruncated": false,
"attendeeRefs": [
{ "id": "6601aa000000000000000001", "reference": "EMP-001" }
],
"attendeeRefsTruncated": false
},
"user": {
"id": "6601aa000000000000000009",
"reference": "EMP-4471",
"email": "jane.smith@example.com",
"firstName": "Jane",
"lastName": "Smith"
},
"createdAt": "2026-08-04T09:20:10.002Z",
"dispatchedAt": "2026-08-04T09:20:11.510Z"
}
event.attendee-registered / event.attendee-cancelled — Attendee Events
Fired when one or more users are registered onto, or removed from, an occurrence.
Event types: event.attendee-registered · event.attendee-cancelled
attendeesis always an array. An admin registering or removing a group sends a single event covering all of them, and a very large group is split across several events, each a complete payload.
Promoting someone from a waitlist is a registration, with
registrationSourceset towaitlist-promotion. There is no separate waitlist event.
| Field | Type | Nullable | Description |
|---|---|---|---|
eventType |
string | No | event.attendee-registered or event.attendee-cancelled |
tenantId |
string | No | Your Thrive tenant identifier |
content |
object | No | The parent event. See content above |
occurrence |
object | No | The occurrence in full. See occurrence above |
attendees |
object[] | No | The users registered or removed. Same shape as user above |
registrationSource |
string | No | self, admin or waitlist-promotion. Sent on event.attendee-registered, omitted on event.attendee-cancelled |
cancellationSource |
string | No | self or admin. Sent on event.attendee-cancelled, omitted on event.attendee-registered |
user |
object | Yes | User who triggered the event |
createdAt |
string | No | ISO 8601 timestamp of when the event occurred on the platform |
dispatchedAt |
string | No | ISO 8601 timestamp of when this webhook was dispatched |
Example payload (event.attendee-registered):
{
"eventType": "event.attendee-registered",
"tenantId": "eu-west-2_AbC123",
"content": {
"id": "665f1a2b3c4d5e6f70819293",
"title": "Advanced Negotiation Skills",
"type": "event",
"urls": ["https://acme.thrive.app/content/665f1a2b3c4d5e6f70819293"],
"isDraft": false
},
"occurrence": {
"id": "6670bb11aa22cc33dd44ee55",
"label": "London — October cohort",
"timezone": "Europe/London",
"timezoneRaw": "Europe/London",
"spaces": 24,
"spacesRemaining": 20,
"attendeeCount": 4,
"sessionCount": 1,
"isPast": false,
"hosts": [{ "id": "6601aa000000000000000009", "reference": "EMP-4471" }],
"sessions": [
{
"id": "6670bb11aa22cc33dd44ee56",
"startDateTime": "2026-10-14T08:30:00.000Z",
"endDateTime": "2026-10-14T12:00:00.000Z",
"location": "Kings Cross Hub, Room 4",
"isWebinar": false,
"meetingMeta": null
}
]
},
"registrationSource": "admin",
"attendees": [
{
"id": "6601aa000000000000000001",
"reference": "EMP-001",
"email": "alice.jones@example.com",
"firstName": "Alice",
"lastName": "Jones"
}
],
"user": {
"id": "6601aa000000000000000009",
"reference": "EMP-4471",
"email": "jane.smith@example.com",
"firstName": "Jane",
"lastName": "Smith"
},
"createdAt": "2026-08-04T09:25:00.000Z",
"dispatchedAt": "2026-08-04T09:25:01.220Z"
}
event.attendance-marked — Attendance Events
Fired when attendance is recorded for an occurrence. Attendance applies to every session of the occurrence, so the payload lists the sessions it covers rather than singling one out.
Event types: event.attendance-marked
Marking attendance removes a user from
occurrence.attendeeCount, which raisesoccurrence.spacesRemainingin turn.
| Field | Type | Nullable | Description |
|---|---|---|---|
eventType |
string | No | event.attendance-marked |
tenantId |
string | No | Your Thrive tenant identifier |
content |
object | No | The parent event. See content above |
occurrence |
object | No | The occurrence in full. See occurrence above |
sessionIds |
string[] | No | IDs of the sessions the attendance covers |
attendances |
object[] | No | The attendance records, with no email or name |
attendances[].id |
string | No | User ID |
attendances[].reference |
string | Yes | External reference (e.g. HR system ID) |
attendances[].status |
string | No | present or absent |
user |
object | Yes | User who triggered the event |
createdAt |
string | No | ISO 8601 timestamp of when the event occurred on the platform |
dispatchedAt |
string | No | ISO 8601 timestamp of when this webhook was dispatched |
Example payload:
{
"eventType": "event.attendance-marked",
"tenantId": "eu-west-2_AbC123",
"content": {
"id": "665f1a2b3c4d5e6f70819293",
"title": "Advanced Negotiation Skills",
"type": "event",
"urls": ["https://acme.thrive.app/content/665f1a2b3c4d5e6f70819293"],
"isDraft": false
},
"occurrence": {
"id": "6670bb11aa22cc33dd44ee55",
"label": "London — October cohort",
"timezone": "Europe/London",
"timezoneRaw": "Europe/London",
"spaces": 24,
"spacesRemaining": 22,
"attendeeCount": 2,
"sessionCount": 1,
"isPast": true,
"hosts": [{ "id": "6601aa000000000000000009", "reference": "EMP-4471" }],
"sessions": [
{
"id": "6670bb11aa22cc33dd44ee56",
"startDateTime": "2026-10-14T08:30:00.000Z",
"endDateTime": "2026-10-14T12:00:00.000Z",
"location": "Kings Cross Hub, Room 4",
"isWebinar": false,
"meetingMeta": null
}
]
},
"sessionIds": ["6670bb11aa22cc33dd44ee56"],
"attendances": [
{
"id": "6601aa000000000000000001",
"reference": "EMP-001",
"status": "present"
},
{
"id": "6601aa000000000000000002",
"reference": "EMP-002",
"status": "absent"
}
],
"user": {
"id": "6601aa000000000000000009",
"reference": "EMP-4471",
"email": "jane.smith@example.com",
"firstName": "Jane",
"lastName": "Smith"
},
"createdAt": "2026-10-14T12:05:00.000Z",
"dispatchedAt": "2026-10-14T12:05:01.300Z"
}