# Webhook subscriptions

![Status page - Webhook subscrption.png](https://imagedelivery.net/xZXo0QFi-1_4Zimer-T0XQ/1e36eec3-c106-4fad-9dba-9736b6710c00/lg2x =2645x2346)

Receive automated HTTP POST requests whenever there's a status update on the services you're monitoring. Instead of constantly polling for changes, we'll push updates directly to your specified endpoint.

## Subscribe with webhooks

1. Visit the status page you want to follow.
2. Click **Get updates**.
3. Select **Webhook** as the subscription type.
4. Enter your endpoint URL (must start with `https://`).
5. Provide your email for confirmation and failure notifications.
6. Click **Subscribe**.
7. Check your email and click the confirmation link.

Your webhook starts receiving updates immediately after confirmation.

## Example payload

[code-tabs]
```json
[label Incident update]
{
  "event_type": "incident",
  "meta": {
    "unsubscribe": "https://status.example.com/unsubscribe/abc123",
    "documentation": "https://docs.betterstack.com/webhooks"
  },
  "page": {
    "id": "12345",
    "status_indicator": "downtime",
    "status_description": "Some services are down"
  },
  "incident": {
    "id": "98765",
    "name": "Database Connection Issues",
    "created_at": "2024-01-15T10:30:00Z",
    "updated_at": "2024-01-15T11:45:00Z",
    "shortlink": "https://status.example.com/incidents/98765",
    "organization_id": "12345",
    "incident_updates": [
      {
        "id": "11111",
        "status_report_id": "98765",
        "body": "We've identified the issue and are working on a fix",
        "created_at": "2024-01-15T11:45:00Z",
        "updated_at": "2024-01-15T11:45:00Z"
      },
      {
        "id": "11110",
        "status_report_id": "98765",
        "body": "We're investigating connection issues with the database",
        "created_at": "2024-01-15T10:30:00Z",
        "updated_at": "2024-01-15T10:30:00Z"
      }
    ]
  }
}
```
```json
[label Maintenance update]
{
  "event_type": "maintenance",
  "meta": {
    "unsubscribe": "https://status.example.com/unsubscribe/abc123",
    "documentation": "https://docs.betterstack.com/webhooks"
  },
  "page": {
    "id": "12345",
    "status_indicator": "maintenance",
    "status_description": "Ongoing maintenance"
  },
  "maintenance": {
    "id": "87654",
    "name": "Scheduled Database Upgrade",
    "created_at": "2024-01-14T09:00:00Z",
    "updated_at": "2024-01-15T02:00:00Z",
    "starts_at": "2024-01-15T02:00:00Z",
    "ends_at": "2024-01-15T04:00:00Z",
    "shortlink": "https://status.example.com/incidents/87654",
    "organization_id": "12345",
    "maintenance_updates": [
      {
        "id": "22222",
        "status_report_id": "87654",
        "body": "Database upgrade scheduled for tonight",
        "created_at": "2024-01-14T09:00:00Z",
        "updated_at": "2024-01-14T09:00:00Z"
      }
    ]
  }
}
```
```json
[label Component update]
{
  "event_type": "component_update",
  "meta": {
    "unsubscribe": "https://status.example.com/unsubscribe/abc123",
    "documentation": "https://docs.betterstack.com/webhooks"
  },
  "page": {
    "id": "12345",
    "status_indicator": "operational",
    "status_description": "All systems operational"
  },
  "component": {
    "id": "55555",
    "name": "API Gateway",
    "status": "operational",
    "previous_status": "degraded",
    "updated_at": "2024-01-15T12:00:00Z"
  }
}
```
[/code-tabs]

## HTTP request details

### Headers

Every webhook request includes these headers:

- `Content-Type: application/json`
- `User-Agent: BetterStack-StatusPage/1.0`
- `X-BetterUptime-Event: [event_type]` (incident, maintenance, or component_update)

### Request format

All webhooks use HTTP POST with JSON payloads. Requests are sent with:
- UTF-8 encoding
- JSON content type
- HTTPS only (plain HTTP is not supported)

### Timeouts

- Connection timeout: 10 seconds
- Request timeout: 30 seconds

Your endpoint must respond within 30 seconds or the request is considered failed.

### Expected response

We consider any 2xx HTTP status code as successful. Your endpoint should:
- Return 200 OK, 201 Created, or 204 No Content
- Respond within 30 seconds
- Not require authentication headers (use URL-based auth if needed)

### Redirects

Webhooks do not follow HTTP redirects. Ensure your endpoint URL returns a direct 2xx response.

## Retry policy

If your webhook fails, we'll automatically retry with exponential backoff:

- 1st retry: after 30 seconds
- 2nd retry: after 1 minute
- 3rd retry: after 2 minutes
- 4th retry: after 4 minutes
- 5th retry: after 8 minutes
- Continuing up to 10 retries

### After failed retries

After 10 failed attempts, we'll:

1. Deactivate the webhook subscription
2. Send an email notification to your contact email about the failure
3. Stop sending updates until you reactivate the subscription

### Reactivating after failure

To reactivate a failed webhook:

1. Fix the endpoint issue causing failures
2. Visit the status page
3. Create a new webhook subscription with the same or updated URL
4. Confirm the subscription via email

## Payload structure

### Event types

Webhooks send three types of events:

**incident** - New incidents and updates to existing incidents:
- New incident created
- Incident status changed
- New update posted to incident
- Incident resolved

**maintenance** - Scheduled maintenance windows:
- Maintenance window created
- Maintenance window updated
- Maintenance started
- Maintenance completed

**component_update** - Individual component status changes:
- Component status changed from operational to degraded
- Component status changed from degraded to downtime
- Component restored to operational

### Incident updates array

Incident payloads include an `incident_updates` array with all updates in reverse chronological order (newest first). Each update includes:

- `id` - Unique update identifier
- `status_report_id` - Parent incident ID
- `body` - Update message text
- `created_at` - When update was posted (ISO 8601)
- `updated_at` - When update was last modified (ISO 8601)

### Status indicators

The `status_indicator` field can have these values:

- `operational` - Everything is working normally
- `degraded` - Some services experiencing issues
- `downtime` - Major service disruption
- `maintenance` - Scheduled maintenance in progress

## Implementation best practices

### Respond quickly

Return a 2xx status as soon as you've received the payload. Don't perform heavy processing before responding:

**Good:**
```python
@app.route('/webhook', methods=['POST'])
def handle_webhook():
    payload = request.json
    # Queue for background processing
    queue.enqueue(process_webhook, payload)
    return '', 204
```

**Bad:**
```python
@app.route('/webhook', methods=['POST'])
def handle_webhook():
    payload = request.json
    # Don't do this - processing blocks response
    send_slack_message(payload)
    update_database(payload)
    notify_team(payload)
    return '', 200
```

### Process asynchronously

Queue webhook payloads for background processing. This ensures:

- Fast response times
- Reliable delivery acknowledgment
- Graceful handling of processing errors
- Ability to retry processing independently

### Monitor failures

Keep an eye on webhook failure notification emails. Common causes:

- Endpoint temporarily unavailable
- SSL certificate expired
- Firewall blocking requests
- Response timeout exceeded

Set up monitoring on your endpoint to detect issues before we disable the webhook.

### Log requests

Log incoming webhook requests for debugging:

- Request headers
- Payload body
- Your processing results
- Any errors encountered

This helps diagnose issues when updates don't appear as expected.

## Troubleshooting

### Webhook not receiving requests

1. Verify webhook was confirmed via email
2. Check endpoint URL is correct and accessible
3. Ensure endpoint returns 2xx for test requests
4. Check firewall allows HTTPS traffic from Better Stack
5. Verify SSL certificate is valid

### Requests timing out

Your endpoint must respond within 30 seconds:

1. Move processing to background queue
2. Return 204 immediately after receiving payload
3. Optimize database queries in endpoint
4. Check network latency to your endpoint

### Receiving failures but endpoint works

1. Check if endpoint URL changed
2. Verify SSL certificate hasn't expired
3. Test endpoint with example payloads
4. Review logs for errors
5. Ensure endpoint handles the payload structure

## Need help?

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