# Texa Desk webhooks

Hear about every conversation, message, contact and ticket in Texa Desk, signed, as it happens.


Texa Desk webhooks tell your server what happens in the helpdesk: new conversations, every message
(from customers, your team and Texa AI), contact changes and tickets. Use them to copy conversations
into your own systems, update a CRM, or trigger your own work.

For events from **Texa API** conversations (replies, action requests, handovers), use the
[Texa API webhooks](/guides/webhooks) instead.

## Add a webhook

In Texa Desk, **Settings → Integrations → Webhooks → Add new webhook**: your URL and the events you
want. Each webhook has a **secret** (shown with an eye button, and copyable) that signs every
delivery. Or use the API: [Add a webhook](/api-reference/desk/webhooks/add-a-webhook).

## Events

| Event | When |
|---|---|
| `conversation_created` | a conversation starts |
| `conversation_updated` | a conversation's attributes change (assignee, team, labels, custom attributes, its ticket) |
| `conversation_status_changed` | it becomes open, pending, snoozed or resolved |
| `message_created` | a message is added: incoming, outgoing, or a private note |
| `message_updated` | a message changes (delivered, read, failed, edited) |
| `contact_created`, `contact_updated` | a contact is added or changed (including a merge) |
| `conversation_typing_on`, `conversation_typing_off` | someone in your team starts or stops typing |
| `webwidget_triggered` | a visitor opens the live chat on your website |
| `inbox_created`, `inbox_updated` | an inbox is added or changed |
| `ticket_created`, `ticket_updated`, `ticket_merged` | a [ticket](/desk/tickets) is made, changed (state, type, person) or merged |

## What arrives

```http
POST https://your-server/texa-desk/webhooks
Content-Type: application/json
X-Chatwoot-Delivery: 7b0d0d6e-0f6c-4b1e-9c0e-2b0d6a3a9f11
X-Chatwoot-Timestamp: 1790000000
X-Chatwoot-Signature: sha256=<hex HMAC-SHA256 of "1790000000.<raw body>" with the webhook's secret>
```

```json
{
  "event": "message_created",
  "id": 50211,
  "content": "Hello, my transfer of 80,000 has not arrived",
  "message_type": "incoming",
  "content_type": "text",
  "private": false,
  "created_at": "2026-10-19T10:00:03.112Z",
  "source_id": "wamid.HBgN...",
  "sender": {"id": 345, "name": "Ngozi Eze", "phone_number": "+2348031234567", "type": "contact"},
  "conversation": {"id": 171, "inbox_id": 12, "status": "pending", "...": "..."},
  "inbox": {"id": 12, "name": "WhatsApp"},
  "account": {"id": 1, "name": "Pilot Bank"}
}
```

- **Messages** carry `content`, `message_type` (`incoming`, `outgoing`, `activity`, `template`),
  `private` (a note your team only), `sender`, `conversation`, `inbox`, `account`, and
  `attachments` when there are files.
- **Conversation events** carry the conversation (with its `meta.sender`, `meta.assignee`, labels,
  custom attributes and `ticket`) and, for updates, `changed_attributes`: each changed field as
  `[before, after]`.
- **Contact events** carry the contact: `id`, `name`, `email`, `phone_number`, `identifier`,
  `custom_attributes`, `additional_attributes`.
- **Ticket events** carry the ticket (reference, title, type, state, person, team, promise),
  `contact`, `conversations`, and for `ticket_updated` its `changed_attributes`, the state and type
  by name: `"state": ["New", "Waiting on customer"]`.

## Check the signature

The signature is HMAC-SHA256 over `"<X-Chatwoot-Timestamp>.<raw body>"` with the webhook's secret,
written as `sha256=<hex>`. Compute it over the **raw** body, before parsing, compare in constant
time, and reject a timestamp older than five minutes. The code is the same as for
[Texa's own signatures](/authentication#checking-what-texa-sends-you), with these header names.

These header names come from the open-source Chatwoot helpdesk Texa Desk is built on, and are kept
so that existing integrations work unchanged.

## Answer fast

- Texa Desk waits **5 seconds** for your answer and sends each event **once**: there are no
  retries. Answer `200` at once and do the work afterwards (put the event on your own queue).
- Use `X-Chatwoot-Delivery` to spot a repeat.
- If your server was down, catch up from the API: [list conversations](/api-reference/desk/conversations/conversations-list)
  updated since then, and [their messages](/api-reference/desk/messages/get-messages).

## Per inbox: API inboxes

An [API inbox](/desk/api-channel) has its own webhook URL, which gets that inbox's events, signed
with the inbox's secret. That's how your own channel hears your team's replies.
