Webhooks
Subscribe your server to Chatasist events and receive signed, real-time HTTP callbacks.
Webhooks let your systems react to things that happen in Chatasist — a new conversation,
an agent reply, a CSAT rating — without polling the API. You register an HTTPS endpoint,
choose the events you care about, and Chatasist sends a signed POST request to that URL
whenever one of those events occurs.
This page covers event webhooks, which fire automatically every time something happens in your workspace. They are different from Automations, where the AI agent decides during a conversation to call a webhook you described to it. Event webhooks are managed by an Administrator.
Webhooks vs. Automations#
Both send an HTTP request to a URL you control, but they answer different needs. Webhooks tell your system what happened, every time. Automations let the AI agent take an action when it decides one is needed.
| Webhooks | Automations | |
|---|---|---|
| What triggers it | Chatasist, automatically, every time a subscribed event happens | The AI agent, when a conversation matches the description you wrote |
| Where you set it up | Settings → Webhooks | Automations in the sidebar |
| What you configure | An endpoint URL and the events to subscribe to | A name, key, "when to use it" description, and URL |
| What gets sent | Details of the conversation, message, call, or customer | The automation key, the agent's summary, the customer's email, and the chat ID |
| Signing | Always signed, with a secret Chatasist generates for you | Signed only if you set a signing secret |
| Delivery | Retried up to 4 times if your endpoint fails | Sent once |
| Availability | All plans, Administrator only | Scale plan and above |
| Typical use | Sync a CRM, send push notifications, feed analytics | "Open a ticket in Zendesk", "log this lead" through Zapier or Make |
Use a webhook when you need to know about every occurrence of something. Use an automation when the agent should judge, mid-conversation, whether to act.
Create a webhook#
Open the webhooks settings
In the web app, go to Settings → Webhooks.
Add your endpoint URL
Enter the HTTPS URL on your server that will receive events, e.g.
https://example.com/webhooks/chatasist.
Choose events
Tick the events you want delivered. Each event shows a short description of when it fires. You can subscribe one endpoint to as many events as you like.
Store your signing secret
When you create the endpoint, Chatasist shows a signing secret that starts with
whsec_. It is shown only once — copy it and store it securely. You'll use it to
verify that incoming requests really came from Chatasist.
Use the Send test button next to an endpoint to deliver a sample ping event and
confirm your server is reachable. The last response status code is shown on the endpoint.
How delivery works#
Each delivery is an HTTP POST with a JSON body in this shape:
{
"event": "message.outgoing",
"data": { "...": "event-specific payload" },
"sent_at": "2026-10-09T12:34:56+00:00"
}
Every request carries these headers:
| Header | Value |
|---|---|
Content-Type | application/json |
X-Chatasist-Event | the event name, e.g. message.outgoing |
X-Chatasist-Signature | sha256=<hmac> — see Verifying signatures |
Retries. If your endpoint doesn't return a 2xx status, Chatasist retries up to
4 times with increasing delays (about 10s, 60s, then 300s). Respond quickly with a
2xx and do any heavy work asynchronously — a slow endpoint may time out and be retried.
A single action can fire more than one event. Resolving a conversation fires both
conversation.status_changed and conversation.resolved. A new agent reply fires both
message.created and message.outgoing. Subscribe only to what you need.
Verifying signatures#
Chatasist signs the raw request body with your endpoint's secret using HMAC-SHA256 and
sends it in the X-Chatasist-Signature header as sha256=<hex digest>. Recompute the
digest with your secret and compare — reject the request if it doesn't match.
import crypto from "node:crypto"
// Capture the RAW body for signature verification.
app.post(
"/webhooks/chatasist",
express.raw({ type: "application/json" }),
(req, res) => {
const signature = req.get("X-Chatasist-Signature") ?? ""
const expected =
"sha256=" +
crypto
.createHmac("sha256", process.env.CHATASIST_WEBHOOK_SECRET)
.update(req.body) // raw Buffer
.digest("hex")
const ok =
signature.length === expected.length &&
crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected))
if (!ok) return res.sendStatus(401)
const { event, data } = JSON.parse(req.body.toString())
// ... handle the event, then:
res.sendStatus(200)
}
)
Events#
Conversations#
| Event | Fires when |
|---|---|
conversation.created | A new conversation was started. |
conversation.assigned | A conversation was assigned to an agent. |
conversation.unassigned | A conversation's agent assignment was removed. |
conversation.status_changed | A conversation moved between open, in progress, or resolved. |
conversation.resolved | A conversation was marked as resolved. |
conversation.reopened | A previously resolved conversation was reopened. |
conversation.priority_changed | A conversation's priority was changed. |
conversation.rated | A customer submitted a CSAT rating. |
conversation.human_requested | A customer asked to be handed from AI to a human agent. |
conversation.sentiment_changed | The detected sentiment of a conversation changed. |
{
"event": "conversation.resolved",
"data": {
"id": 456,
"conversation_id": "a1b2c3",
"customer_id": 123,
"channel_id": 7,
"assignee_id": 9,
"status": "resolved",
"priority": 1,
"survey_rating": null,
"sentiment": "positive",
"created_at": "2026-10-09T12:00:00+00:00"
},
"sent_at": "2026-10-09T12:34:56+00:00"
}
Messages#
| Event | Fires when |
|---|---|
message.created | Any new message was added (excludes internal notes). |
message.incoming | A customer sent a new message. |
message.outgoing | An agent or the AI replied. Useful for driving push notifications. |
note.created | An internal note was added (never visible to the customer). |
{
"event": "message.outgoing",
"data": {
"id": 9876,
"chat_id": 456,
"type": "message",
"sender_type": "User",
"sender_id": 9,
"internal": false,
"preview": "Hi, thanks for reaching out — I can help with that.",
"customer": {
"id": 123,
"external_customer_id": "crm-55",
"email": "jane@example.com"
},
"created_at": "2026-10-09T12:34:55+00:00"
},
"sent_at": "2026-10-09T12:34:56+00:00"
}
preview is a plain-text, truncated version of the message (HTML stripped, up to 280
characters). Use the API to fetch the full message if you
need it. The customer object gives you the identity to match the message to a user in
your own system — handy when sending a push notification.
Calls#
| Event | Fires when |
|---|---|
call.started | A voice or video call started in a conversation. |
call.ended | A voice or video call ended. |
call.recording_ready | A call recording finished processing and is available. |
{
"event": "call.recording_ready",
"data": {
"id": 42,
"chat_id": 456,
"type": "video",
"initiator_type": "User",
"initiator_id": 9,
"recording_url": "https://.../recording.mp4",
"started_at": "2026-10-09T12:10:00+00:00",
"ended_at": "2026-10-09T12:18:00+00:00"
},
"sent_at": "2026-10-09T12:34:56+00:00"
}
Customers#
| Event | Fires when |
|---|---|
customer.created | A new customer was created. |
customer.identified | An anonymous visitor became an identified customer. |
customer.updated | A customer's profile details were updated. |
{
"event": "customer.identified",
"data": {
"id": 123,
"external_customer_id": "crm-55",
"name": "Jane Doe",
"email": "jane@example.com",
"guest": false,
"created_at": "2026-10-09T11:00:00+00:00"
},
"sent_at": "2026-10-09T12:34:56+00:00"
}
Common use: push notifications#
To notify a customer's mobile app of a new reply, subscribe to message.outgoing. On
delivery, match data.customer to a user in your system, look up their device token, and
send the push through your own FCM/APNs setup. See the mobile SDK's push guidance for how
to avoid duplicate notifications while the app is in the foreground.
How to authenticate when calling the API to fetch full objects referenced by a webhook.

