Documentation

Downtime.so

Developer-first incident communication and status page infrastructure for indie hackers and small teams. Get a public status page, real-time incident timeline, and subscriber notifications up and running in minutes.

Public Status Page

Live status page at your URL

Incident Management

Timeline-driven incident updates

Email & SMS Alerts

Subscriber notifications on events

Core concepts

ConceptDescription
OrganizationYour account and its configuration. Every registered user belongs to one organization.
ServiceA system or component you monitor (e.g. "API", "Web App", "Database"). Services have a status and can have incidents.
IncidentA service disruption event. Has a title, impact level, and a chronological timeline of updates.
UpdateA timestamped message posted to an incident timeline as you investigate and resolve the issue.
SubscriberA person who opted in to receive email or SMS notifications when incidents occur on a service.
Status PageThe public-facing page at /status/{orgSlug} showing all services and active incidents.

Getting Started#

You can be fully operational — with a live status page and your first service — in under five minutes.

1. Create an account

Navigate to /register and fill in your name, organization name, email address, and a password of at least 8 characters. Your organization name becomes your URL slug (e.g. acme-corp/status/acme-corp).

2. Add a service

From the dashboard, go to ServicesAdd Service. Give it a name (e.g. "API", "Website", "Database") and an optional description. New services start as OPERATIONAL.

3. Share your status page

Your status page is immediately live at /status/{orgSlug}. Find the full URL in Settings → Organization → Public Status Page. Share this link with your users so they can see live status and subscribe to notifications.

4. Create your first incident

When a service has an issue, go to Incidents → Create Incident. Select the affected service, set the impact level, and write an initial message describing what is happening. The service status updates automatically and all subscribers receive a notification.

Tip: You can also create incidents programmatically via the REST API or have them created automatically by webhook integrations (UptimeRobot, Datadog).

Services#

Services represent the components of your infrastructure that you want to surface on your status page. Each service has an independent status that you can update manually, through the API, or automatically via webhooks and incident lifecycle events.

Service statuses

StatusLabelMeaning
OPERATIONALOperationalService is fully functioning normally
DEGRADEDDegradedReduced performance but service is available
PARTIAL_OUTAGEPartial OutageSome users or features are affected
MAJOR_OUTAGEMajor OutageService is down or completely unavailable
MAINTENANCEMaintenancePlanned maintenance window is in progress

Automatic status transitions

When you create an incident, the affected service status is automatically set based on impact:

  • MINOR impact → service becomes DEGRADED
  • MAJOR impact → service becomes PARTIAL_OUTAGE
  • CRITICAL impact → service becomes MAJOR_OUTAGE

When the incident is resolved, the service automatically reverts to OPERATIONAL (provided no other active incidents remain on that service).

Note: Deleting a service also removes all its incidents, incident updates, and subscribers.

Incidents#

An incident is the primary communication unit in Downtime.so. Every incident has a title, impact level, an affected service, and a timeline of updates that are visible on the public status page in real time.

Impact levels

ImpactSeverityTypical use
MINORMinorSlowness or minor degradation, most users unaffected
MAJORMajorSignificant impact, large portion of users affected
CRITICALCriticalComplete outage or major data integrity issue

Incident lifecycle

Incidents progress through four statuses as your team investigates and resolves the issue:

INVESTIGATINGInitial state when created
IDENTIFIEDRoot cause found
MONITORINGFix deployed, watching
RESOLVEDFully resolved

Posting updates

From the incident detail page, use the Post Update form to add a new timeline entry. Each update includes a status (to advance the incident through its lifecycle) and a message for subscribers and the public status page. Every update triggers a notification to all subscribers of the affected service.

Resolving an incident

Click Resolve Incident on the incident detail page. This posts a final update with status RESOLVED, sets resolvedAt on the incident, and — if no other active incidents remain — restores the service to OPERATIONAL. Resolved incidents are moved to a separate "Resolved" section in the incidents list.

