Events
Every event type an endpoint can subscribe to, and what its data contains.
| Event | When it's sent |
|---|---|
content.published | A version of a tour, tooltip, banner, checklist, survey or announcement was published to an environment (also on rollback). |
content.unpublished | Content was taken down from an environment, or deleted while live. |
publish_request.created | Someone asked for content to be reviewed before publishing. |
publish_request.approved | A review request was approved, and the version published. |
publish_request.rejected | A review request was rejected. |
guidance.completed | An end user completed a tour, tooltip or banner. |
guidance.dismissed | An end user dismissed or skipped a tour, tooltip or banner. |
survey.answered | An end user finished a survey: completed it, or answered some questions and closed it. |
member.joined | Someone joined the workspace (invite, single sign-on or SCIM). |
The Send test event button (and POST /api/webhooks/{id}/test) sends webhook.test, which endpoints can't subscribe to.
Data by event
content.published
JSON
{
"contentType": "tour",
"contentId": 318,
"name": "Invoice flow",
"environment": "production",
"version": 7,
"versionId": 1290,
"publishedBy": { "userId": 12, "email": "ada@acme.com" },
"rollback": false,
"requestId": 55
}rollback is true when an earlier version was published again. requestId is there when the publish came from an approved review request.
content.unpublished
JSON
{
"contentType": "banner",
"contentId": 77,
"name": "Maintenance window",
"environment": "production",
"reason": "unpublished",
"unpublishedBy": { "userId": 12, "email": "ada@acme.com" }
}reason is unpublished or deleted.
publish_request.created, .approved, .rejected
JSON
{
"requestId": 55,
"contentType": "tour",
"contentId": 318,
"name": "Invoice flow",
"environment": "production",
"version": 7,
"versionId": 1290,
"status": "pending",
"note": "New step for exports",
"requestedBy": { "userId": 31, "email": "sam@acme.com" },
"reviewer": null,
"reviewNote": null
}guidance.completed, guidance.dismissed
JSON
{
"contentType": "tour",
"contentId": 318,
"contentName": "Invoice flow",
"stepIndex": 4,
"stepId": 2210,
"reason": "skip",
"userId": "user-123",
"anonymousId": "…",
"sessionId": "…",
"url": "https://app.example.com/invoices",
"occurredAt": "2026-10-26T09:30:00.000Z"
}stepIndex (0-based) is where the person finished or left a tour. reason is only on guidance.dismissed: dismiss (closed) or skip (skipped the tour). userId is the id you passed to Cueston.identify(), or null for anonymous visitors.
survey.answered
JSON
{
"surveyId": 9,
"surveyName": "NPS — Q4",
"responseId": "…",
"version": 3,
"environment": "production",
"completed": true,
"npsScore": 9,
"answers": [
{ "questionId": "how-likely", "type": "nps", "prompt": "How likely are you to recommend us?", "value": 9 },
{ "questionId": "why", "type": "text", "prompt": "What's the main reason?", "value": "Fast exports" }
],
"userId": "user-123",
"anonymousId": "…",
"sessionId": "…",
"url": "https://app.example.com/reports",
"locale": "en",
"createdAt": "2026-10-26T09:29:12.000Z",
"finishedAt": "2026-10-26T09:30:00.000Z"
}Sent once per response.
member.joined
JSON
{ "userId": 87, "email": "lee@acme.com", "role": "member", "source": "invite" }source is invite, sso or scim.