Webhook subscriptions

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.

Status page subscriptions - Webhook.png

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

Incident update Maintenance update Component 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"
      }
    ]
  }
}
{
  "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"
      }
    ]
  }
}
{
  "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"
  }
}

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! 🙏