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

# Notifications

> Get workflow notifications programmatically

Notifications alert you when workflows complete, fail, or detect data changes. You can receive them via email, webhooks, or WebSockets. The SDK handles channel management automatically.

<Note>
  For event types and channel details, see [Notifications](/docs/notifications).
</Note>

## Prerequisites

* Kadoa account with API key
* SDK installed: `npm install @kadoa/node-sdk` or `uv add kadoa-sdk`

## Quick Start

<CodeGroup>
  ```typescript Node SDK theme={null}
  import { KadoaClient } from "@kadoa/node-sdk";

  const client = new KadoaClient({ apiKey: "YOUR_API_KEY" });

  await client.notification.setupForWorkflow({
    workflowId: "YOUR_WORKFLOW_ID",
    events: ["workflow_data_change"],
    channels: {
      WEBHOOK: {
        name: "my-webhook",
        webhookUrl: "https://your-server.com/webhook",
        httpMethod: "POST",
      },
    },
  });
  ```

  ```python Python SDK theme={null}
  from kadoa_sdk import KadoaClient, KadoaClientConfig
  from kadoa_sdk.notifications import SetupWorkflowNotificationSettingsRequest

  client = KadoaClient(KadoaClientConfig(api_key="YOUR_API_KEY"))

  client.notification.setup_for_workflow(
      SetupWorkflowNotificationSettingsRequest(
          workflow_id="YOUR_WORKFLOW_ID",
          events=["workflow_data_change"],
          channels={
              "WEBHOOK": {
                  "name": "my-webhook",
                  "webhookUrl": "https://your-server.com/webhook",
                  "httpMethod": "POST",
              }
          },
      )
  )
  ```

  ```text MCP Server theme={null}
  > "Set up a webhook notification on my 'Product Monitor' workflow that triggers on data changes, sending to https://your-server.com/webhook"
  ```
</CodeGroup>

<Info>
  The SDK reuses existing channels with the same name. Running setup multiple times won't create duplicates.
</Info>

## Channel Types

### Email

<CodeGroup>
  ```typescript Node SDK theme={null}
  // Use account email
  await client.notification.setupForWorkflow({
    workflowId: workflowId,
    events: ["workflow_finished", "workflow_failed"],
    channels: { EMAIL: true },
  });

  // Or specify recipients
  await client.notification.setupForWorkflow({
    workflowId: workflowId,
    events: ["workflow_finished"],
    channels: {
      EMAIL: {
        name: "team-notifications",
        recipients: ["team@example.com"],
      },
    },
  });
  ```

  ```python Python SDK theme={null}
  # Use account email
  client.notification.setup_for_workflow(
      SetupWorkflowNotificationSettingsRequest(
          workflow_id=workflow_id,
          events=["workflow_finished", "workflow_failed"],
          channels={"EMAIL": True},
      )
  )

  # Or specify recipients
  client.notification.setup_for_workflow(
      SetupWorkflowNotificationSettingsRequest(
          workflow_id=workflow_id,
          events=["workflow_finished"],
          channels={
              "EMAIL": {
                  "name": "team-notifications",
                  "recipients": ["team@example.com"],
              }
          },
      )
  )
  ```
</CodeGroup>

### Slack

<CodeGroup>
  ```typescript Node SDK theme={null}
  await client.notification.setupForWorkflow({
    workflowId: workflowId,
    events: ["workflow_failed"],
    channels: {
      SLACK: {
        name: "team-notifications",
        slackChannelId: "C1234567890",
        slackChannelName: "alerts",
        webhookUrl: "https://hooks.slack.com/services/YOUR/WEBHOOK",
      },
    },
  });
  ```

  ```python Python SDK theme={null}
  client.notification.setup_for_workflow(
      SetupWorkflowNotificationSettingsRequest(
          workflow_id=workflow_id,
          events=["workflow_failed"],
          channels={
              "SLACK": {
                  "name": "team-notifications",
                  "slackChannelId": "C1234567890",
                  "slackChannelName": "alerts",
                  "webhookUrl": "https://hooks.slack.com/services/YOUR/WEBHOOK",
              }
          },
      )
  )
  ```
</CodeGroup>

### Webhook

<CodeGroup>
  ```typescript Node SDK theme={null}
  await client.notification.setupForWorkflow({
    workflowId: workflowId,
    events: ["workflow_data_change", "workflow_finished"],
    channels: {
      WEBHOOK: {
        name: "api-integration",
        webhookUrl: "https://api.example.com/webhooks/kadoa",
        httpMethod: "POST",
      },
    },
  });
  ```

  ```python Python SDK theme={null}
  client.notification.setup_for_workflow(
      SetupWorkflowNotificationSettingsRequest(
          workflow_id=workflow_id,
          events=["workflow_finished"],
          channels={
              "WEBHOOK": {
                  "name": "api-integration",
                  "webhookUrl": "https://api.example.com/webhooks/kadoa",
                  "httpMethod": "POST",
              }
          },
      )
  )
  ```
</CodeGroup>

### WebSocket

Receive events in real-time

<Note>
  For reconnect, drain, and reliability semantics, see [WebSockets](/docs/integrations/websockets).
</Note>

