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

# Notifications

> Send workload events to an HTTP receiver or Slack webhook. Delivery is saved separately from task execution, so a destination outage does not change a completed run's outcome.

How-to guideApplies to: Unified engine deployments

Send workload events to an HTTP receiver or Slack webhook. Delivery is saved separately from task execution, so a destination outage does not change a completed run's outcome.

## Before you start

You need a reachable destination and an instance that permits external HTTP. Store bearer tokens or Slack webhook URLs in [Secrets](https://docs.e6data.com/transformation/learn/secrets.md). Use secret references in the workload instead of copying tokens into definitions.

Start with a small Manual workload so you can check delivery without enabling a recurring schedule.

## 1. Add a destination

In workload details, expand **Callbacks and notifications** and select **Add destination**. Give it a stable name, choose the channel, set its URL or secret reference, and select events.

The complete Manual orders workload below includes this subscription in its `workflow.notifications` field:

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "name": "Learn - order event notifications",
  "tasks": [
    {
      "name": "summarize",
      "sql": "WITH orders(id, category, region, amount) AS (\n  VALUES\n    (1, 'Books', 'North', 20),\n    (2, 'Games', 'South', 30),\n    (3, 'Games', 'North', 15),\n    (4, 'Books', 'North', 40),\n    (5, 'Garden', 'South', 25),\n    (6, 'Garden', 'North', 10)\n)\nSELECT COUNT(*) AS order_count, SUM(amount) AS sales\nFROM orders;",
      "settings": {
        "current_catalog": "default",
        "namespace": [
          "default"
        ],
        "time_zone": "UTC",
        "case_sensitive": false,
        "ansi_enabled": true
      }
    }
  ],
  "dependencies": [],
  "options": {
    "execution_target": "DuckDb"
  },
  "policy": "Manual",
  "workflow": {
    "data_windows": false,
    "notifications": [
      {
        "name": "orders_events",
        "channel": {
          "kind": "webhook",
          "url": "https://alerts.example.com/laminar/events",
          "secret": "orders_callback_token"
        },
        "events": [
          "run_succeeded",
          "run_failed",
          "sensor_timeout"
        ],
        "max_attempts": 5
      }
    ]
  }
}
```

Replace the endpoint and secret reference before saving. For HTTP webhooks, the secret supplies bearer authentication. A Slack channel uses `kind: "slack"`; its secret can hold the complete Slack webhook URL. The URL field must still contain a valid HTTP URL for definition validation.

A workload supports at most 16 uniquely named subscriptions. Each needs at least one event and 1–20 delivery attempts. Omitted `max_attempts` defaults to 5.

## 2. Choose events

| Event | Meaning |
| - | - |
| `run_started` | Run execution starts. |
| `run_succeeded` | Run completes successfully. |
| `run_failed` | Run ends in failure. |
| `run_cancelled` | Run cancellation completes. |
| `outcome_unknown` | A final execution outcome cannot be confirmed. |
| `task_retry` | A task retry is recorded. |
| `task_failed` | A task ends in failure. |
| `sensor_timeout` | A sensor reaches its deadline. |
| `backfill_completed` | A backfill completes. |
| `backfill_failed` | A backfill fails. |

The API event list is explicit. The editor exposes the main completion, task, sensor, and backfill events. Select only the events the receiver needs.

## 3. Run and check delivery

Start the workload, open its run, and select **Notification history**. Inspect the destination, event, delivery status, attempts, and any error. For a full event ID and delivery record, use GET `/api/v1/workloads/{workload_id}/runs/{run_id}/notifications`.

Check the event ID, subscription name, attempts, status, and last error. Delivery states are `pending`, `in_flight`, `delivered`, and `exhausted`. A successful run with an exhausted notification is still a successful run.

HTTP webhooks receive a JSON body with an `event` object. The request includes an `Idempotency-Key` header containing the event ID. Slack receives a text message identifying the event and workload/run or backfill.

## Handle duplicate and failed delivery

Delivery is at least once. A receiver may accept a message even when its acknowledgement is lost. Store the event ID and ignore duplicate delivery for that event and subscription as appropriate.

Successful HTTP responses confirm delivery. Transport failures, HTTP 429, and server errors can retry. Rejected requests such as other non-success statuses can end delivery without exhausting every possible attempt.

After correcting a destination problem, open **Notification history** and select **Retry delivery** for an exhausted delivery. The equivalent HTTP operation is:

```http theme={"theme":{"light":"github-light","dark":"github-dark"}}
POST /api/v1/workloads/{workload_id}/runs/{run_id}/notifications/retry
Content-Type: application/json
```

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "event_id": "replace-with-event-id-from-history",
  "subscription": "orders_events"
}
```

Follow notification history again. Retrying delivery does not rerun the workload or repeat its table writes.

## Finish

Remove practice destinations when you no longer need them. Keep receiver logs and event IDs when investigating duplicate delivery. Use [Inspect runs and attempts](https://docs.e6data.com/transformation/workloads/runs.md) for execution failures rather than treating notification delivery as execution status.


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