Skip to main content
This is the complete list of events the platform emits. Subscribe to the ones you care about in Settings → Webhooks. Subscribing to a new event has no effect on existing endpoints — each endpoint receives only events it explicitly opted into. Payloads are delivered as the body of a POST, with metadata (event type, delivery id, signature) in headers. See Overview for the delivery shape and Signing for verification.
Webhook payloads use camelCase field names. This differs from the REST API’s snake_case responses — historical and not worth breaking compatibility over. Within each side, the convention is consistent.

Chatbots

chatbot.created

Fires when a chatbot is created via dashboard or POST /chatbots.

chatbot.updated

Fires on any mutation of a chatbot’s configuration — name, status, system prompt, attached pages, etc.

chatbot.deleted

Fires when a chatbot is hard-deleted.

Conversations

conversation.created

Fires when an end-user starts a new conversation with a chatbot. The bot has been provisioned but no user messages have been sent yet.
qrCodeId / productId / objectId reflect the entry surface — null if the conversation didn’t originate from a scan.

conversation.updated

Fires when any conversation field changes: status, priority, title, contact info, assignment. Payload includes the new state and a changes object describing the diff.

message.created

Fires for every new message in a conversation — user, assistant, system. System messages include an event field describing what triggered them (status change, human takeover, conversation reopen).
role is one of user, assistant, system. For assistant messages, source is "bot", "human", or "api" (when delivered via POST /conversations/{id}/messages). For user messages, source is "email" when the message arrived via inbound email reply, otherwise absent.

Messages with attachments

When the message carries image attachments, message.attachments is included. The field is omitted entirely when there are none — don’t expect an empty array.
string (uuid)
required
Stable identifier for the underlying bytes in the org’s asset library. Re-attaching the same image to a different message returns the same assetId. Treat as opaque.
string
required
Public URL to fetch the image. Long-lived — content-addressed paths never expire and are immutable.
string
required
MIME type as detected by Awardee’s pipeline. May differ from the original upload if the asset was re-encoded by the compression step (e.g. image/png → image/webp).
string
required
Human-readable filename, used as <img alt> text. May fall back to a generic name (upload, image.png) when the source had no filename (paste from clipboard, inline email image).
URLs are content-addressed within an organization. Attaching the same image bytes to two different messages — even in different conversations — produces the same url and assetId. Don’t dedupe webhook events by attachment URL; use message.id for message-level idempotency.

Submissions

page.submission.created

Fires when an end-user submits a form attached to a page.

submission.updated

Fires on any mutation of a submission — status, priority, flag, assignment, notes.

QR codes

qr_code.scanned

Fires on every scan of a tracked QR code, including from misconfigured codes and scans that resolve to “not found”.

qr_code.updated

Fires on any mutation — destination changes, name, description, properties, URL params, status. Payloads include article_ids and category_ids (the QR code’s linked knowledge). A PATCH that changes only those still fires qr_code.updated.

QR groups

qr_group.created / qr_group.updated

qr_group.updated also fires when the group’s properties are replaced (PUT /qr-groups/{id}/properties), so you can resync without polling. Payloads include article_ids and category_ids (the group’s linked knowledge). A PATCH that changes only those still fires qr_group.updated.
A group-level destination is inherited by every child code that doesn’t override it.

qr_group.deleted

Products

product.scanned

Fires when a GS1 Digital Link URL resolves to one of your products.

product.created / product.updated

Payloads include article_ids and category_ids (the product’s linked knowledge). A PATCH that changes only those still fires product.updated.

product.deleted

Objects

Programmable scan URLs that aren’t QR codes or products — custom-typed entities you mint and resolve under /o/<slug>.

object.scanned

object.created / object.updated

Payloads include article_ids and category_ids (the object’s linked knowledge). A PATCH that changes only those still fires object.updated.

object.deleted

The slug stays permanently reserved so analytics rows keep their references — it will never be reassigned to a new object.

Articles

article.created / article.updated

article.published

Fires when an article transitions from draft to published (and on first publish of a translation).

article.unpublished

Fires when an article transitions back to draft / unpublished / archived.

article.deleted

article.indexed

Fires when the embedding pipeline finishes writing chunks for an article (primary language + every translation). The article is now retrievable via chatbot search.
language is the article’s primary language; languages lists every language that was embedded in this run (primary + each translation that had content).

article.indexing_failed

Fires when the embedding pipeline errors out for an article. indexing_status on the article is set to failed and the error string travels in this payload (it isn’t exposed via the public API).

Article categories

article_category.created / article_category.updated

article_category.deleted

A cascade delete of a non-empty category also emits one article.deleted per child article.

Members

member.invited

Fires when an org owner sends an invite.

member.joined

Fires when an invited user accepts and is added to the org.

member.removed

Fires when a member is removed from the org, or when the org is deleted (one event per remaining member).
reason is one of "removed", "org_deleted", "left".

Customers

customer.created

Fires when a new identified customer is created — one carrying a strong key (email, phone, or external_id). Anonymous visitors (resolved by visitor hash only) and name-only leads do not trigger this event, so you only hear about real people. Created via the identify/upsert endpoint, a human attaching a contact in the inbox, or a form submission that supplies an email.

customer.updated

Fires when an identified customer’s editable fields change — name, email, phone, external id, or custom attributes — whether edited from the dashboard, the conversation inbox, or PATCH /customers/{id}. The payload is the full current customer in the same shape as customer.created.
Pair customer.created and customer.updated to keep an external CRM in sync. Match on external_id (your system’s id) when present, otherwise email.