# UptimeSignal - Full API Reference > This is the detailed API reference for AI agents that need to call the UptimeSignal API directly. For a summary, see /llms.txt. Base URL: `https://api.uptimesignal.io` Authentication: `Authorization: Bearer ` header on all authenticated endpoints. --- ## Authentication ### Request Magic Link ``` POST /auth/magic-link Content-Type: application/json { "email": "user@example.com" } Response 200: { "success": true } ``` Sends a magic link email. Creates user account if new. ### Verify Magic Link ``` POST /auth/verify Content-Type: application/json { "token": "" } Response 200: { "token": "eyJ...", "user": { "id": "uuid", "email": "user@example.com", "plan": "free" } } ``` Use the returned `token` as Bearer token for all subsequent requests. Tokens expire in 7 days. ### Get Current User ``` GET /auth/me Authorization: Bearer Response 200: { "user": { "id": "uuid", "email": "user@example.com", "plan": "free", "stripe_customer_id": null } } ``` ### Logout ``` POST /auth/logout Authorization: Bearer Response 200: { "success": true } ``` --- ## Monitors ### List Monitors ``` GET /monitors GET /monitors?tags=production,api Authorization: Bearer Response 200: { "monitors": [ { "id": "uuid", "name": "My API", "url": "https://api.example.com/health", "method": "GET", "interval_seconds": 300, "expected_status_code": 200, "status": "active", "current_status": "up", "consecutive_failures": 0, "last_check_at": 1709900000000, "last_response_time_ms": 145, "created_at": 1709800000000, "keyword": null, "keyword_invert": 0, "ssl_issuer": "R3", "ssl_expires_at": 1717200000000, "ssl_checked_at": 1709900000000, "ssl_alert_days": 14, "paused_at": null, "tags": "[\"production\",\"api\"]", "badge_enabled": 1 } ] } ``` ### Create Monitor ``` POST /monitors Authorization: Bearer Content-Type: application/json { "name": "My API Health", "url": "https://api.example.com/health", "method": "GET", "headers": { "Authorization": "Bearer api-key-123" }, "body": null, "content_type": "application/json", "interval_seconds": 60, "expected_status_code": 200, "keyword": "healthy", "keyword_invert": false, "ssl_alert_days": 14, "tags": ["production", "api"], "response_time_threshold": 2000, "response_time_alert_enabled": true } Response 201: { "id": "uuid" } ``` Parameters: - `name` (required, string, max 100 chars) - `url` (required, string, must start with http:// or https://, max 2000 chars) - `method` (optional, default "GET") - GET, POST, PUT, PATCH, DELETE - `headers` (optional, object) - Custom request headers - `body` (optional, string) - Request body for POST/PUT/PATCH - `content_type` (optional, default "application/json") - Content-Type for request body - `interval_seconds` (optional, default 300) - Check interval. Free: min 300 (5min). Pro: min 60 (1min). - `expected_status_code` (optional, default 200) - Expected HTTP status (100-599) - `keyword` (optional, string) - Keyword to check for in response body - `keyword_invert` (optional, boolean) - If true, alert when keyword IS found - `ssl_alert_days` (optional, default 14) - Days before SSL expiry to alert - `tags` (optional, string[]) - Max 5 tags, lowercase alphanumeric + hyphens, max 20 chars each - `response_time_threshold` (optional, number 1-60000) - Response time threshold in ms - `response_time_alert_enabled` (optional, boolean) - Enable response time SLA alerts ### Get Monitor ``` GET /monitors/:id Authorization: Bearer Response 200: { "monitor": { ...full monitor object... } } ``` ### Update Monitor ``` PUT /monitors/:id Authorization: Bearer Content-Type: application/json { "name": "Updated Name", "url": "https://api.example.com/v2/health", "interval_seconds": 60, "keyword": "ok", "tags": ["production"], "badge_enabled": true, "response_time_threshold": 1500, "response_time_alert_enabled": true } Response 200: { "success": true } ``` All fields are optional. Only provided fields are updated. ### Delete Monitor ``` DELETE /monitors/:id Authorization: Bearer Response 200: { "success": true } ``` ### Pause Monitor ``` POST /monitors/:id/pause Authorization: Bearer Response 200: { "success": true } ``` ### Resume Monitor ``` POST /monitors/:id/resume Authorization: Bearer Response 200: { "success": true } ``` ### Quick Suppress Alerts ``` POST /monitors/:id/suppress Authorization: Bearer Content-Type: application/json { "minutes": 30 } Response 200: { "success": true, "id": "uuid", "message": "Alerts suppressed for 30 minutes", "end_time": 1709901800000 } ``` Creates a one-time maintenance window. Minutes: 1-1440. ### Get Check History ``` GET /monitors/:id/checks?limit=100 Authorization: Bearer Response 200: { "checks": [ { "id": "uuid", "status": "up", "response_time_ms": 145, "status_code": 200, "checked_at": 1709900000000, "error": null } ] } ``` ### Get Single Check (with response body) ``` GET /monitors/:id/checks/:checkId Authorization: Bearer Response 200: { "check": { "id": "uuid", "status": "down", "response_time_ms": 2300, "status_code": 500, "checked_at": 1709900000000, "error": "Expected 200, got 500", "response_body": "{\"error\":\"internal server error\"}", "response_headers": { "content-type": "application/json" } } } ``` ### Get Monitor Stats ``` GET /monitors/:id/stats?period=24h Authorization: Bearer Response 200: { "uptime_percent": 99.85, "avg_response_time": 145, "min_response_time": 98, "max_response_time": 2340, "total_checks": 288, "successful_checks": 287, "incident_count": 1 } ``` Periods: `24h`, `7d`, `30d` ### Get Uptime Bars ``` GET /monitors/:id/uptime-bars?hours=24 Authorization: Bearer Response 200: { "bars": [ { "hour": "2024-03-08T00:00:00.000Z", "status": "up", "avg_response": 142 }, { "hour": "2024-03-08T01:00:00.000Z", "status": "partial", "avg_response": 1200 } ] } ``` Status values: `up`, `down`, `partial`, `empty`. Max hours: 168 (7 days). ### Get Alert History ``` GET /monitors/:id/alerts?limit=50 Authorization: Bearer Response 200: { "alerts": [ { "id": "uuid", "type": "down", "message": "Expected 200, got 500", "sent_at": 1709900000000 } ] } ``` Alert types: `down`, `up`, `ssl_expiring`, `slow`, `slow_recovery` --- ## Dashboard Stats ``` GET /stats Authorization: Bearer Response 200: { "total": 12, "up": 10, "down": 1, "paused": 1, "pending": 0 } ``` ## Tags ``` GET /tags Authorization: Bearer Response 200: { "tags": [ { "name": "production", "count": 5 }, { "name": "api", "count": 3 } ] } ``` --- ## Status Pages ### Create Status Page ``` POST /status-pages Authorization: Bearer Content-Type: application/json { "slug": "my-company", "name": "My Company Status", "logo_url": "https://example.com/logo.png", "monitors": ["monitor-uuid-1", "monitor-uuid-2"] } Response 201: { "id": "uuid", "slug": "my-company" } ``` Free plan: 1 status page. Pro: unlimited. ### Update Status Page ``` PUT /status-pages/:id Authorization: Bearer Content-Type: application/json { "name": "Updated Name", "monitors": ["uuid1", "uuid2"], "accent_color": "#10b981", "header_text": "All systems operational", "show_powered_by": false } Response 200: { "success": true } ``` ### Set Custom Domain (Pro) ``` POST /status-pages/:id/custom-domain Authorization: Bearer Content-Type: application/json { "domain": "status.example.com" } Response 200: { "success": true, "domain": "status.example.com", "cname_target": "status-pages.uptimesignal.io", "validation_records": [ { "txt_name": "_cf-custom-hostname.status.example.com", "txt_value": "..." } ], "ssl_status": "pending_validation", "instructions": "Add a CNAME record pointing status.example.com to status-pages.uptimesignal.io, and add the TXT record for SSL verification." } ``` ### Verify Custom Domain ``` POST /status-pages/:id/custom-domain/verify Authorization: Bearer Response 200 (pending): { "verified": false, "hostname_status": "pending", "ssl_status": "pending_validation", "validation_records": [...], "status_message": "Waiting for your CNAME record.", "status_step": 1, "expected_cname": "status-pages.uptimesignal.io" } Response 200 (verified): { "verified": true, "domain": "status.example.com" } ``` --- ## Incidents ### Create Incident ``` POST /status-pages/:id/incidents Authorization: Bearer Content-Type: application/json { "title": "API Degraded Performance", "status": "investigating", "impact": "minor", "message": "We are investigating reports of slow API responses.", "affected_monitors": ["monitor-uuid-1"] } Response 201: { "id": "uuid" } ``` Statuses: `investigating`, `identified`, `monitoring`, `resolved` Impacts: `none`, `minor`, `major`, `critical` ### Add Incident Update ``` POST /status-pages/:id/incidents/:incidentId/updates Authorization: Bearer Content-Type: application/json { "status": "identified", "message": "Root cause identified. A database connection pool was exhausted." } Response 201: { "id": "uuid" } ``` --- ## Components & Groups ### Create Component Group ``` POST /status-pages/:id/component-groups Authorization: Bearer Content-Type: application/json { "name": "Core Services", "description": "Primary APIs", "collapsed": false } Response 201: { "id": "uuid" } ``` ### Create Component ``` POST /status-pages/:id/components Authorization: Bearer Content-Type: application/json { "name": "User API", "description": "Authentication and user management", "group_id": "group-uuid", "status": "operational" } Response 201: { "id": "uuid" } ``` Statuses: `operational`, `degraded`, `partial_outage`, `major_outage`, `maintenance` ### Update Component Status ``` PUT /status-pages/:id/components/:componentId Authorization: Bearer Content-Type: application/json { "status": "degraded" } Response 200: { "success": true } ``` --- ## Inbound Webhooks (Status Page Automation) ### Create Webhook ``` POST /status-pages/:id/webhooks Authorization: Bearer Content-Type: application/json { "name": "GitHub Actions" } Response 201: { "id": "uuid", "secret": "a1b2c3d4e5...", "webhook_url": "https://api.uptimesignal.io/webhook/a1b2c3d4e5..." } ``` ### Use Inbound Webhook (Public, no auth) ``` POST /webhook/:secret Content-Type: application/json ``` #### Update Component Status ```json { "action": "update_component", "component_name": "User API", "component_status": "degraded" } ``` #### Create Incident ```json { "action": "create_incident", "incident_title": "Deploy in progress", "incident_message": "Deploying v2.3.0 to production.", "incident_impact": "minor" } ``` #### Update Incident ```json { "action": "update_incident", "incident_id": "uuid", "incident_message": "Deploy completed. Verifying stability." } ``` #### Resolve Incident ```json { "action": "resolve_incident", "incident_id": "uuid", "incident_message": "Deploy successful. All systems normal." } ``` --- ## Integrations (Pro only) ### Create Integration ``` POST /integrations Authorization: Bearer Content-Type: application/json ``` #### Slack ```json { "type": "slack", "name": "Slack #alerts", "config": { "webhook_url": "https://hooks.slack.com/services/T00/B00/xxx" } } ``` #### Discord ```json { "type": "discord", "name": "Discord alerts", "config": { "webhook_url": "https://discord.com/api/webhooks/123/abc" } } ``` #### Telegram ```json { "type": "telegram", "name": "Telegram", "config": { "chat_id": "123456789" } } ``` Use the Telegram verification flow instead of providing chat_id directly: 1. `POST /integrations/telegram/init` - Returns `{ "code": "USG-ABC123", "deepLink": "https://t.me/UptimeSignal_Bot?start=USG-ABC123" }` 2. User clicks deep link and sends /start to bot 3. `GET /integrations/telegram/status` - Returns `{ "connected": true }` when verified #### Custom Webhook ```json { "type": "webhook", "name": "PagerDuty", "config": { "webhook_url": "https://my-server.com/webhook", "headers": { "X-Custom-Header": "value" } } } ``` Webhook payload format (sent by UptimeSignal to your URL): ```json { "event": "monitor.down", "monitor": { "id": "uuid", "name": "My API", "url": "https://api.example.com/health" }, "check": { "status_code": 500, "response_time_ms": 2340, "error": "Expected 200, got 500", "timestamp": "2024-03-08T12:00:00.000Z" }, "alert": { "type": "down", "sent_at": "2024-03-08T12:00:05.000Z" }, "downtime_seconds": null } ``` ### Test Integration ``` POST /integrations/:id/test Authorization: Bearer Response 200: { "success": true } ``` --- ## Maintenance Windows ### Create Maintenance Window ``` POST /maintenance Authorization: Bearer Content-Type: application/json ``` #### One-time window ```json { "name": "Server migration", "monitor_id": "uuid-or-null-for-all", "start_time": 1709900000000, "end_time": 1709910000000 } ``` #### Recurring daily ```json { "name": "Nightly backups", "monitor_id": null, "start_time": 1709900000000, "end_time": 1709910000000, "recurring": "daily", "recurring_start_minutes": 120, "recurring_duration_minutes": 60, "timezone": "UTC" } ``` `recurring_start_minutes`: minutes from midnight UTC (e.g., 120 = 02:00 UTC) #### Recurring weekly ```json { "name": "Sunday maintenance", "monitor_id": null, "start_time": 1709900000000, "end_time": 1709910000000, "recurring": "weekly", "recurring_day": 0, "recurring_start_minutes": 60, "recurring_duration_minutes": 120, "timezone": "UTC" } ``` `recurring_day`: 0=Sunday, 1=Monday, ..., 6=Saturday #### Recurring monthly ```json { "name": "Monthly patching", "monitor_id": null, "start_time": 1709900000000, "end_time": 1709910000000, "recurring": "monthly", "recurring_day": 1, "recurring_start_minutes": 0, "recurring_duration_minutes": 240, "timezone": "UTC" } ``` `recurring_day`: 1-31 (day of month) --- ## Badges (Public, no auth required) ### Uptime Badge (SVG) ``` GET /badge/:monitor_id/uptime.svg Returns SVG image showing 30-day uptime percentage. Colors: green (>=99%), yellow (95-99%), red (<95%), gray (N/A) Cache: 5 minutes ``` ### Status Badge (SVG) ``` GET /badge/:monitor_id/status.svg Returns SVG showing current status: operational/down/pending Colors: green (up), red (down), yellow (pending), gray (unknown) ``` ### Response Time Badge (SVG) ``` GET /badge/:monitor_id/response.svg Returns SVG showing average 24h response time in ms. Colors: green (<500ms), yellow (500-1000ms), red (>1000ms) ``` ### Badge Data (JSON) ``` GET /badge/:monitor_id/data.json Response 200: { "monitor_id": "uuid", "name": "My API", "status": "up", "uptime_percent_30d": 99.95, "avg_response_ms_24h": 145, "generated_at": "2024-03-08T12:00:00.000Z" } ``` Embed in README: ```markdown ![Uptime](https://api.uptimesignal.io/badge/MONITOR_ID/uptime.svg) ![Status](https://api.uptimesignal.io/badge/MONITOR_ID/status.svg) ``` --- ## Billing ### Create Checkout (Upgrade to Pro) ``` POST /stripe/checkout Authorization: Bearer Response 200: { "url": "https://checkout.stripe.com/..." } ``` Redirect user to the returned URL for Stripe Checkout. ### Create Billing Portal ``` POST /stripe/portal Authorization: Bearer Response 200: { "url": "https://billing.stripe.com/..." } ``` --- ## Tools (Public, rate-limited: 10 req/min per IP) ### Check URL ``` POST /tools/check-url Content-Type: application/json { "url": "https://example.com" } Response 200: { "url": "https://example.com", "status": 200, "statusText": "OK", "responseTime": 245, "isUp": true, "timestamp": "2024-03-08T12:00:00.000Z" } ``` ### SSL Check ``` POST /tools/ssl-check Content-Type: application/json { "domain": "example.com" } Response 200: { "domain": "example.com", "valid": true, "protocol": "TLS", "message": "SSL certificate is valid and the site is accessible over HTTPS.", "checkedAt": "2024-03-08T12:00:00.000Z" } ``` --- ## Public Status Page Data (no auth) ``` GET /public/status/:slug Response 200: { "name": "My Company Status", "logo_url": "https://example.com/logo.png", "accent_color": "#10b981", "header_text": "All systems operational", "show_powered_by": 1, "overall_status": "operational", "monitors": [ { "id": "uuid", "name": "API", "status": "up", "uptime_30d": 99.95, "uptime_bars": [100, 100, 99.5, ...], "last_checked": "2024-03-08T12:00:00.000Z", "affected_by_incident": false } ], "component_groups": [...], "components": [...], "active_incidents": [...], "past_incidents": [...], "updated_at": "2024-03-08T12:00:00.000Z" } ``` Overall status: `operational`, `partial`, `major` --- ## Test Endpoints (Public) All return JSON: `{ "status": , "message": "...", "timestamp": "...", "powered_by": "UptimeSignal" }` | Endpoint | Status Code | Notes | |---|---|---| | GET /test/healthy | 200 | | | GET /test/unhealthy | 500 | | | GET /test/200 | 200 | | | GET /test/201 | 201 | | | GET /test/400 | 400 | | | GET /test/401 | 401 | | | GET /test/403 | 403 | | | GET /test/404 | 404 | | | GET /test/500 | 500 | | | GET /test/502 | 502 | | | GET /test/503 | 503 | | | GET /test/504 | 504 | | | GET /test/timeout | 200 | 60s delay | | GET /test/slow | 200 | 5s delay | | GET /test/random | 200/500/503 | Random | --- ## Error Responses All errors follow this format: ```json { "error": "Human-readable error message", "code": "OPTIONAL_ERROR_CODE" } ``` Common error codes: - `INTERVAL_RESTRICTED` - Check interval below plan minimum - `PRO_REQUIRED` - Feature requires Pro plan Common HTTP status codes: - 400 - Bad request / validation error - 401 - Unauthorized / invalid token - 403 - Forbidden / plan limit reached - 404 - Resource not found - 429 - Rate limit exceeded - 500 - Internal server error --- ## Monitoring Behavior - Checks run every minute via Cloudflare Workers cron - A monitor is marked "down" after 2 consecutive failures - Recovery alert sent when next check succeeds - SSL certificates checked once per day for HTTPS monitors - Alerts suppressed during active maintenance windows (one-time and recurring) - Response time SLA: alert when response exceeds threshold, recovery when back below - Keyword validation runs after status code check - Response body and headers captured on failed checks (truncated at 10KB) - User-Agent: `UptimeSignal/1.0 (https://uptimesignal.io)` --- ## Quick-Start for AI Agents If you are an AI agent setting up monitoring for a user, here is the fastest path: ### Step 1: Create a monitor (one API call) Only `name` and `url` are required. Everything else has sensible defaults. ```bash curl -X POST https://api.uptimesignal.io/monitors \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{"name": "Production API", "url": "https://api.example.com/health"}' ``` Response: `{"id": "abc-123"}` Defaults applied: GET method, 5-min interval (free) / 1-min (Pro), expects HTTP 200, email alerts enabled. ### Step 2: Verify it's working ```bash curl https://api.uptimesignal.io/monitors/abc-123 \ -H "Authorization: Bearer $TOKEN" ``` ### Step 3: Check status across all monitors ```bash curl https://api.uptimesignal.io/stats \ -H "Authorization: Bearer $TOKEN" ``` Response: `{"total": 1, "up": 1, "down": 0, "paused": 0, "pending": 0}` ### Common agent workflows **Monitor a new deployment:** ```bash # Create monitor for the deployed service curl -X POST https://api.uptimesignal.io/monitors \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{"name": "Staging API", "url": "https://staging.example.com/health", "tags": ["staging"]}' ``` **Check if a URL is up right now (no account needed):** ```bash curl -X POST https://api.uptimesignal.io/tools/check-url \ -H "Content-Type: application/json" \ -d '{"url": "https://example.com"}' ``` **Pause monitoring during a deploy:** ```bash curl -X POST https://api.uptimesignal.io/monitors/MONITOR_ID/suppress \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{"minutes": 15}' ``` **Create a status page with existing monitors:** ```bash curl -X POST https://api.uptimesignal.io/status-pages \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{"slug": "acme", "name": "Acme Status", "monitors": ["monitor-id-1", "monitor-id-2"]}' ``` **Get 30-day uptime stats:** ```bash curl "https://api.uptimesignal.io/monitors/MONITOR_ID/stats?period=30d" \ -H "Authorization: Bearer $TOKEN" ``` --- ## MCP Server The `uptimesignal-mcp` npm package exposes UptimeSignal tools via the Model Context Protocol, so AI agents can manage monitors through natural language. ### Installation ```bash npx uptimesignal-mcp ``` ### Configuration for Claude Code Add to `~/.claude/settings.json`: ```json { "mcpServers": { "uptimesignal": { "command": "npx", "args": ["-y", "uptimesignal-mcp"], "env": { "UPTIMESIGNAL_API_KEY": "your-api-token" } } } } ``` ### Configuration for Cursor Add to `.cursor/mcp.json`: ```json { "mcpServers": { "uptimesignal": { "command": "npx", "args": ["-y", "uptimesignal-mcp"], "env": { "UPTIMESIGNAL_API_KEY": "your-api-token" } } } } ``` ### Configuration for GitHub Copilot (VS Code) Add to VS Code `settings.json`: ```json { "github.copilot.chat.mcp.servers": { "uptimesignal": { "command": "npx", "args": ["-y", "uptimesignal-mcp"], "env": { "UPTIMESIGNAL_API_KEY": "your-api-token" } } } } ``` ### Configuration for OpenAI Codex CLI Add to `~/.codex/config.toml`: ```toml [mcp.uptimesignal] command = "npx" args = ["-y", "uptimesignal-mcp"] [mcp.uptimesignal.env] UPTIMESIGNAL_API_KEY = "your-api-token" ``` ### Available MCP Tools | Tool | Description | |------|-------------| | `list_monitors` | List all monitors with status, uptime, response time | | `create_monitor` | Create a monitor (name + URL required) | | `get_monitor` | Get detailed monitor info | | `update_monitor` | Update monitor configuration | | `delete_monitor` | Delete a monitor | | `pause_monitor` | Pause checks and alerts | | `resume_monitor` | Resume a paused monitor | | `get_monitor_stats` | Uptime stats for 24h, 7d, or 30d | | `get_monitor_checks` | Recent check history with status codes | | `check_url` | One-off URL check (no monitor created) | | `get_dashboard_stats` | Overall up/down/paused counts | | `list_status_pages` | List status pages | | `create_status_page` | Create a public status page | | `delete_status_page` | Delete a status page | ### Getting an API Token 1. Sign in at https://app.uptimesignal.io 2. Go to Settings > API Tokens 3. Create a token and use it as `UPTIMESIGNAL_API_KEY` --- ## Comparison to Alternatives | Feature | UptimeSignal (Pro) | UptimeRobot (Pro) | Pingdom | Better Stack | Checkly | |---|---|---|---|---|---| | Price | $10/mo flat | from $7/mo (10 monitors) | $15/mo per 10 monitors | $29/mo per responder | $30/mo | | Unlimited monitors | Yes | No (tiered) | No (tiered) | No (tiered) | No (tiered) | | Min check interval | 1 min | 1 min | 1 min | 30 sec | 1 min | | Status pages | Included | Separate product | Included | Included | Not included | | Custom domains | Yes (auto-SSL) | No | No | Yes | N/A | | Free tier | 25 monitors | 50 monitors | None | 5 monitors | 5 monitors | | Free commercial use | Yes | Yes | N/A | Yes | Yes | | MCP server | Yes | No | No | No | No | | API simplicity | 2 required fields | 3+ required fields | Complex | Complex | Complex | Key differentiators: - Flat pricing: $10/mo for unlimited everything, no per-monitor or per-seat charges - Agent-native: MCP server for AI coding agents, API designed for programmatic use - Minimum viable request: `{"name": "...", "url": "..."}` — two fields to create a monitor - Free tier allows commercial use with no credit card required