# WebHook Integration Tutorial
The WebHook feature in EMQX Edge enables the broker to automatically send HTTP POST requests to external services in response to specific MQTT events. These events include client connections, message publications, disconnections, and more. This mechanism makes it easy to integrate EMQX Edge with external systems such as logging services, analytics platforms, or custom dashboards, without writing custom plugins.

## How It Works

When a specified event occurs, EMQX Edge composes an HTTP POST request with structured JSON data and sends it to a user-defined endpoint (`url`). You can configure one or more event rules under the `webhook` section in the configuration file.

## Enable and Configure WebHook Integration

You can enable WebHook integration by adding the following snippet to your `nanomq.conf`. Refer to [WebHook Configuration](../config-description/webhook.md) for more detailed configuration item explanations.

```
webhook {
  url = "http://127.0.0.1:8888"                   # Destination endpoint for webhook requests
  headers.content-type = "application/json"       # Content-Type of the request
  body.encoding = plain                           # Payload encoding: plain, base64, or base62
  pool_size = 32                                  # Number of concurrent HTTP connections

  events = [
    {
      event = "on_message_publish"
      topic = "nmq/pub"
    }
    {
      event = "on_client_connack"
    }
    {
      event = "on_client_disconnected"
    }
  ]
}
```

**Key parameters:**

- `url`: HTTP endpoint to receive WebHook calls.
- `headers.content-type`: Content-Type header for the payload (JSON recommended).
- `body.encoding`: Encoding of the payload (e.g., `plain` or `base64`).
- `pool_size`: Number of concurrent HTTP worker threads.
- `events`: List of event triggers; `topic` filters can include wildcards (e.g., `nmq/#`).

## Event Rules

Webhook behavior is defined by specifying a set of rules, where each rule listens for a specific event (and optionally a topic). Each entry in the `events` array defines a WebHook rule. When an event occurs, EMQX Edge sends a structured HTTP POST request to a preconfigured URL.

### Event Rule Fields

| Field   | Type   | Description                                                  |
| ------- | ------ | ------------------------------------------------------------ |
| `event` | string | The event type that will trigger the WebHook. Supported values: `on_message_publish`, `on_client_connack`, `on_client_disconnected`. |
| `topic` | string | Optional. A topic filter that restricts triggering to specific MQTT topics (only applies to message-related events). |

## Supported Events

The following built-in MQTT events can trigger WebHook:

| Event Name               | Description                      | **Trigger timing**                                           |
| ------------------------ | -------------------------------- | ------------------------------------------------------------ |
| `on_client_connack`      | Client connection acknowledgment | Triggered when a client completes the MQTT connection handshake and the server is ready to send CONNACT packet. |
| `on_client_disconnected` | Client disconnects               | Triggered when a client disconnects from the broker.         |
| `on_message_publish`     | Message published                | Triggered when a message is published to a configured topic. |

### HTTP Request Format

When an event is triggered, EMQX Edge sends an HTTP POST request to the configured `url`. The request format is:

```bash
URL: <configured url>      # From the url field in the configuration file
Method: POST    # Fixed as POST method

Body: <JSON-formatted event data>    # Body is a JSON format string
```

The `body` for different events may differ. For example, a payload for the `on_client_connack` event might look like this:

```json
{"proto_ver":4,"keepalive":60,"conn_ack":"success","username":"wbhk_test","clientid":"wbhk_clientid","action":"client_connack"}
```

Each event type includes a specific payload schema:

**`on_client_connack`**

| Key       | Type    | Description                                                 |
| --------- | ------- | ----------------------------------------------------------- |
| action    | string  | Event name<br />Value: "client_connack", cannot be modified |
| clientid  | string  | Client ID                                                   |
| username  | string  | Client username (or `"undefined"` if absent)                |
| keepalive | integer | Heartbeat keepalive time applied by the client              |
| proto_ver | integer | MQTT protocol version （3 ｜ 4 ｜ 5）                       |
| conn_ack  | string  | "success" or reason for failure                             |

**`on_client_disconnected`**

| Key      | Type   | Description                                                  |
| -------- | ------ | ------------------------------------------------------------ |
| action   | string | Event name<br />Value: "client_disconnected", cannot be modified |
| clientid | string | Client ID                                                    |
| username | string | Client username (or `"undefined"` if absent)                 |
| reason   | string | Error reasons                                                |

**`on_message_publish`**

| Key            | Type    | Description                                                 |
| -------------- | ------- | ----------------------------------------------------------- |
| action         | string  | Event name<br/>Value: "message_publish", cannot be modified |
| from_client_id | string  | Publisher's client ID                                       |
| from_username  | string  | Publisher's username (or `"undefined"` if absent)           |
| topic          | string  | Topic name                                                  |
| qos            | enum    | QoS level (`0`, `1`, or `2`)                                |
| retain         | bool    | Whether it is a Retain message                              |
| payload        | string  | Message payload                                             |
| ts             | integer | Timestamp (second)                                          |

## Test the WebHook Integration

This section demonstrates how to verify that WebHook events are properly triggered in EMQX Edge.

### Start EMQX Edge and a Test HTTP Server

For testing, you can use a simple HTTP server that prints incoming requests and responds with `ok`.

Start EMQX Edge with your configuration:

```bash
$ emqx-edge start --conf path/to/nanomq.conf
```

::: tip

Ensure your HTTP server is running and listening on the URL specified in the `webhook.url` field of the configuration.

:::

### Trigger `on_client_connack` Event

Use the [MQTTX Client Tool](https://mqttx.app/) to connect to EMQX Edge. This triggers the `on_client_connack` event.

Sample connection setup in MQTTX:

![Alt text](../images/wbhk-connect.png)

Expected HTTP request received by the server:
```
header: content-type: [application/json]
Received: {"proto_ver":4,"keepalive":60,"conn_ack":"success","username":"wbhk_test","clientid":"wbhk_clientid","action":"client_connack"}
```

### Trigger `on_message_publish` Event

Next, publish a message to the topic `nmq/pub`:
![Alt text](../images/wbhk-pub.png)
Expected HTTP request:

```
header: content-type: [application/json]
Received: {"ts":1706703724960,"topic":"nmq/pub","retain":true,"qos":1,"action":"message_publish","from_username":"wbhk_test","from_client_id":"wbhk_clientid","payload":"Hello World!"}
```

::: tip

The `topic` field in your webhook event configuration supports MQTT wildcards. For example, setting `topic = "nmq/#"` will match all subtopics like `nmq/pub1` or `nmq/pub2`.

:::

### Trigger `on_client_disconnected` Event

Disconnect the client to trigger the `on_client_disconnected` event.

Expected HTTP request:

```
header: content-type: [application/json]
Received: {"reason":"normal","username":"wbhk_test","clientid":"wbhk_clientid","action":"client_disconnected"}
```
