> ## Documentation Index
> Fetch the complete documentation index at: https://workspace.guide/llms.txt
> Use this file to discover all available pages before exploring further.

# Events

> Every event you can subscribe to, and what its data contains.

The authoritative list for your workspace is [`GET /api/v1/workspace-webhooks/events`](/webhooks/manage#list-available-events). It includes each event's JSON schema and a sample. This page summarises it.

Fields that have no value are left out of `data`. IDs are always UUIDs.

## Publishing events

| Event | When |
| - | - |
| `publishing.account.added` | A social account is connected |
| `publishing.account.updated` | A social account changes |
| `publishing.account.deleted` | A social account is removed |
| `publishing.post.scheduled` | A post is scheduled |
| `publishing.post.published` | A post is published |
| `publishing.post.publishing_failed` | Publishing a post failed |
| `publishing.post.deleted` | Posts are deleted or moved to trash |

**Account events** carry the account's `id`, `name`, `provider` (for example `instagram`) and `status`. `account.deleted` carries `id` and `"deleted": true`.

**Post events** carry the post's `id` and a numeric `status`. Fetch the full post with [Get a post](/publishing/posts/get-a-post).

**`post.deleted`** carries `ids` (a list of post IDs), `deleted` and `to_trash`.

```json theme={null}
{ "event": "publishing.post.deleted", "data": { "ids": ["1e7d9b0a-..."], "deleted": false, "to_trash": true } }
```

## Messaging events

Messaging events can be limited to one channel per subscription: `whatsapp`, `facebook`, `instagram`, `sms` or `tiktok`, or `all`.

### Contacts

| Event | Data |
| - | - |
| `salesbot.contact.created` | `contact` |
| `salesbot.contact.updated` | `contact` |
| `salesbot.contact.tagged` | `contact`, `tag` |
| `salesbot.contact.untagged` | `contact`, `tag` |
| `salesbot.contact.stage_changed` | `contact`, `stage`, `previous_stage` |
| `salesbot.contact.date_reached` | `contact`, `event`, `date` (`field`, `value`) |

### Conversations and messages

| Event | Data |
| - | - |
| `salesbot.message.received` | `contact`, `conversation`, `message` |
| `salesbot.conversation.assigned` | `contact`, `conversation`, `assigned_to` (`name`) |
| `salesbot.conversation.closed` | `contact`, `conversation` (`id`, `status`) |
| `salesbot.message.sent` | `channel`, `provider`, `contact`, `conversation`, `message` |
| `salesbot.message.delivered` | same as `message.sent` |
| `salesbot.message.read_or_seen` | same as `message.sent` |
| `salesbot.message.failed` | same as `message.sent`, with `message.error_code` |

Not every channel reports every message status:

| Channel | Sent | Delivered | Read / seen | Failed |
| - | - | - | - | - |
| WhatsApp | Yes | Yes | Limited | Yes |
| Facebook | Yes | Yes | Yes | Yes |
| Instagram | Yes | No | Yes | Yes |
| SMS | Yes | Limited | No | Yes |
| TikTok | No | No | No | No |

You can't subscribe a channel to a status it never reports.

### Automations and broadcasts

| Event | Data |
| - | - |
| `salesbot.automation.triggered` | `contact`, `automation` |
| `salesbot.automation.completed` | `contact`, `automation` |
| `salesbot.automation.failed` | `contact`, `automation` |
| `salesbot.broadcast.sent` | `broadcast` |
| `salesbot.broadcast.completed` | `broadcast` |
| `salesbot.broadcast.failed` | `broadcast` |

### Payments and bookings

| Event | Data |
| - | - |
| `salesbot.payment.succeeded` | `contact`, `payment` |
| `salesbot.payment.failed` | `contact`, `payment` |
| `salesbot.payment.refunded` | `contact`, `payment` |
| `salesbot.booking.created` | `contact`, `booking` |
| `salesbot.booking.rescheduled` | `contact`, `booking` |
| `salesbot.booking.cancelled` | `contact`, `booking` |

### Store

All store events carry `event`, `contact` and `order`.

`salesbot.store.order_created`, `salesbot.store.order_paid`, `salesbot.store.payment_failed`, `salesbot.store.checkout_abandoned`, `salesbot.store.order_fulfilled`, `salesbot.store.order_cancelled`, `salesbot.store.order_refunded`, `salesbot.store.product_back_in_stock`, `salesbot.store.inventory_low`, `salesbot.store.customer_milestone`

## Data objects

| Object | Fields |
| - | - |
| `contact` | `id`, `name`, `email`, `phone`, `platform`, `stage`, `tags`, `created_at`, and `source` on `message.received` (see below) |
| `conversation` | `id`, `status` |
| `message` | `id`, `text`, `type`, `platform`, `direction`, `status`, `sent_at`, `status_at`, `error_code`, and `referral` on `message.received` (see below) |
| `automation` | `id`, `name`, `builder` |
| `broadcast` | `id`, `name`, `recipients`, `sent`, `failed` |
| `payment` | `id`, `provider`, `amount`, `currency`, `status`, `paid_at` |
| `booking` | `id`, `meeting_type`, `status`, `scheduled_at`, `ends_at` |
| `order` | `id`, `number`, `total`, `currency`, `status`, `provider` |

Text fields are capped at 1,000 characters (`message.text` at 10,000) and lists at 100 items. Contact and message events can include personal data such as names, emails, phone numbers and message text, so protect your receiver accordingly.

### Ad referrals on `message.received`

`salesbot.message.received` carries two extra fields that tell you which ad brought the person in. No other event changes.

* **`message.referral`**: the Click-to-WhatsApp, Click-to-Messenger or Click-to-Instagram ad, or `m.me` / `ig.me` ref link, this message came from. It's `null` on an ordinary message.
* **`contact.source`**: the contact's first touch, as text. For example `Messenger ad: 2021 Toyota Corolla LE`, `Instagram ad: Autumn sale`, `WhatsApp ad: ...` or `WhatsApp post: ...`. It's `null` when the contact didn't come from an ad.

`message.referral` is the same 12-key object the [Messaging API](/ad-referrals) returns:

| Key | Meaning |
| - | - |
| `source` | `ad`, `post` (a WhatsApp ad pointing at an organic post) or `link` (a ref link) |
| `ad_id`, `ad_title`, `body` | The ad's ID, headline and text |
| `photo_url`, `video_url`, `thumbnail_url` | The ad's image, video and video thumbnail |
| `source_url` | Link to the ad or post |
| `post_id` | The post the ad points at |
| `product_id` | For catalog ads, the catalog product the person tapped |
| `ref` | The `ref` parameter of the ad or link |
| `ctwa_clid` | Click ID (WhatsApp only) |

Every key is present, and `null` when Meta didn't send it. Links are only passed on when they are plain `http(s)` URLs with no username or password and at most 2,048 characters; any other link becomes `null`. Links are never shortened.

<Warning>
  The media links are Meta CDN links and they expire. If you need the image or video later, copy it when the webhook arrives.
</Warning>

When someone taps an ad without writing anything, an inbound message reading `Opened the chat from an ad` is recorded with the referral, so you still get a `message.received` for the tap.

### Example

```json theme={null}
{
  "id": "a3f1c0e2-...",
  "schema_version": "1",
  "event": "salesbot.message.received",
  "product": "salesbot",
  "occurred_at": "2026-10-18T12:00:00Z",
  "workspace_id": "c2a4f0d1-58e4-4c1b-a1f7-2b6f3e9d0a11",
  "test": false,
  "data": {
    "contact": {
      "id": "5b1e...",
      "name": "Ada Lovelace",
      "platform": "facebook",
      "source": "Messenger ad: 2021 Toyota Corolla LE"
    },
    "conversation": { "id": "5b1e..." },
    "message": {
      "text": "Is this still available?",
      "type": "text",
      "platform": "facebook",
      "direction": "inbound",
      "referral": {
        "source": "ad",
        "ad_id": "120210000000000000",
        "ad_title": "2021 Toyota Corolla LE",
        "body": "Low mileage, one owner. Message us to book a test drive.",
        "photo_url": "https://scontent.xx.fbcdn.net/v/t45.1600-4/corolla.jpg",
        "video_url": null,
        "thumbnail_url": null,
        "source_url": null,
        "post_id": null,
        "product_id": "6543210987654321",
        "ref": null,
        "ctwa_clid": null
      }
    }
  }
}
```


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.