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
| Concept | Description |
|---|---|
| Organization | Your account and its configuration. Every registered user belongs to one organization. |
| Service | A system or component you monitor (e.g. "API", "Web App", "Database"). Services have a status and can have incidents. |
| Incident | A service disruption event. Has a title, impact level, and a chronological timeline of updates. |
| Update | A timestamped message posted to an incident timeline as you investigate and resolve the issue. |
| Subscriber | A person who opted in to receive email or SMS notifications when incidents occur on a service. |
| Status Page | The 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 Services → Add 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.
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
| Status | Label | Meaning |
|---|---|---|
| OPERATIONAL | Operational | Service is fully functioning normally |
| DEGRADED | Degraded | Reduced performance but service is available |
| PARTIAL_OUTAGE | Partial Outage | Some users or features are affected |
| MAJOR_OUTAGE | Major Outage | Service is down or completely unavailable |
| MAINTENANCE | Maintenance | Planned 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).
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
| Impact | Severity | Typical use |
|---|---|---|
| MINOR | Minor | Slowness or minor degradation, most users unaffected |
| MAJOR | Major | Significant impact, large portion of users affected |
| CRITICAL | Critical | Complete outage or major data integrity issue |
Incident lifecycle
Incidents progress through four statuses as your team investigates and resolves the issue:
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:
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:
- MAJOR_OUTAGE — if any service is in major outage
- PARTIAL_OUTAGE — if any service has a partial outage
- DEGRADED — if any service is degraded
- MAINTENANCE — if any service is in maintenance
- OPERATIONAL — all systems are working normally
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.
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.
x-api-key: <your_api_key>Services#
/api/v1/servicesList all services for your organization (JWT)
/api/v1/servicesCreate a new service (JWT)
/api/v1/services/:idGet a service with its recent incidents (JWT)
/api/v1/services/:idUpdate service name, description, or status (JWT)
/api/v1/services/:idDelete a service and all related data (JWT)
# 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#
/api/v1/incidentsList incidents for your org (paginated, filterable by status) (JWT)
/api/v1/incidentsCreate incident from the dashboard (JWT)
/api/v1/incidents/apiCreate incident programmatically (machine-to-machine) (API Key)
/api/v1/incidents/:idGet incident with full update timeline (JWT)
/api/v1/incidents/:idUpdate incident title, status, or impact (JWT)
/api/v1/incidents/:id/updatesPost a new update to the incident timeline (JWT)
# 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#
/api/v1/subscribersList subscribers (filter by serviceId, paginated) (JWT)
/api/v1/subscribersSubscribe to a service (used by the status page) (Public)
/api/v1/subscribers/:id?token=<token>Unsubscribe via one-click link in notification emails (Token)
# 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.
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).
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.
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."
}'| Field | Type | Required | Description |
|---|---|---|---|
| serviceId | string | Required | The ID of the service to update |
| status | enum | Required | One of the five service status values |
| message | string | Optional | Initial incident message (creates an incident if provided with a non-operational status) |
| incidentTitle | string | Optional | Title 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
npm install @downtime/reactUsage
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>
);
}| Prop | Type | Description |
|---|---|---|
| orgSlug | string | Your organization slug (from Settings) |
| apiUrl | string | Base URL of your Downtime.so API server |
| statusPageUrl | string | Link shown in the banner pointing to your full status page |