# Webhooks (/docs/developers/webhooks)

Get Discord or HTTP alerts when videos cross view targets, links go dead, creators stop posting or handles change, plus a daily performance report.

Webhooks let Bloss tell you when something happens in your brand. Each webhook goes either to a **Discord channel** (as a formatted message) or to **your own URL** (as JSON).

## Set up a webhook [#set-up-a-webhook]

1. Go to <UiPath>Settings › Integrations › Webhooks</UiPath> and click **Add integration**.
2. Choose the **Platform**: **Discord** (paste a Discord channel webhook URL) or **Custom** (any HTTPS endpoint you control).
3. Pick the **Video platforms** the webhook covers — Instagram, TikTok, YouTube, Facebook.
4. Turn on the alerts you want (below) and set their targets.
5. Click **Send test** to receive a sample, then save.

You can edit, pause (the **Enabled** switch) or delete a webhook at any time. Any brand admin can manage webhooks.

## Alerts [#alerts]

| Alert                        | Fires when                                                                                                                                                                                 | Settings                                                                                 | `type`                    |
| ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------- | ------------------------- |
| **Video view threshold**     | A video reaches the view count you set (default 10,000). It fires on the crossing, once per video.                                                                                         | View threshold, fields to include                                                        | `video_view_threshold`    |
| **Low-view alert**           | A video is still below your view target more than 24 hours after it was posted.                                                                                                            | View target, fields to include                                                           | `video_view_underperform` |
| **Inactive creator alert**   | A creator hasn't posted for longer than your window **and** their recent videos are all under your view target. One alert per creator; it can fire again after they post.                  | Inactive for (hours, default 72), view target (default 1,000), recent videos (default 5) | `creator_inactive`        |
| **Dead link alert**          | A tracked video's link is confirmed dead — deleted by the creator, set to private, or removed or archived. A video that's only missing from the creator's profile feed doesn't trigger it. | Fields to include                                                                        | `video_unavailable`       |
| **Handle change alert**      | A creator's handle stops working — either they renamed the account (the alert includes the new handle) or the account is gone.                                                             | —                                                                                        | `creator_handle_changed`  |
| **Daily performance report** | Once a day, a summary of **yesterday** in your brand's timezone: views, likes, comments, saves, shares, videos posted, creators who posted, and the top videos.                            | —                                                                                        | `daily_report`            |

Selectable **fields to include** for video alerts: creator name, platform, view count, video URL, caption, thumbnail URL and posted date.

## Delivery [#delivery]

- Bloss checks for new alerts **every hour**; daily reports are sent once per day after your brand's data for that day is complete.
- Each alert is sent **once**. A video alert is identified by the webhook, video, alert type and threshold — changing the threshold lets a video alert again.
- Requests are `POST` with `Content-Type: application/json` and a **10-second timeout**. Any `2xx` response counts as delivered.
- If your endpoint times out or returns a non-`2xx` status, the alert isn't marked as sent, so Bloss **tries again on the next hourly run**.

<Callout type="warn" title="Requests aren't signed">

  Custom webhook requests don't carry a signature or secret header. Use a long,
  unguessable URL (for example with a random token in the path), accept only
  `POST`, and treat the payload as a notification — fetch anything sensitive
  from the [Campaign API](/docs/developers/api-reference) instead.

</Callout>

## Custom payloads [#custom-payloads]

Every payload has a `type` and a `triggeredAt` ISO timestamp. Video alerts include only the fields you selected (plus `videoId`).

<Tabs items={['View threshold / low views', 'Dead link', 'Inactive creator', 'Handle change', 'Daily report']}>
<Tab>

```json
{
  "type": "video_view_threshold",
  "brand": { "id": "brd_123", "name": "Acme Skincare" },
  "threshold": 10000,
  "video": {
    "videoId": "vid_456",
    "creatorName": "Maya Lee",
    "platform": "tiktok",
    "views": 10342,
    "videoUrl": "https://www.tiktok.com/@maya/video/123",
    "caption": "My morning routine",
    "thumbnailUrl": "https://…",
    "postedAt": "2026-10-10T15:04:00.000Z"
  },
  "triggeredAt": "2026-10-12T09:00:12.000Z"
}
```

The low-view alert has the same shape with `"type": "video_view_underperform"`.

</Tab>
<Tab>

```json
{
  "type": "video_unavailable",
  "brand": { "id": "brd_123", "name": "Acme Skincare" },
  "threshold": 0,
  "video": { "videoId": "vid_456", "videoUrl": "https://…" },
  "unavailable": {
    "reason": "private",
    "label": "set to private",
    "detectedAt": "2026-10-12T06:30:00.000Z"
  },
  "triggeredAt": "2026-10-12T07:00:05.000Z"
}
```

`reason` is `deleted_by_author`, `private`, `not_found` (removed or archived) or `null` (no longer reachable).

</Tab>
<Tab>

```json
{
  "type": "creator_inactive",
  "brand": { "id": "brd_123", "name": "Acme Skincare" },
  "creator": { "id": "cr_789", "name": "Maya Lee" },
  "inactiveHours": 72,
  "viewTarget": 1000,
  "videoCount": 5,
  "hoursSinceLastPost": 96,
  "lastPostedAt": "2026-10-08T10:00:00.000Z",
  "recentVideos": [
    {
      "videoId": "vid_456",
      "platform": "instagram",
      "views": 412,
      "url": "https://…",
      "postedAt": "2026-10-08T10:00:00.000Z"
    }
  ],
  "triggeredAt": "2026-10-12T10:00:03.000Z"
}
```

</Tab>
<Tab>

```json
{
  "type": "creator_handle_changed",
  "brand": { "id": "brd_123", "name": "Acme Skincare" },
  "creator": { "id": "cr_789", "name": "Maya Lee" },
  "platform": "instagram",
  "kind": "handle_changed",
  "storedHandle": "mayalee",
  "detectedHandle": "maya.creates",
  "evidencePostUrl": "https://www.instagram.com/p/…",
  "detectedAt": "2026-10-12T05:00:00.000Z",
  "alertId": "alr_321",
  "triggeredAt": "2026-10-12T06:00:02.000Z"
}
```

`kind` is `handle_changed` (with the new handle in `detectedHandle`) or `profile_unavailable` (the account looks deleted, banned or private; `detectedHandle` is `null`).

</Tab>
<Tab>

```json
{
  "type": "daily_report",
  "brand": { "name": "Acme Skincare" },
  "date": "2026-10-11",
  "viewsToday": 128400,
  "likesToday": 9310,
  "commentsToday": 412,
  "savesToday": 655,
  "sharesToday": 380,
  "videosPostedToday": 24,
  "creatorsPostedToday": 11,
  "totalVideos": 1820,
  "topVideos": [
    {
      "creatorName": "Maya Lee",
      "url": "https://…",
      "platform": "tiktok",
      "caption": "My morning routine",
      "viewsGained": 41200,
      "likesGained": 3100,
      "commentsGained": 120,
      "sharesGained": 88
    }
  ],
  "triggeredAt": "2026-10-12T08:00:01.000Z"
}
```

The `…Today` figures are for `date` — yesterday in your brand's timezone.

</Tab>
</Tabs>
