# Outgoing webhooks

Integrate Better Stack with your own services by **receiving an HTTP request when errors change or a new release is detected**.

## Setting up a webhook

1. Navigate to **Errors** → [Outgoing webhooks](https://errors.betterstack.com/team/0/integrations/webhooks ";_blank")
2. Find **Error webhook** or **Release webhook** and click **Add**.
3. Enter the **Webhook URL** we should send requests to.
4. For error webhooks, select which events should fire the webhook.
5. Click **Create webhook**.

Use **Send a test webhook** to verify your endpoint receives the request.

## Webhook events

**Error webhook** sends a request when the selected error lifecycle events happen:

- **New error**: an error is seen for the first time.
- **Threshold**: an error reaches its notification threshold.
- **Spike**: an error suddenly spikes.
- **Reoccurred**: a resolved or ignored error comes back.
- **Resolved**, **Ignored**, and **Unresolved**: the error state changes.

**Release webhook** sends a request when a new release is detected.

## Webhook request

Webhooks are sent as HTTP POST requests with a JSON body:

```json
[label Example error webhook request body]
{
  "data": {
    "id": "a1b2c3d4e5",
    "type": "error",
    "attributes": {
      "event": "new_error",
      "application_id": 4821,
      "application_name": "Backend API",
      "team_id": 12345,
      "error_url": "https://errors.betterstack.com/team/12345/errors/a1b2c3d4e5?s=4821",
      "error_type": "ActiveRecord::RecordNotFound",
      "error_message": "Couldn't find User with 'id'=999",
      "call_site_function": "UsersController#show",
      "call_site_file": "app/controllers/users_controller.rb",
      "first_seen": "2026-07-02T09:14:03Z",
      "last_seen": "2026-07-02T09:14:03Z",
      "environment": "production",
      "notify_threshold": null,
      "previous_state": null
    }
  }
}
```

```json
[label Example release webhook request body]
{
  "data": {
    "id": "5567",
    "type": "release",
    "attributes": {
      "event": "new_release",
      "application_id": 4821,
      "application_name": "Backend API",
      "team_id": 12345,
      "release_ref": "v1.2.3",
      "release_url": "https://errors.betterstack.com/team/12345/releases/5567",
      "first_seen_at": "2026-07-02T09:00:00Z",
      "last_seen_at": "2026-07-02T09:14:00Z",
      "environment": "production"
    }
  }
}
```

For a `threshold` event, `notify_threshold` contains the configured threshold. For a `reoccurred` event, `previous_state` is `resolved` or `ignored`.

Requests time out after 25 seconds and are retried up to 3 times. Review recent deliveries and responses in the webhook's logs when editing the webhook.

## Customizing the request

Open **Advanced settings** when creating or editing a webhook to customize the request:

- **HTTP method**: use HEAD, GET, POST, PUT, PATCH, OPTIONS, or DELETE.
- **Headers**: add custom header names and values.
- **Basic HTTP authentication**: username and password, stored in an encrypted form.
- **Request body template**: write your own body using variables like `$ERROR_ID`, `$EVENT`, `$APPLICATION_NAME`, or `$ERROR_URL`. Available variables are listed under the template field.

[info]
#### Want to verify a request comes from Better Stack?

Webhook requests are not signed. Set up **Basic HTTP authentication** or add a custom header with a secret value and check it on your server.
[/info]

## Need help?

Please let us know at hello@betterstack.com.  
We're happy to help! 🙏