Subscribers & Notifications#

Subscribers are people who have opted in to receive incident notifications for one or more of your services. They can provide an email address, a phone number (for SMS), or both.

How subscribers sign up

The public status page (/status/{orgSlug}) has a Get Notified form at the bottom. Visitors enter their email or phone number and select a service. Subscriptions are per-service — a subscriber who monitors "API" will only receive notifications about incidents on that service.

Notification triggers

Notifications are sent to all subscribers of a service when:

  • A new incident is created on the service
  • A new update is posted to an active incident on the service

Email notifications

Emails are sent via Resend from status@downtime.so. Each email contains the incident title, current status, the latest update message, and an unsubscribe link.

SMS notifications

SMS messages are sent via Twilio. Messages include the service name, incident title, and a truncated version of the latest update (up to 100 characters). Phone numbers must be in E.164 format (e.g. +14155550123).

Managing subscribers

The Subscribers page in the dashboard shows all subscribers across all services. You can filter by service and export the full list as a CSV file.

Public Status Page#

Every organization gets a public status page at:

url
https://downtime.so/status/{orgSlug}

The page is publicly accessible — no login required. It shows:

  • An overall status banner (derived from the worst service status)
  • Individual status badges for every service
  • Active incidents with their full update timelines
  • A subscribe form for email and SMS notifications

Real-time updates

The status page uses Server-Sent Events (SSE) to push updates instantly. When a service status changes or a new incident update is posted, visitors see the change without refreshing. A live indicator in the top-right corner of the page shows the connection state.

Overall status calculation

The top-level banner shows the worst status across all services, evaluated in this priority order:

  1. MAJOR_OUTAGE — if any service is in major outage
  2. PARTIAL_OUTAGE — if any service has a partial outage
  3. DEGRADED — if any service is degraded
  4. MAINTENANCE — if any service is in maintenance
  5. OPERATIONAL — all systems are working normally
Tip: Find your full status page URL in the dashboard under Settings → Organization → Public Status Page. Copy it and add it to your app's footer, error pages, or support documentation.

API Reference#

Downtime.so exposes a REST API for programmatic access to all resources. All endpoints accept and return JSON. The base URL for all API calls is your server URL (set as NEXT_PUBLIC_API_URL in the frontend).

Authentication#

Two authentication methods are supported depending on the endpoint:

JWT Bearer token (dashboard endpoints)

Obtained by calling POST /api/auth/login or POST /api/auth/register. Access tokens expire after 15 minutes; use the refresh token to obtain a new one via POST /api/auth/refresh.

http
Authorization: Bearer <access_token>

API Key (machine-to-machine)

Your organization's API key is shown in Settings → API Access. Pass it as a request header. API keys are rate-limited to 50 requests per minute using a sliding window.

http
x-api-key: <your_api_key>

Services#

GET
/api/v1/services

List all services for your organization (JWT)

POST
/api/v1/services

Create a new service (JWT)

GET
/api/v1/services/:id

Get a service with its recent incidents (JWT)

PATCH
/api/v1/services/:id

Update service name, description, or status (JWT)

DELETE
/api/v1/services/:id

Delete a service and all related data (JWT)

bash
# Create a service
curl -X POST https://your-api.com/api/v1/services \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{"name": "API", "description": "Main REST API"}'

# Update service status
curl -X PATCH https://your-api.com/api/v1/services/<id> \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{"status": "DEGRADED"}'

Incidents#

GET
/api/v1/incidents

List incidents for your org (paginated, filterable by status) (JWT)

POST
/api/v1/incidents

Create incident from the dashboard (JWT)

POST
/api/v1/incidents/api

Create incident programmatically (machine-to-machine) (API Key)

GET
/api/v1/incidents/:id

Get incident with full update timeline (JWT)

PATCH
/api/v1/incidents/:id

Update incident title, status, or impact (JWT)

POST
/api/v1/incidents/:id/updates

Post a new update to the incident timeline (JWT)

