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

# Webhooks

> Receive real-time notifications for important events in your Setter AI integration

## Overview

Setter AI sends webhook notifications to your server when important events occur, allowing you to build real-time integrations and automate workflows.

## Setting Your Webhook URL

Configure your webhook URL in the Setter AI dashboard:

1. Navigate to **Settings > General**
2. Enter your webhook endpoint URL in the "Webhook URL" field
3. Save your settings

Alternatively, you can configure it via API:

```bash theme={null}
PUT /api/v1/organizations/current/settings
Content-Type: application/json
Authorization: Bearer YOUR_API_KEY

{
  "webhookUrl": "https://api.example.com/webhook"
}
```

<Note>
  Your webhook endpoint must accept POST requests with `Content-Type: application/json`.
</Note>

## Webhook Events

### Appointment Booked

Triggered when a contact successfully books an appointment through any connected calendar integration.

**Event Type:** `appointment_booked`

#### Payload Example

```json theme={null}
{
  "type": "appointment_booked",
  "timestamp": "2025-12-04T10:30:00.000Z",
  "startTime": "2025-12-05T14:00:00.000Z",
  "startTimeInTz": "2025-12-05T09:00:00-05:00",
  "endTime": "2025-12-05T15:00:00.000Z",
  "timeZone": "America/New_York",
  "contactEmail": "user@example.com",
  "contactWhatsappId": "1234567890",
  "contactPhoneNumber": "+1234567890",
  "contactFullName": "John Doe",
  "contactFirstName": "John",
  "contactLastName": "Doe",
  "contactMetadata": {},
  "concatenatedConversation": "Full conversation history...",
  "botId": 123,
  "botIntegrationId": 456
}
```

### Conversation Inactive

Triggered 23 hours after the last user message in a conversation.

**Event Type:** `conversation_inactive`

#### Payload Example

```json theme={null}
{
  "type": "conversation_inactive",
  "timestamp": "2025-12-04T10:30:00.000Z",
  "lastUserMessageSentAt": "2025-12-03T11:30:00.000Z",
  "inactiveForDuration": "PT23H",
  "conversationStatus": ["replied"],
  "contactEmail": "user@example.com",
  "contactWhatsappId": "1234567890",
  "contactPhoneNumber": "+1234567890",
  "contactFullName": "John Doe",
  "contactFirstName": "John",
  "contactLastName": "Doe",
  "contactMetadata": {},
  "concatenatedConversation": "Full conversation history...",
  "botId": 123,
  "botIntegrationId": 456
}
```

### Message Delivery Failed

Triggered when a WhatsApp message fails to deliver. Use this to implement fallback workflows — for example, triggering an SMS via Zapier when a WhatsApp message can't be delivered.

**Event Type:** `message_delivery_failed`

#### Payload Example

```json theme={null}
{
  "type": "message_delivery_failed",
  "timestamp": "2025-12-04T10:30:00.000Z",
  "platformResourceId": "wamid.HBgLNDQ3...",
  "errorCode": 131026,
  "errorTitle": "Message undeliverable",
  "errorMessage": "Message failed to send because there were one or more errors related to your phone number.",
  "errorDetails": "The message could not be delivered.",
  "contactWhatsappId": "447911123456",
  "contactPhoneNumber": "+447911123456",
  "contactFullName": "John Doe",
  "contactFirstName": "John",
  "contactLastName": "Doe",
  "contactEmail": "john@example.com",
  "contactMetadata": {},
  "botIntegrationId": 456
}
```

#### Use case: SMS fallback via Zapier

If a WhatsApp message fails to deliver, you can use this webhook to trigger an SMS to the same contact:

1. Create a Zap with **Webhook by Zapier** as the trigger (Catch Hook)
2. Set your Zapier webhook URL as the **Webhook URL** in your Setter AI settings
3. Filter on `type === "message_delivery_failed"`
4. Use `contactPhoneNumber` to send an SMS via Twilio or another SMS provider

