Webhook subscriptions

Status page - Webhook subscrption.png

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 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, which 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 payloads

Every request shares the same meta and page objects. The event_type field tells you which event was delivered, and the event-specific object that follows.

Incident event Maintenance event Component update event
{
  "event_type": "incident",
  "meta": {
    "unsubscribe": "https://status.example.com/unsubscribe-webhook/abc123",
    "documentation": "https://betterstack.com/docs/uptime/subscribing-to-status-updates/subscribing-with-webhooks/"
  },
  "page": {
    "id": 12345,
    "status_indicator": "downtime",
    "status_description": "Some services are down"
  },
  "incident": {
    "id": 98765,
    "name": "Database connection issues",
    "created_at": "2026-01-15T10:30:00Z",
    "updated_at": "2026-01-15T11:45:00Z",
    "shortlink": "https://status.example.com/98765/incidents",
    "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": "2026-01-15T11:45:00Z",
        "updated_at": "2026-01-15T11:45:00Z"
      },
      {
        "id": 11110,
        "status_report_id": 98765,
        "body": "We're investigating connection issues with the database.",
        "created_at": "2026-01-15T10:30:00Z",
        "updated_at": "2026-01-15T10:30:00Z"
      }
    ]
  }
}
{
  "event_type": "maintenance",
  "meta": {
    "unsubscribe": "https://status.example.com/unsubscribe-webhook/abc123",
    "documentation": "https://betterstack.com/docs/uptime/subscribing-to-status-updates/subscribing-with-webhooks/"
  },
  "page": {
    "id": 12345,
    "status_indicator": "maintenance",
    "status_description": "Ongoing maintenance"
  },
  "maintenance": {
    "id": 87654,
    "name": "Scheduled database upgrade",
    "created_at": "2026-01-14T09:00:00Z",
    "updated_at": "2026-01-15T02:00:00Z",
    "starts_at": "2026-01-15T02:00:00Z",
    "ends_at": "2026-01-15T04:00:00Z",
    "shortlink": "https://status.example.com/87654/incidents",
    "organization_id": 12345,
    "maintenance_updates": [
      {
        "id": 22222,
        "status_report_id": 87654,
        "body": "Database upgrade scheduled for tonight.",
        "created_at": "2026-01-14T09:00:00Z",
        "updated_at": "2026-01-14T09:00:00Z"
      }
    ]
  }
}
{
  "event_type": "component_update",
  "meta": {
    "unsubscribe": "https://status.example.com/unsubscribe-webhook/abc123",
    "documentation": "https://betterstack.com/docs/uptime/subscribing-to-status-updates/subscribing-with-webhooks/"
  },
  "page": {
    "id": 12345,
    "status_indicator": "degraded",
    "status_description": "Some services are degraded"
  },
  "component_update": {
    "id": "a1b2c3d4e5f60718293a4b5c",
    "created_at": "2026-01-15T12:00:00Z",
    "old_status": "operational",
    "new_status": "degraded",
    "component_id": 55555
  },
  "component": {
    "id": 55555,
    "name": "API Gateway",
    "status": "degraded",
    "created_at": "2025-11-02T08:15:00Z"
  }
}

Payload structure

Shared objects

Every payload includes meta and page.

Meta:

  • unsubscribe - Link that stops this webhook subscription
  • documentation - Link to this page

Page:

  • id - Numeric identifier of the status page
  • status_indicator - Overall status of the page, one of operational, degraded, downtime, or maintenance
  • status_description - Human-readable summary of status_indicator

The status_indicator and status_description values always pair up as follows:

status_indicator status_description
operational All services are online
degraded Some services are degraded
downtime Some services are down
maintenance Ongoing maintenance

Event types

The event_type field determines which event-specific object is present:

  • incident - New incident or an update to an existing incident.
    Payload carries an incident object.
  • maintenance - Scheduled maintenance window or an update to one.
    Payload carries a maintenance object.
  • component_update - Monitored component changed status.
    Payload carries component_update and component objects.

Incident and maintenance objects

Both objects share the same fields. Maintenance adds starts_at and ends_at, and names its updates array maintenance_updates.

  • id - Numeric identifier of the incident or maintenance
  • name - Title shown on the status page
  • created_at / updated_at - ISO 8601 timestamps
  • starts_at / ends_at - Scheduled window for maintenance only
  • shortlink - Public link to the incident on the status page
  • organization_id - Identifier of the status page the incident belongs to, matches page.id
  • incident_updates or maintenance_updates - Array of updates, newest first, each entry contains:
    • id - Numeric identifier of the update
    • status_report_id - Identifier of the parent incident or maintenance
    • body - Update message text
    • created_at / updated_at - ISO 8601 timestamps

Component updates and component objects

The component_update describes the change:

  • id - Unique identifier for this change event
  • created_at - ISO 8601 timestamp of the change
  • old_status - Previous status, set to resolved when the previous status wasn't tracked
  • new_status - Status the component changed to
  • component_id - Numeric identifier of the component, matches component.id

The component describes the component's current state:

  • id - Numeric identifier of the component
  • name - Public name of the component
  • status - Current status, matching new_status
  • created_at - ISO 8601 timestamp of when the component was created

Component statuses use the same values as page.status_indicator: operational, degraded, downtime, and maintenance.

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]
    Event type is either 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. Make sure 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 deactivated webhook:

  1. Fix the endpoint issue causing failures.
  2. Visit the status page and subscribe again with the same endpoint URL.
  3. Confirm the subscription via email.

Resubscribing with the same URL resets the failure count and requires a fresh email confirmation.

Best practices

  • Respond fast, process later. Return a 2xx response as soon as you receive the payload, then queue it for background processing. Heavy work before responding risks hitting the 30 second timeout.

  • Handle retries idempotently. A failed delivery may arrive more than once. Deduplicate on id fields so repeated deliveries don't create duplicate work.

  • Monitor failure emails. A deactivation email means deliveries stopped. Common causes are an unreachable endpoint, an expired SSL certificate, or a firewall blocking Better Stack.

  • Log requests. Record headers and bodies so you can debug when updates don't appear as expected.

Troubleshooting

Webhook not receiving requests

  1. Verify the subscription was confirmed via email.
  2. Check the endpoint URL is correct and reachable over HTTPS.
  3. Ensure the endpoint returns a 2xx status within 30 seconds.
  4. Confirm your firewall allows HTTPS traffic from Better Stack.
  5. Verify the SSL certificate is valid.

Requests timing out

  1. Move processing to a background queue.
  2. Return a 2xx response immediately after receiving the payload.
  3. Check network latency to your endpoint.

Need help?

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