<CodeGroup>
  ```typescript Node SDK theme={null}
  const client = new KadoaClient({ apiKey });
  const realtime = await client.connectRealtime();

  // Subscribe to all events
  realtime.onEvent((event) => {
    console.log("Event received:", event.eventType, event.message);
  });

  // Filter events by type
  realtime.onEvent((event) => {
    if (event.eventType === "workflow_finished") {
      console.log("Workflow completed:", event.message);
    }
  });

  // Handle errors
  realtime.onError((error) => {
    console.error("WebSocket error:", error);
  });

  realtime.close();
  ```

  ```python Python SDK theme={null}
  client = KadoaClient(KadoaClientConfig(api_key=api_key))
  realtime = await client.connect_realtime()

  # Subscribe to all events
  realtime.on_event(lambda event: print("Event received:", event["eventType"], event["message"]))

  # Filter events by type
  def handle_filtered(event):
      if event["eventType"] == "workflow_finished":
          print("Workflow completed:", event["message"])

  realtime.on_event(handle_filtered)

  # Handle errors
  realtime.on_error(lambda error: print("WebSocket error:", error))

  realtime.close()
  ```
</CodeGroup>

## Subscribe to All Events

```typescript theme={null}
await client.notification.setupForWorkflow({
  workflowId: workflowId,
  events: "all",
  channels: { EMAIL: true },
});
```

## Reusing Channels

Reference existing channels by ID

<CodeGroup>
  ```typescript Node SDK theme={null}
  // List channels
  const channels = await client.notification.channels.listChannels({});
  const webhookChannel = channels.find(c => c.name === "my-webhook");

  await client.notification.setupForWorkflow({
    workflowId: newWorkflowId,
    events: ["workflow_data_change"],
    channels: {
      WEBHOOK: { channelId: webhookChannel.id },
    },
  });
  ```

  ```python Python SDK theme={null}
  # List channels
  channels = client.notification.channels.list_channels()
  webhook_channel = next((c for c in channels if c.name == "my-webhook"), None)

  client.notification.setup_for_workflow(
      SetupWorkflowNotificationSettingsRequest(
          workflow_id=new_workflow_id,
          events=["workflow_data_change"],
          channels={
              "WEBHOOK": {"channelId": webhook_channel.id}
          },
      )
  )
  ```
</CodeGroup>

## Template-Managed Notifications

When a workflow is linked to a [template](/docs/templates) that includes notifications, the notification settings are managed through the template. Attempting to modify notifications on a template-linked workflow returns a `409` error. Unlink the workflow first, or update the template and apply the change.

## Setup Notifications via API

### Step 1: Create Notification Channels

First, create the channels you want to use for notifications. See [Email](/docs/integrations/email), [Webhooks](/docs/integrations/webhooks) and [WebSockets](/docs/integrations/websockets) for channel creation examples.

### Step 2: Subscribe to Events

Subscribe to events by sending a POST request to `/v5/notifications/settings`.

#### Workspace-Level Subscription

Apply notifications to all workflows:

<CodeGroup>
  ```javascript Request theme={null}
  // POST /v5/notifications/settings
  {
    "eventType": "workflow_finished",
    "eventConfiguration": {},
    "enabled": true,
    "channelIds": ["<channel-id>"]
  }
  ```

  ```json Response theme={null}
  {
    "data": {
      "settings": {
        "id": "settings-123",
        "eventType": "workflow_finished",
        "eventConfiguration": {},
        "enabled": true,
        "channelIds": ["<channel-id>"]
      }
    }
  }
  ```
</CodeGroup>

#### Workflow-Level Subscription

Apply notifications to a specific workflow:

<CodeGroup>
  ```javascript Request theme={null}
  // POST /v5/notifications/settings
  {
    "workflowId": "<YOUR_WORKFLOW_ID>",
    "eventType": "workflow_data_change",
    "eventConfiguration": {},
    "enabled": true,
    "channelIds": ["<channel-id>"]
  }
  ```

  ```json Response theme={null}
  {
    "data": {
      "settings": {
        "id": "settings-456",
        "workflowId": "<YOUR_WORKFLOW_ID>",
        "eventType": "workflow_data_change",
        "eventConfiguration": {},
        "enabled": true,
        "channelIds": ["<channel-id>"]
      }
    }
  }
  ```
</CodeGroup>

### Step 3: Update Existing Settings

To add more channels to existing settings, use a PUT request:

<CodeGroup>
  ```javascript Request theme={null}
  // PUT /v5/notifications/settings/<settings-id>
  {
    "channelIds": ["existing-channel-id", "new-channel-id"]
  }
  ```

  ```json Response theme={null}
  {
    "data": {
      "settings": {
        "id": "<settings-id>",
        "workflowId": "YOUR_WORKFLOW_ID",
        "eventType": "workflow_data_change",
        "eventConfiguration": {},
        "enabled": true,
        "channelIds": ["existing-channel-id", "new-channel-id"]
      }
    }
  }
  ```
</CodeGroup>

<Note>
  For payload formats, see [Email](/docs/integrations/email), [Webhooks](/docs/integrations/webhooks), and [WebSockets](/docs/integrations/websockets).
</Note>