bash
# Create an incident via API key
curl -X POST https://your-api.com/api/v1/incidents/api \
  -H "x-api-key: <your_api_key>" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Elevated API error rates",
    "impact": "MAJOR",
    "serviceId": "<service_id>",
    "initialMessage": "We are investigating elevated error rates on the API."
  }'

# Post a timeline update
curl -X POST https://your-api.com/api/v1/incidents/<id>/updates \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "message": "Root cause identified. Deploying a fix now.",
    "status": "IDENTIFIED"
  }'

Subscribers#

GET
/api/v1/subscribers

List subscribers (filter by serviceId, paginated) (JWT)

POST
/api/v1/subscribers

Subscribe to a service (used by the status page) (Public)

DELETE
/api/v1/subscribers/:id?token=<token>

Unsubscribe via one-click link in notification emails (Token)

bash
# Subscribe to a service (public endpoint, no auth needed)
curl -X POST https://your-api.com/api/v1/subscribers \
  -H "Content-Type: application/json" \
  -d '{
    "email": "user@example.com",
    "serviceId": "<service_id>"
  }'

# Subscribe via SMS
curl -X POST https://your-api.com/api/v1/subscribers \
  -H "Content-Type: application/json" \
  -d '{
    "phone": "+14155550123",
    "serviceId": "<service_id>"
  }'

Webhook Integrations#

Webhooks let external monitoring tools automatically update your service status and create incidents without manual intervention. Downtime.so supports three webhook endpoints.

UptimeRobot

Configure a webhook alert contact in UptimeRobot. When a monitor goes down, an incident is automatically created. When it recovers, the incident is auto-resolved and the service returns to operational.

url
POST /api/webhooks/uptimerobot?serviceId=<service_id>

In UptimeRobot: My Settings → Alert Contacts → Add Alert Contact → Webhook. Set the URL to the endpoint above and include your service ID as a query parameter.

Datadog

Connect Datadog alerts to auto-create and resolve incidents based on alert state changes (Alert, Warn, Resolved).

url
POST /api/webhooks/datadog?serviceId=<service_id>

In Datadog: Integrations → Webhooks → New Webhook. Set the URL and optionally include a serviceId in the payload body.

Generic webhook

Use the generic webhook endpoint to update service status from any tool that can send an HTTP request. This endpoint requires API key authentication.

bash
curl -X POST https://your-api.com/api/webhooks/generic \
  -H "x-api-key: <your_api_key>" \
  -H "Content-Type: application/json" \
  -d '{
    "serviceId": "<service_id>",
    "status": "MAJOR_OUTAGE",
    "incidentTitle": "Database connection failures",
    "message": "Primary database is unreachable."
  }'
FieldTypeRequiredDescription
serviceIdstringRequiredThe ID of the service to update
statusenumRequiredOne of the five service status values
messagestringOptionalInitial incident message (creates an incident if provided with a non-operational status)
incidentTitlestringOptionalTitle for the auto-created incident (defaults to "{service} incident")

React Embed#

The <DowntimeBanner /> component lets you surface active incidents directly inside your application. It renders nothing when all systems are operational and shows a banner when there is an active incident.

Installation

bash
npm install @downtime/react

Usage

tsx
import { DowntimeBanner } from '@downtime/react';

export default function App() {
  return (
    <div>
      <DowntimeBanner
        orgSlug="your-org-slug"
        apiUrl="https://your-api.downtime.so"
        statusPageUrl="https://downtime.so/status/your-org-slug"
      />
      {/* rest of your application */}
    </div>
  );
}
PropTypeDescription
orgSlugstringYour organization slug (from Settings)
apiUrlstringBase URL of your Downtime.so API server
statusPageUrlstringLink shown in the banner pointing to your full status page
Note: The embed component connects to the SSE endpoint and updates in real-time without polling. It will show an incident banner as soon as a new incident is created, even if the user has not refreshed the page.
© 2025 Downtime.so