API Reference
Webhook Events
HTTP headers
- Content-Type
application/jsonAll webhook payloads are JSON-encoded.
- X-Checkupstream-Signature
<64 lowercase hex characters>HMAC-SHA256 of the raw request body using your webhook secret, with no algorithm prefix. Included only when a secret is configured. Verify the signature before processing the event.
Verifying signatures
X-Checkupstream-Signature header before processing events. The value is an HMAC-SHA256 hash of the raw request body, hex-encoded with no algorithm prefix.import crypto from "node:crypto";
export function verifySignature(
body: string,
signature: string,
secret: string,
): boolean {
// Check the format before decoding untrusted header values.
if (!/^[0-9a-f]{64}$/i.test(signature)) return false;
const expected = crypto.createHmac("sha256", secret).update(body).digest();
return crypto.timingSafeEqual(Buffer.from(signature, "hex"), expected);
}Event payloads
incident.detected
Sent for qualifying incident alerts about a service your organization tracks. Your alert configuration determines which incidents trigger delivery.
predictedResolution summarises historical incident start and closure timestamps. Closure can mean a feed entry disappeared or tracking expired. These durations do not confirm vendor or application recovery, and they are not minutes remaining.
{
"event": "incident.detected",
"serviceId": "svc_stripe",
"serviceName": "Stripe",
"incidentId": "inc_abc123",
"title": "Elevated error rates on the Charges API",
"impact": "major_outage",
"affectedProjects": [
{
"id": "prj_checkout",
"name": "checkout-api",
"dependencies": [
{ "name": "stripe", "version": "14.12.0", "ecosystem": "npm" }
]
}
],
"enrichment": {
"aiSummary": "Card charges are failing for a subset of requests.",
"affectedCapabilities": ["Card payments"],
"survivingCapabilities": ["Subscription billing"],
"mitigations": ["Queue charge retries behind an idempotency key"],
"architectureInsight": null,
"affectedProjects": [
{
"id": "prj_checkout",
"name": "checkout-api",
"impactScore": 82,
"dependencies": [
{ "name": "stripe", "version": "14.12.0", "ecosystem": "npm" }
]
}
],
"affectedRegions": ["us-east-1"],
"customerImpact": "degraded",
"errorRateDelta": 0.47,
"latencyDelta": 820,
"recurrenceCount7d": 2,
"communityDetectedLeadMs": 240000,
"source": "ai-cached"
},
"predictedResolution": {
"likelyMinutes": 42,
"optimisticMinutes": 25,
"pessimisticMinutes": 90,
"sampleSize": 11,
"line": "Historical duration ~42 min, based on 11 recorded Stripe incidents in the last 180 days (range 25 to 90 min). This is not a recovery forecast.",
"compact": "~42 min historical duration (based on 11 recorded incidents; range 25 to 90 min)"
},
"timestamp": "2026-04-06T14:32:00Z"
}incident.updated
Sent after a status or severity change to the original webhook URL, while its channel is enabled and the alert remains unmuted. Read impact for the current severity and updateBody for the vendor's update.
{
"event": "incident.updated",
"kind": "incident_updated",
"serviceId": "svc_stripe",
"serviceName": "Stripe",
"incidentId": "inc_abc123",
"title": "Elevated error rates on the Charges API",
"status": "monitoring",
"impact": "degraded",
"updateBody": "We are monitoring the results of a fix.",
"timestamp": "2026-04-06T15:02:00Z"
}incident.resolved
Sent when a tracked record closes, to the original webhook URL while its channel is enabled and the alert remains unmuted. Read resolution before interpreting the event as vendor recovery.
- vendor_declared
- The vendor explicitly reported its incident resolved. Application recovery still needs your own evidence.
- absent_from_feed
- The incident disappeared from the vendor feed. No vendor resolution was recorded.
- max_age_timeout
- The record reached CheckUpstream's 30-day tracking limit. Vendor recovery is unconfirmed.
- unspecified
- The record closed without a recognized reason. Vendor recovery is unconfirmed.
The duration field is a human-readable interval between the record’s start and closure timestamps, such as 42m. It is not measured application downtime.
{
"event": "incident.resolved",
"kind": "incident_resolved",
"serviceId": "svc_stripe",
"serviceName": "Stripe",
"incidentId": "inc_abc123",
"title": "Elevated error rates on the Charges API",
"resolution": "absent_from_feed",
"duration": "42m",
"timestamp": "2026-04-06T15:14:00Z"
}alert.test
Sent when you press "Send test" on a webhook channel in Settings → Alerts. If a secret is configured, the test uses it to sign the request. Use this event to check your receiver before an incident.
{
"event": "alert.test",
"service": "Stripe",
"title": "Test alert from CheckUpstream",
"timestamp": "2026-04-06T14:32:00Z"
}Ready to receive events
Add your endpoint and secret, then use Send test to check signature handling and delivery.