Incidents, delivered anywhere.

SolidUptime can POST a JSON payload to any HTTPS endpoint when alert events occur on your project. Wire it into Slack, Discord, PagerDuty, Linear, or your own handler.

Delivery

Method POST
Content-Type application/json
User-Agent SolidUptime-Webhook/1.0
Timeout 10 seconds per attempt
Retries Transient failures (network errors, 429, 5xx) are retried with exponential backoff — after 1 minute, then 5 minutes, then 15 minutes. After 3 failed attempts the job is marked permanently failed. 4xx responses (except 429) are treated as permanent failures and not retried.

Respond with a 2xx status quickly — do any heavy processing asynchronously.

Signature verification

When a signing secret is set on your webhook channel, every request includes an X-SolidUptime-Signature header. The value is the HMAC-SHA256 of the raw request body, hex-encoded. Verify it before processing the payload.

const crypto = require('crypto');

function isValidSignature(rawBody, secret, header) {
  const expected = crypto
    .createHmac('sha256', secret)
    .update(rawBody)
    .digest('hex');
  return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(header));
}
import hmac, hashlib

def is_valid_signature(raw_body: bytes, secret: str, header: str) -> bool:
    expected = hmac.new(secret.encode(), raw_body, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, header)

Always use a constant-time comparison (timingSafeEqual / hmac.compare_digest) to prevent timing attacks. Compute the signature over the raw request body bytes — do not parse or reformat the JSON first.

Payload structure

Every event shares a common envelope. The data object is specific to each event type.

Field Type Description
event string Event type identifier (see below)
project_id string (UUID) ID of the project that triggered the event
project_name string Display name of the project
incident_id integer ID of the related incident. Present only on incident events.
data object Event-specific payload (see each event below)

Event types

Event Trigger
incident.opened A new incident is detected — one or more checks have crossed the failure threshold
incident.escalated An additional check fails while an incident is already active
incident.resolved All checks have recovered and the grace period has elapsed
alert.tls_expiry_warning A monitored certificate will expire within 7 days
alert.test A test delivery triggered manually from the dashboard

incident.opened

Fired when a new incident starts — at least one check has crossed the failure threshold.

{
  "event": "incident.opened",
  "project_id": "e3b0c442-98fc-1c14-9afb-f4c8996fb924",
  "project_name": "My API",
  "incident_id": 42,
  "data": {
    "severity": 2,
    "started_at": "2026-03-16T10:00:00Z",
    "affected_checks": [
      { "name": "Homepage",   "url": "https://example.com" },
      { "name": "API health", "url": "https://api.example.com/health" }
    ]
  }
}
data field Type Description
severity integer Incident severity (see Severity levels)
started_at string (RFC 3339) When the incident began. Always UTC.
affected_checks array Checks that contributed to the incident at the time of opening
affected_checks[].name string Check display name
affected_checks[].url string Check target URL

incident.escalated

Fired when an additional check fails while an incident is already active. The affected_checks array reflects the full set of currently failing checks.

{
  "event": "incident.escalated",
  "project_id": "e3b0c442-98fc-1c14-9afb-f4c8996fb924",
  "project_name": "My API",
  "incident_id": 42,
  "data": {
    "severity": 3,
    "started_at": "2026-03-16T10:00:00Z",
    "affected_checks": [
      { "name": "Homepage",   "url": "https://example.com" },
      { "name": "API health", "url": "https://api.example.com/health" },
      { "name": "Checkout",   "url": "https://example.com/checkout" }
    ]
  }
}

Same data fields as incident.opened.

incident.resolved

Fired after all checks have recovered and the grace period has elapsed without a new failure.

{
  "event": "incident.resolved",
  "project_id": "e3b0c442-98fc-1c14-9afb-f4c8996fb924",
  "project_name": "My API",
  "incident_id": 42,
  "data": {
    "resolved_at": "2026-03-16T10:45:00Z",
    "duration_seconds": 2700.0
  }
}
data field Type Description
resolved_at string (RFC 3339) When the incident was marked resolved. Always UTC.
duration_seconds number Total incident duration in seconds

alert.tls_expiry_warning

Fired once per certificate when it is 7 days or fewer from expiry and the check is currently passing. Will not re-fire for the same certificate unless it is renewed and the expiry date changes.

{
  "event": "alert.tls_expiry_warning",
  "project_id": "e3b0c442-98fc-1c14-9afb-f4c8996fb924",
  "project_name": "My API",
  "data": {
    "check_name": "API health",
    "domain": "api.example.com",
    "days_left": 5,
    "tls_expires_at": "2026-03-21T00:00:00Z"
  }
}
data field Type Description
check_name string Display name of the check monitoring this certificate
domain string Hostname extracted from the check URL
days_left integer Days remaining until certificate expiry
tls_expires_at string (RFC 3339) Certificate expiry timestamp. Always UTC.

alert.test

Fired when a team member sends a test delivery from the alert channel settings. Use this to verify your endpoint is receiving events correctly before relying on it for real incidents.

{
  "event": "alert.test",
  "project_id": "e3b0c442-98fc-1c14-9afb-f4c8996fb924",
  "project_name": "My API",
  "data": {
    "triggered_by": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "triggered_at": "2026-03-16T10:00:00Z"
  }
}
data field Type Description
triggered_by string (UUID) ID of the user who triggered the test
triggered_at string (RFC 3339) When the test was triggered. Always UTC.

Severity levels

Severity is calculated from the ratio of currently failing checks to total active checks in the project. It only ever increases during an incident — it never drops while the incident is ongoing.

Value Label Threshold
1 Low < 5% of checks failing
2 Medium ≥ 5% of checks failing
3 High ≥ 20% of checks failing
4 Critical ≥ 50% of checks failing