> ## Documentation Index
> Fetch the complete documentation index at: https://api.onlysocial.io/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`](https://api.onlysocial.io/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](https://api.onlysocial.io/publishing/posts/get-a-post.md).

**`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` |

### Channel connect

Only for connections a partner started through
Channel Connect. They report the outcome of the
onboarding — not a later token expiry or disconnection. See
[Channel Connect](https://api.onlysocial.io/partner/channel-connect.md).

| Event | Data |
| - | - |
| `salesbot.channel.connection.completed` | `channel`, `connection` |
| `salesbot.channel.connection.failed` | `channel`, `connection` |
| `salesbot.channel.connection.cancelled` | `channel`, `connection` |
| `salesbot.channel.connection.expired` | `channel`, `connection` |

`connection` carries `id` (the connection, not the channel), `platform`,
`status`, `channel_id` (only on `completed`), `error_code`, `state` and
`expires_at`.

```json theme={null}
{
  "event": "salesbot.channel.connection.completed",
  "data": {
    "channel": "whatsapp",
    "connection": {
      "id": "7f2c1a84-...",
      "platform": "whatsapp",
      "status": "connected",
      "channel_id": "b4e9d201-...",
      "error_code": null,
      "state": "dealer-4821",
      "expires_at": "2026-10-20T09:42:00+00:00"
    }
  }
}
```

### 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](https://api.onlysocial.io/ad-referrals.md) 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.

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.