---
title: Webhooks
description: Send real-time event data from Plunk to your own application using webhooks
icon: Webhook
---

Plunk can send real-time HTTP requests to your application when specific events occur, such as email bounces, spam complaints, or custom events. This is done by creating a [workflow](/concepts/workflows) that uses the **Webhook** step to forward event data to your own endpoint.

## How it works

Webhooks in Plunk are powered by the workflow system. The basic flow is:

1. An event occurs in Plunk (e.g. an email bounces, a contact subscribes, or a custom event is tracked)
2. A workflow is triggered by that event
3. The workflow executes a **Webhook** step, sending an HTTP request to your URL with relevant data

This means you can receive notifications for any event Plunk tracks, including both system events and your own custom events.

## Internal events

Plunk automatically tracks a set of internal events that you can use as workflow triggers. These events cannot be manually tracked via the API — they are generated by the system.

### Email events

| Event             | Description                                                                                              |
| ----------------- | -------------------------------------------------------------------------------------------------------- |
| `email.sent`      | An email was successfully sent                                                                           |
| `email.delivery`  | An email was delivered to the recipient                                                                  |
| `email.open`      | A contact opened an email for the first time                                                             |
| `email.click`     | A contact clicked a link in an email for the first time                                                  |
| `email.bounce`    | An email bounced (hard or soft bounce)                                                                   |
| `email.complaint` | A contact marked an email as spam                                                                        |
| `email.received`  | An email was received at your verified domain (requires [inbound email setup](/guides/receiving-emails)) |

### Contact events

| Event                  | Description                                             |
| ---------------------- | ------------------------------------------------------- |
| `contact.subscribed`   | A contact's subscription status changed to subscribed   |
| `contact.unsubscribed` | A contact's subscription status changed to unsubscribed |

### Segment events

| Event                  | Description                 |
| ---------------------- | --------------------------- |
| `segment.<name>.entry` | A contact entered a segment |
| `segment.<name>.exit`  | A contact exited a segment  |

<Callout title="Segment event names" variant="idea">
  Segment events use a slugified version of the segment name. For example, a segment called "VIP Users" would produce
  the events `segment.vip-users.entry` and `segment.vip-users.exit`.
</Callout>

## Setting up a webhook

<div className='fd-steps [&_h3]:fd-step'>

### Create the workflow

Navigate to the **Workflows** section in the dashboard and create a new workflow. Choose the event you want to listen for as the trigger. For example, to receive notifications when an email bounces, use `email.bounce` as the trigger event.

### Add a Webhook step

After the trigger, add a **Webhook** step and configure it:

- **URL**: The endpoint on your server that will receive the webhook (e.g. `https://api.example.com/webhooks/plunk`)
- **Method**: The HTTP method to use. Defaults to `POST`, which is recommended for most use cases.
- **Headers** (optional): Custom headers to include in the request, provided as JSON. This is useful for authentication.

```json
{
  "Authorization": "Bearer your-secret-token"
}
```

### Enable the workflow

Once configured, enable the workflow. It will start sending webhook requests whenever the trigger event occurs.

</div>

## Webhook payload

When using the default payload (no custom body configured), Plunk sends a JSON request with the following structure:

```json
{
  "contact": {
    "email": "user@example.com",
    "subscribed": true,
    "data": {
      "name": "John",
      "plan": "pro"
    }
  },
  "workflow": {
    "id": "wf_abc123",
    "name": "Bounce Notifications"
  },
  "execution": {
    "id": "exec_xyz789",
    "startedAt": "2025-01-15T10:30:00.000Z"
  },
  "event": {
    "subject": "Welcome to Plunk",
    "from": "hello@example.com",
    "bounceType": "Permanent"
  }
}
```

The `event` field contains the data associated with the event that triggered the workflow. The exact contents depend on the event type.

### Event data by type

The `event` field varies depending on which event triggered the workflow:

| Event             | Fields in `event`                                                        |
| ----------------- | ------------------------------------------------------------------------ |
| `email.sent`      | `subject`, `from`, `messageId`, `templateId`, `campaignId`, `sourceType` |
| `email.open`      | `subject`, `from`, `openedAt`, `isFirstOpen`                             |
| `email.click`     | `subject`, `from`, `clickedAt`, `clicks`, `isFirstClick`                 |
| `email.bounce`    | `subject`, `from`, `bounceType`, `bouncedAt`                             |
| `email.complaint` | `subject`, `from`, `complainedAt`                                        |
| Custom events     | Whatever data you passed when tracking the event                         |

## Common use cases

### Bounce and complaint monitoring

Create a workflow triggered by `email.bounce` or `email.complaint` to forward these events to your application. This allows you to keep your own database in sync with Plunk's contact statuses.

You can use additional workflow steps before the webhook to add logic:

- **Condition**: Only send the webhook for hard bounces by checking the `bounceType` field
- **Delay**: Add a short delay to batch-process related events
- **Update Contact**: Mark the contact with metadata before sending the webhook

### Syncing unsubscribes

Trigger a workflow on `contact.unsubscribed` to notify your application when a contact opts out. This is useful for keeping subscription status synchronized across multiple systems.

### Custom event forwarding

If you track custom events in Plunk (e.g. `user.signup`, `order.completed`), you can forward those same events to other services via webhooks. This turns Plunk into an event router — track once, distribute to multiple endpoints.

## Adding conditions and delays

Since webhooks are part of the workflow system, you can combine them with other step types for more advanced setups:

- Use a **Condition** step to only fire the webhook when certain criteria are met (e.g. only notify for contacts on a specific plan)
- Use a **Wait for Event** step to wait for a follow-up event before sending the webhook (e.g. wait to see if a bounced contact re-subscribes)
- Use a **Delay** step to add a time buffer before the webhook fires