## Payload Fields

### Common Fields

| Field                | Type           | Description                                                                                                                                                                                                                                                                                                           |
| -------------------- | -------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `type`               | string         | Event type identifier (`appointment_booked`, `conversation_inactive`, or `message_delivery_failed`)                                                                                                                                                                                                                   |
| `timestamp`          | ISO 8601       | When the event occurred (UTC)                                                                                                                                                                                                                                                                                         |
| `contactEmail`       | string \| null | Contact's email address                                                                                                                                                                                                                                                                                               |
| `contactWhatsappId`  | string \| null | WhatsApp user ID                                                                                                                                                                                                                                                                                                      |
| `contactPhoneNumber` | string \| null | Contact's phone number                                                                                                                                                                                                                                                                                                |
| `contactFullName`    | string \| null | Contact's full name                                                                                                                                                                                                                                                                                                   |
| `contactFirstName`   | string \| null | Contact's first name                                                                                                                                                                                                                                                                                                  |
| `contactLastName`    | string \| null | Contact's last name                                                                                                                                                                                                                                                                                                   |
| `contactMetadata`    | object \| null | Custom metadata associated with the contact                                                                                                                                                                                                                                                                           |
| `botId`              | number \| null | Bot identifier (shown in the dashboard URL, e.g. `…/bots/700/…`)                                                                                                                                                                                                                                                      |
| `botIntegrationId`   | number         | Bot Integration ID — identifies the specific channel (WhatsApp or SMS integration) the event belongs to. Different from `botId`; found in the bot's Integrations settings. Use this value when calling the [Send Message](/setter-ai/api-reference) and [Conversation History](/setter-ai/conversation-history) APIs. |

### Appointment-Specific Fields

| Field           | Type     | Description                                          |
| --------------- | -------- | ---------------------------------------------------- |
| `startTime`     | ISO 8601 | Appointment start time (UTC)                         |
| `startTimeInTz` | ISO 8601 | Appointment start time in the invitee's timezone     |
| `endTime`       | ISO 8601 | Appointment end time (UTC)                           |
| `timeZone`      | string   | IANA timezone identifier (e.g., "America/New\_York") |

### Conversation Inactive Fields

| Field                      | Type              | Description                                                                   |
| -------------------------- | ----------------- | ----------------------------------------------------------------------------- |
| `lastUserMessageSentAt`    | ISO 8601          | Timestamp of the last user message                                            |
| `inactiveForDuration`      | ISO 8601 Duration | Duration of inactivity (e.g., "PT23H" = 23 hours)                             |
| `conversationStatus`       | string\[]         | Array of conversation status tags (e.g., \["appointment\_booked", "replied"]) |
| `concatenatedConversation` | string \| null    | Complete conversation history                                                 |

### Message Delivery Failed Fields

| Field                | Type           | Description                                                                                                               |
| -------------------- | -------------- | ------------------------------------------------------------------------------------------------------------------------- |
| `platformResourceId` | string         | The WhatsApp message ID (wamid) that failed to deliver                                                                    |
| `errorCode`          | number \| null | WhatsApp error code (see [Meta error codes](https://developers.facebook.com/docs/whatsapp/cloud-api/support/error-codes)) |
| `errorTitle`         | string \| null | Short error title                                                                                                         |
| `errorMessage`       | string \| null | Detailed error message                                                                                                    |
| `errorDetails`       | string \| null | Additional error context                                                                                                  |

## Best Practices

<Tip>
  **Implement Idempotency**: Your webhook endpoint should handle duplicate events gracefully. Use the `timestamp` and event-specific fields to deduplicate requests.
</Tip>

* **Respond Quickly**: Return a 2xx status code within 5 seconds to acknowledge receipt
* **Process Asynchronously**: Queue webhook processing for longer operations
* **Secure Your Endpoint**: Use HTTPS and validate webhook signatures (if implemented)
* **Handle Failures**: Implement retry logic with exponential backoff on your side
