# Alert channels Source: https://docs.larm.dev/alert-channels Alert channel types and configuration Alert channels define where Larm sends notifications when a monitor goes down or recovers. Each monitor can be linked to one or more channels. Larm sends alerts for these events: * **Monitor down** — a monitor has been confirmed down * **Monitor recovered** — a monitor is back up * **Certificate expiring** — an SSL certificate is nearing expiry * **Test** — a manual test alert sent from the dashboard ## Slack Posts a formatted message to a Slack channel via an incoming webhook. | Field | Description | | --------------- | ---------------------------------------------------------------------------- | | **Webhook URL** | Slack incoming webhook URL (starts with `https://hooks.slack.com/services/`) | ## Discord Posts an embed message to a Discord channel via webhook. | Field | Description | | --------------- | ----------------------------------------------------------------------------- | | **Webhook URL** | Discord webhook URL (matches `https://discord.com/api/webhooks/{id}/{token}`) | ## Email Sends an HTML email to one or more recipients. | Field | Description | | -------------- | ----------------------- | | **Recipients** | List of email addresses | ## Webhook POSTs a JSON payload to any HTTPS URL. Use this to integrate with services Larm doesn't have a native adapter for. | Field | Required | Description | | -------------------- | -------- | ------------------------------------------------------------------------------ | | **URL** | Yes | HTTPS endpoint to receive the payload | | **Signing secret** | No | Used to generate an HMAC-SHA256 signature in the `x-larm-signature-256` header | | **Headers** | No | Custom HTTP headers to include with the request | | **Payload template** | No | Custom JSON template with variable interpolation | See [Webhooks](/webhooks) for payload format, template variables, and signature verification. ## PagerDuty Triggers and resolves incidents via the PagerDuty Events API v2. | Field | Description | | ------------------- | ---------------------------------------------------- | | **Integration key** | 32-character PagerDuty Events API v2 integration key | When a monitor goes down, Larm triggers a PagerDuty incident. When it recovers, Larm automatically resolves the incident using a stable dedup key. ## Microsoft Teams Posts an Adaptive Card message to a Teams channel. Supports both legacy Office 365 Connector and Power Automate Workflow webhooks. | Field | Description | | --------------- | -------------------------- | | **Webhook URL** | Teams incoming webhook URL | ## Grafana IRM Creates and resolves alerts in Grafana OnCall via the Formatted Webhook integration. | Field | Description | | ------------------- | ------------------------------------------------ | | **Integration URL** | Grafana OnCall Formatted Webhook integration URL | When a monitor goes down, Larm creates an alert in Grafana OnCall. When it recovers, the alert is automatically resolved using a stable dedup key. ## ilert Creates and resolves alerts via the ilert Events API. ilert is an EU-native incident management platform based in Cologne, Germany. | Field | Description | | ----------- | -------------------------- | | **API key** | ilert alert source API key | When a monitor goes down, Larm creates a HIGH-priority alert in ilert. When it recovers, the alert is automatically resolved using a stable dedup key. Certificate expiry and test alerts are created with LOW priority. ## incident.io Creates and resolves alerts via incident.io's HTTP Alert Source API. | Field | Description | | -------------------- | --------------------------------------------------------------------- | | **Alert source URL** | incident.io alert source URL (starts with `https://api.incident.io/`) | | **API token** | incident.io API token for authentication | When a monitor goes down, Larm fires an alert in incident.io. When it recovers, the alert is automatically resolved using a stable dedup key. ## Mattermost Posts a formatted message to a Mattermost channel via an incoming webhook. | Field | Required | Description | | --------------- | -------- | ------------------------------------------- | | **Webhook URL** | Yes | Mattermost incoming webhook URL | | **Channel** | No | Override the webhook's default channel | | **Username** | No | Override the webhook's default bot username | ## Pushover Sends push notifications to your devices via Pushover. | Field | Description | | ------------------ | -------------------------------------------------- | | **User/group key** | Your Pushover user key or delivery group key | | **API token** | Application API token from your Pushover dashboard | ## ntfy Sends notifications via [ntfy](https://ntfy.sh), a simple pub/sub notification service. Works with the public ntfy.sh instance or your own self-hosted server. | Field | Required | Description | | ---------------- | -------- | ---------------------------------------- | | **Server URL** | Yes | ntfy server URL (e.g. `https://ntfy.sh`) | | **Topic** | Yes | Topic name to publish to | | **Access token** | No | Required for authenticated ntfy servers | ## Telegram Sends messages to a Telegram chat via the Bot API. You provide your own bot (created via [@BotFather](https://t.me/BotFather)) and a chat ID. | Field | Description | | ------------- | ------------------------------------------------------------ | | **Bot token** | Bot API token from BotFather (format: `123456789:ABCdef...`) | | **Chat ID** | Numeric chat/group ID (e.g. `-1001234567890`) or `@username` | To find your chat ID, send a message to your bot and visit `https://api.telegram.org/bot/getUpdates`. ## SMS SMS alerts are available on Pro and Business plans. Sends a text message to a verified phone number. | Field | Description | | ---------------- | --------------------------------------------------- | | **Phone number** | Phone number in E.164 format (e.g. `+447700900000`) | When you add an SMS channel, the phone number must be verified via a confirmation code. SMS alerts are metered: Pro plans include 125 messages per month, Business includes 500 per month. Additional hourly and daily rate limits apply to prevent burst costs from flapping monitors. ## Retries and failure handling Alert delivery is attempted up to 3 times with exponential backoff. If a channel returns a permanent error (401, 403, or 404), Larm disables the channel automatically and notifies the organization owner by email. You can re-enable it from the dashboard after fixing the configuration. # Create alert channel Source: https://docs.larm.dev/api-reference/alert-channels/create POST /api/v1/alert-channels Creates a new alert channel Requires `alert_channels:read_write` permission. Channel name (1–255 characters) `slack`, `discord`, `email`, `webhook`, `pagerduty`, `teams`, `grafana_irm`, `ilert`, `incident_io`, `mattermost`, `pushover`, `ntfy`, `telegram`, or `sms` Type-specific configuration. See [Alert channels](/alert-channels) for fields per type. Whether the channel is active Automatically link to newly created monitors ```json 201 theme={null} { "data": { "id": "550e8400-e29b-41d4-a716-446655440000", "name": "Engineering Slack", "type": "slack", "enabled": true, "default_for_new_monitors": true, "broken_at": null, "broken_reason": null, "inserted_at": "2025-03-01T12:00:00Z", "updated_at": "2025-03-01T12:00:00Z" } } ``` # Delete alert channel Source: https://docs.larm.dev/api-reference/alert-channels/delete DELETE /api/v1/alert-channels/{id} Deletes an alert channel Requires `alert_channels:read_write` permission. Alert channel ID (UUID) ```json 204 theme={null} ``` # Get alert channel Source: https://docs.larm.dev/api-reference/alert-channels/get GET /api/v1/alert-channels/{id} Returns a single alert channel by ID Requires `alert_channels:read` permission. Alert channel ID (UUID) ```json 200 theme={null} { "data": { "id": "550e8400-e29b-41d4-a716-446655440000", "name": "Engineering Slack", "type": "slack", "enabled": true, "default_for_new_monitors": true, "broken_at": null, "broken_reason": null, "inserted_at": "2025-03-01T12:00:00Z", "updated_at": "2025-03-01T12:00:00Z" } } ``` # List alert channels Source: https://docs.larm.dev/api-reference/alert-channels/list GET /api/v1/alert-channels Returns all alert channels in the organization Requires `alert_channels:read` permission. ```json 200 theme={null} { "data": [ { "id": "550e8400-e29b-41d4-a716-446655440000", "name": "Engineering Slack", "type": "slack", "enabled": true, "default_for_new_monitors": true, "broken_at": null, "broken_reason": null, "inserted_at": "2025-03-01T12:00:00Z", "updated_at": "2025-03-01T12:00:00Z" } ] } ``` # Update alert channel Source: https://docs.larm.dev/api-reference/alert-channels/update PATCH /api/v1/alert-channels/{id} Updates an existing alert channel Requires `alert_channels:read_write` permission. Only include the fields you want to change. Alert channel ID (UUID) Channel name (1–255 characters) Type-specific configuration. See [Alert channels](/alert-channels) for fields per type. Whether the channel is active Automatically link to newly created monitors ```json 200 theme={null} { "data": { "id": "550e8400-e29b-41d4-a716-446655440000", "name": "Ops Slack", "type": "slack", "enabled": true, "default_for_new_monitors": false, "broken_at": null, "broken_reason": null, "inserted_at": "2025-03-01T12:00:00Z", "updated_at": "2025-03-01T14:30:00Z" } } ``` # Create component group Source: https://docs.larm.dev/api-reference/component-groups/create POST /api/v1/status-pages/{status_page_id}/component-groups Creates a new component group on a status page Requires `status_pages:read_write` permission. Component groups render as collapsible headings on the public status page. Status page UUID Group name (1–255 characters) Display position (0-indexed) within the page ```json 201 theme={null} { "data": { "id": "880e8400-e29b-41d4-a716-446655440000", "name": "Backend", "position": 0, "inserted_at": "2025-03-01T12:00:00Z", "updated_at": "2025-03-01T12:00:00Z" } } ``` # Delete component group Source: https://docs.larm.dev/api-reference/component-groups/delete DELETE /api/v1/status-pages/{status_page_id}/component-groups/{id} Deletes a component group Requires `status_pages:read_write` permission. Components inside the deleted group are detached and become ungrouped top-level entries on the page. Status page UUID Component group UUID ```json 204 theme={null} ``` # Get component group Source: https://docs.larm.dev/api-reference/component-groups/show GET /api/v1/status-pages/{status_page_id}/component-groups/{id} Returns a single component group Requires `status_pages:read` permission. Status page UUID Component group UUID ```json 200 theme={null} { "data": { "id": "880e8400-e29b-41d4-a716-446655440000", "name": "Backend", "position": 0, "inserted_at": "2025-03-01T12:00:00Z", "updated_at": "2025-03-01T12:00:00Z" } } ``` # Update component group Source: https://docs.larm.dev/api-reference/component-groups/update PATCH /api/v1/status-pages/{status_page_id}/component-groups/{id} Updates a component group's name or position Requires `status_pages:read_write` permission. Status page UUID Component group UUID Group name Display position ```json 200 theme={null} { "data": { "id": "880e8400-e29b-41d4-a716-446655440000", "name": "Backend services", "position": 1, "inserted_at": "2025-03-01T12:00:00Z", "updated_at": "2025-03-01T14:30:00Z" } } ``` # Create component Source: https://docs.larm.dev/api-reference/components/create POST /api/v1/status-pages/{status_page_id}/components Adds a component to a status page Requires `status_pages:read_write` permission. Status page UUID Component name (1–255 characters) Display position (0-indexed) Optional description Optional group UUID to organize components under a heading Monitors to link. Each object has `monitor_id` (monitor UUID) and `down_status` (`major_outage`, `partial_outage`, or `degraded_performance`). Linked monitors trigger auto-disruptions when they detect failures. ```json 201 theme={null} { "data": { "id": "550e8400-e29b-41d4-a716-446655440000", "name": "API", "description": "REST API endpoints", "position": 0, "component_group_id": null, "monitors": [ { "monitor_id": "660e8400-e29b-41d4-a716-446655440000", "down_status": "major_outage" } ], "inserted_at": "2026-03-28T12:00:00Z", "updated_at": "2026-03-28T12:00:00Z" } } ``` # Delete component Source: https://docs.larm.dev/api-reference/components/delete DELETE /api/v1/status-pages/{status_page_id}/components/{id} Removes a component from a status page Requires `status_pages:read_write` permission. Status page UUID Component UUID Returns `204 No Content` on success. # Get component Source: https://docs.larm.dev/api-reference/components/get GET /api/v1/status-pages/{status_page_id}/components/{id} Returns a single component with its linked monitors Requires `status_pages:read` permission. Status page UUID Component UUID ```json 200 theme={null} { "data": { "id": "550e8400-e29b-41d4-a716-446655440000", "name": "API", "description": "REST API and GraphQL endpoints", "position": 0, "component_group_id": null, "monitors": [ { "monitor_id": "660e8400-e29b-41d4-a716-446655440000", "down_status": "major_outage" } ], "inserted_at": "2026-03-01T12:00:00Z", "updated_at": "2026-03-01T12:00:00Z" } } ``` # Update component Source: https://docs.larm.dev/api-reference/components/update PATCH /api/v1/status-pages/{status_page_id}/components/{id} Updates a component's name, description, position, or linked monitors Requires `status_pages:read_write` permission. Status page UUID Component UUID Component name Component description Display position Group UUID Replaces all linked monitors. Each object has `monitor_id` (monitor UUID) and `down_status`. ```json 200 theme={null} { "data": { "id": "550e8400-e29b-41d4-a716-446655440000", "name": "API v2", "description": "Updated API", "position": 0, "component_group_id": null, "monitors": [], "inserted_at": "2026-03-28T12:00:00Z", "updated_at": "2026-03-28T13:00:00Z" } } ``` # Create disruption Source: https://docs.larm.dev/api-reference/disruptions/create POST /api/v1/disruptions Creates a new disruption, optionally publishing to a status page Requires `incidents:read_write` permission. Create a disruption to communicate a service issue. Optionally publish to a status page with affected components in the same call. Disruption title (1–255 characters) When the disruption began (ISO 8601 timestamp, e.g. `2026-03-28T12:00:00Z`) `disruption` or `maintenance` `minor`, `major`, or `critical` Initial timeline message. If omitted, the disruption is created with a default message. UUID of the status page to publish to. Must be used together with `components`. Components to mark as affected. Each object has `id` (component UUID) and `status` (`major_outage`, `partial_outage`, `degraded_performance`, `under_maintenance`, or `operational`). ```json 201 theme={null} { "data": { "id": "550e8400-e29b-41d4-a716-446655440000", "title": "API outage", "type": "disruption", "status": "investigating", "impact": "major", "auto_created": false, "started_at": "2026-03-28T12:00:00Z", "resolved_at": null, "updates": [ { "id": "660e8400-e29b-41d4-a716-446655440000", "status": "investigating", "body": "Investigating API errors.", "posted_at": "2026-03-28T12:00:00Z", "posted_by": "user@example.com" } ], "affected_components": [ { "id": "770e8400-e29b-41d4-a716-446655440000", "name": "API", "status": "major_outage" } ], "inserted_at": "2026-03-28T12:00:00Z", "updated_at": "2026-03-28T12:00:00Z" } } ``` # Get disruption Source: https://docs.larm.dev/api-reference/disruptions/get GET /api/v1/disruptions/{id} Returns a disruption with its timeline and affected components Requires `incidents:read` permission. Disruption UUID ```json 200 theme={null} { "data": { "id": "550e8400-e29b-41d4-a716-446655440000", "title": "API outage", "type": "disruption", "status": "identified", "impact": "major", "auto_created": false, "started_at": "2026-03-28T12:00:00Z", "resolved_at": null, "updates": [ { "id": "770e8400-e29b-41d4-a716-446655440000", "status": "identified", "body": "Root cause found in database connection pool.", "posted_at": "2026-03-28T12:30:00Z", "posted_by": "user@example.com" }, { "id": "660e8400-e29b-41d4-a716-446655440000", "status": "investigating", "body": "Investigating API errors.", "posted_at": "2026-03-28T12:00:00Z", "posted_by": "user@example.com" } ], "affected_components": [ { "id": "880e8400-e29b-41d4-a716-446655440000", "name": "API", "status": "major_outage" } ], "inserted_at": "2026-03-28T12:00:00Z", "updated_at": "2026-03-28T12:30:00Z" } } ``` # List disruptions Source: https://docs.larm.dev/api-reference/disruptions/list GET /api/v1/disruptions Lists disruptions for your organization Requires `incidents:read` permission. Filter by status: `investigating`, `identified`, `monitoring`, `resolved`, `scheduled`, `in_progress`, `completed` Filter by type: `disruption` or `maintenance` ```json 200 theme={null} { "data": [ { "id": "550e8400-e29b-41d4-a716-446655440000", "title": "API outage", "type": "disruption", "status": "investigating", "impact": "major", "auto_created": false, "started_at": "2026-03-28T12:00:00Z", "resolved_at": null, "inserted_at": "2026-03-28T12:00:00Z", "updated_at": "2026-03-28T12:00:00Z" } ] } ``` # Update disruption Source: https://docs.larm.dev/api-reference/disruptions/update PATCH /api/v1/disruptions/{id} Updates a disruption — change fields, add a timeline entry, publish to a status page, or resolve Requires `incidents:read_write` permission. All fields are optional. A single call can update the title, add a timeline message, publish to a status page, and resolve — all at once. Disruption UUID Update the disruption title `minor`, `major`, or `critical` Advance the disruption status. Setting to `resolved` or `completed` resolves the disruption. Disruption statuses: `investigating`, `identified`, `monitoring`, `resolved` Maintenance statuses: `scheduled`, `in_progress`, `completed` Adds a timeline entry with this message. If `status` is also provided, the entry reflects the new status. UUID of the status page to publish to. Must be used together with `components`. Components to mark as affected. Each object has `id` (component UUID) and `status` (`major_outage`, `partial_outage`, `degraded_performance`, `under_maintenance`, or `operational`). ```json 200 theme={null} { "data": { "id": "550e8400-e29b-41d4-a716-446655440000", "title": "API outage", "type": "disruption", "status": "resolved", "impact": "major", "auto_created": false, "started_at": "2026-03-28T12:00:00Z", "resolved_at": "2026-03-28T13:00:00Z", "updates": [ { "id": "880e8400-e29b-41d4-a716-446655440000", "status": "resolved", "body": "Issue fixed. All services operational.", "posted_at": "2026-03-28T13:00:00Z", "posted_by": "user@example.com" } ], "affected_components": [], "inserted_at": "2026-03-28T12:00:00Z", "updated_at": "2026-03-28T13:00:00Z" } } ``` # Heartbeat Source: https://docs.larm.dev/api-reference/heartbeat GET /api/heartbeat/{token} Monitor cron jobs, scheduled tasks, and background workers Heartbeat monitor token, found in monitor settings Heartbeat monitors work by expecting a periodic ping. If the ping stops arriving within the configured interval, Larm marks the monitor as down and fires alerts. ## Endpoint ``` ANY https://app.larm.dev/api/heartbeat/{token} ``` Accepts any HTTP method (GET, POST, HEAD, etc.). The token is found in your heartbeat monitor's settings in the dashboard. No `Authorization` header is needed. The token in the URL is the authentication. ## Response Every call returns `200 {"status": "ok"}`. This is deliberate — invalid tokens, missing monitors, and rate-limited pings all return the same response to prevent token enumeration. ```json 200 theme={null} { "status": "ok" } ``` ## Rate limiting To bound storage from abusive ping rates, Larm records at most one heartbeat per token within a window of `interval_seconds × 100` milliseconds — roughly 10 pings per expected interval. Pings beyond that within the same window still return `200 {"status": "ok"}` but are not stored. Extra pings never cause an alert. ## Examples ### Cron job Ping after your job completes. If the job fails or hangs, the ping never arrives and Larm alerts you. ```bash theme={null} # Add to the end of your crontab entry 0 * * * * /usr/local/bin/backup.sh && curl -sf https://app.larm.dev/api/heartbeat/YOUR_TOKEN ``` ### curl ```bash theme={null} curl https://app.larm.dev/api/heartbeat/YOUR_TOKEN ``` ### Python ```python theme={null} import requests requests.get("https://app.larm.dev/api/heartbeat/YOUR_TOKEN") ``` ### Node.js ```javascript theme={null} fetch("https://app.larm.dev/api/heartbeat/YOUR_TOKEN"); ``` ### Ruby ```ruby theme={null} require "net/http" Net::HTTP.get(URI("https://app.larm.dev/api/heartbeat/YOUR_TOKEN")) ``` # Get current organization Source: https://docs.larm.dev/api-reference/identity/me GET /api/v1/me Returns the organization that the current API key or OAuth token belongs to Requires `monitors:read` permission. Useful for confirming which organization a token is scoped to before making writes. ```json 200 theme={null} { "data": { "organization": { "id": 123, "name": "Acme Inc." } } } ``` # Introduction Source: https://docs.larm.dev/api-reference/introduction Authenticate and interact with the Larm API ## Base URL ``` https://app.larm.dev/api/v1 ``` ## Authentication All API requests require a Bearer token in the `Authorization` header: ```bash theme={null} curl https://app.larm.dev/api/v1/monitors \ -H "Authorization: Bearer larm_api_..." ``` ### Creating an API key 1. Go to **Dashboard > Settings > API Keys** 2. Click **Create API key** 3. Choose permissions for each resource (monitors, status pages, alert channels) 4. Copy the key — it's only shown once API keys use the format `larm_api_`. ### Permissions Each API key has a permission level per resource: | Resource | Levels | | -------------- | ---------------------------- | | Monitors | `none`, `read`, `read_write` | | Status pages | `none`, `read`, `read_write` | | Alert channels | `none`, `read`, `read_write` | Full API access (read and write) is available on all plans, including Free. ## Rate limits | Operation | Limit | | --------- | ---------------- | | Read | 120 requests/min | | Write | 30 requests/min | | Stats | 30 requests/min | Limits are per API key. Rate limit headers are included on every response: | Header | Description | | ----------------------- | ----------------------------------------- | | `x-ratelimit-limit` | Maximum requests allowed in the window | | `x-ratelimit-remaining` | Requests remaining in the current window | | `x-ratelimit-reset` | Unix timestamp when the window resets | | `retry-after` | Seconds until you can retry (only on 429) | ## Error format All errors return a consistent JSON structure: ```json theme={null} { "error": { "type": "invalid_api_key", "message": "The provided API key is invalid or has been revoked." } } ``` ### Standard error codes | Status | Type | Description | | ------ | ----------------- | ---------------------------------------------- | | 401 | `invalid_api_key` | Missing, invalid, or revoked API key | | 403 | `forbidden` | API key lacks the required permission | | 429 | `rate_limited` | Too many requests — check `retry-after` header | The [heartbeat endpoint](/api-reference/heartbeat) uses token-based authentication (no API key needed). All other endpoints require an API key. # Get certificate info Source: https://docs.larm.dev/api-reference/monitors/cert GET /api/v1/monitors/{monitor_id}/cert Returns TLS certificate information for an HTTP monitor Requires `monitors:read` permission. Uses the **Stats** rate limit bucket (30 req/min). Monitor ID (UUID) Returns certificate details from the most recent check result. Only meaningful for HTTP monitors — returns 404 if the monitor has no TLS data. ```json 200 theme={null} { "data": { "cert_expiry": "2026-06-01T00:00:00Z", "cert_valid": true, "cert_issuer": "Let's Encrypt", "cert_subject": "example.com", "days_remaining": 85 } } ``` ```json 404 No certificate data theme={null} { "error": { "type": "not_found", "message": "No certificate data" } } ``` # Create monitor Source: https://docs.larm.dev/api-reference/monitors/create POST /api/v1/monitors Creates a new monitor Requires `monitors:read_write` permission. Monitor name (1–255 characters) `http`, `tcp`, `dns`, `heartbeat`, or `synthetic` Type-specific configuration. See [Monitors](/monitors) for fields per type. Check interval in seconds (minimum: 30) Timeout in milliseconds (range: 1000–60000) Minutes of consecutive failures before marking down (HTTP, TCP, DNS, heartbeat) Minutes of consecutive successes before marking recovered (HTTP, TCP, DNS, heartbeat) Consecutive failures before marking down (synthetic monitors only, range: 1–10) Consecutive passes before marking recovered (synthetic monitors only, range: 1–10) Whether the monitor is active List of alert channel IDs to attach. If omitted, channels with `default_for_new_monitors` are linked automatically. ```json 201 theme={null} { "data": { "id": "550e8400-e29b-41d4-a716-446655440000", "name": "Marketing site", "check_type": "http", "enabled": true, "interval_seconds": 180, "timeout_ms": 10000, "confirm_down_minutes": 1, "confirm_up_minutes": 3, "config": { "url": "https://example.com", "method": "GET", "expected_status_codes": [200], "follow_redirects": true }, "current_state": "pending", "alert_channel_ids": ["660e8400-e29b-41d4-a716-446655440000"], "inserted_at": "2025-03-01T12:00:00Z", "updated_at": "2025-03-01T12:00:00Z" } } ``` # Delete monitor Source: https://docs.larm.dev/api-reference/monitors/delete DELETE /api/v1/monitors/{id} Deletes a monitor Requires `monitors:read_write` permission. Monitor ID (UUID) ```json 204 theme={null} ``` # Get monitor Source: https://docs.larm.dev/api-reference/monitors/get GET /api/v1/monitors/{id} Returns a single monitor by ID Requires `monitors:read` permission. Monitor ID (UUID) ```json 200 theme={null} { "data": { "id": "550e8400-e29b-41d4-a716-446655440000", "name": "Marketing site", "check_type": "http", "enabled": true, "interval_seconds": 180, "timeout_ms": 10000, "confirm_down_minutes": 1, "confirm_up_minutes": 3, "config": { "url": "https://example.com", "method": "GET", "expected_status_codes": [200], "follow_redirects": true }, "current_state": "up", "alert_channel_ids": ["660e8400-e29b-41d4-a716-446655440000"], "inserted_at": "2025-03-01T12:00:00Z", "updated_at": "2025-03-01T12:00:00Z" } } ``` # List monitors Source: https://docs.larm.dev/api-reference/monitors/list GET /api/v1/monitors Returns all monitors in the organization Requires `monitors:read` permission. ```json 200 theme={null} { "data": [ { "id": "550e8400-e29b-41d4-a716-446655440000", "name": "Marketing site", "check_type": "http", "enabled": true, "interval_seconds": 180, "timeout_ms": 10000, "confirm_down_minutes": 1, "confirm_up_minutes": 3, "config": { "url": "https://example.com", "method": "GET", "expected_status_codes": [200], "follow_redirects": true }, "current_state": "up", "alert_channel_ids": ["660e8400-e29b-41d4-a716-446655440000"], "inserted_at": "2025-03-01T12:00:00Z", "updated_at": "2025-03-01T12:00:00Z" } ] } ``` # Get response times Source: https://docs.larm.dev/api-reference/monitors/response-times GET /api/v1/monitors/{monitor_id}/response-times Returns p95 response times overall and by probe location Requires `monitors:read` permission. Uses the **Stats** rate limit bucket (30 req/min). Monitor ID (UUID) Time range. One of: `1h`, `6h`, `24h`, `7d`, `30d`, `90d`. Returns the aggregate p95 response time (averaged across regions) and a per-region breakdown sorted by p95 descending. ```json 200 theme={null} { "data": { "p95": 142.5, "by_location": [ { "location": "us-east", "p95": 185.2, "checks": 1440 }, { "location": "eu-central", "p95": 99.8, "checks": 1440 } ] } } ``` ```json 200 No data theme={null} { "data": { "p95": null, "by_location": [] } } ``` # Get monitor state Source: https://docs.larm.dev/api-reference/monitors/state GET /api/v1/monitors/{monitor_id}/state Returns the current state of a monitor Requires `monitors:read` permission. Uses the **Stats** rate limit bucket (30 req/min). Monitor ID (UUID) The state reflects the evaluator's current assessment: `pending` (no data yet), `up`, `down`, or `stale` (no recent check results). ```json 200 theme={null} { "data": { "state": "up", "entered_at": "2025-03-01T12:00:00.000000Z", "previous_state": "down" } } ``` ```json 200 No state yet theme={null} { "data": { "state": null, "entered_at": null, "previous_state": null } } ``` # Update monitor Source: https://docs.larm.dev/api-reference/monitors/update PATCH /api/v1/monitors/{id} Updates an existing monitor Requires `monitors:read_write` permission. Only include the fields you want to change. Monitor ID (UUID) Monitor name (1–255 characters) Type-specific configuration. See [Monitors](/monitors) for fields per type. Check interval in seconds (minimum: 30) Timeout in milliseconds (range: 1000–60000) Minutes of consecutive failures before marking down Minutes of consecutive successes before marking recovered Whether the monitor is active Replace the linked alert channels. Pass all channel IDs you want linked — this is a full replacement, not an append. ```json 200 theme={null} { "data": { "id": "550e8400-e29b-41d4-a716-446655440000", "name": "Production site", "check_type": "http", "enabled": true, "interval_seconds": 60, "timeout_ms": 10000, "confirm_down_minutes": 1, "confirm_up_minutes": 3, "config": { "url": "https://example.com", "method": "GET", "expected_status_codes": [200], "follow_redirects": true }, "current_state": "up", "alert_channel_ids": ["660e8400-e29b-41d4-a716-446655440000"], "inserted_at": "2025-03-01T12:00:00Z", "updated_at": "2025-03-01T14:30:00Z" } } ``` # Get monitor uptime Source: https://docs.larm.dev/api-reference/monitors/uptime GET /api/v1/monitors/{monitor_id}/uptime Returns uptime percentage and status distribution for a monitor Requires `monitors:read` permission. Uses the **Stats** rate limit bucket (30 req/min). Monitor ID (UUID) Time range. One of: `1h`, `6h`, `24h`, `7d`, `30d`, `90d`. Returns the overall uptime percentage (averaged across probe locations) and a breakdown of check result statuses. ```json 200 theme={null} { "data": { "uptime_pct": 99.95, "distribution": { "pass": 4312, "fail": 2, "error": 0, "timeout": 1, "total": 4315 } } } ``` # Create status page Source: https://docs.larm.dev/api-reference/status-pages/create POST /api/v1/status-pages Creates a new status page Requires `status_pages:read_write` permission. Creates the page itself. To add components and groups, use the [Components](/api-reference/components/create) and [Component groups](/api-reference/component-groups/create) endpoints, or replace the entire structure in one call with [PUT structure](/api-reference/status-pages/structure). Page name (1–255 characters) URL identifier (3–63 characters, lowercase alphanumeric and hyphens; cannot start or end with a hyphen) Brief description (up to 1000 characters) `system`, `light`, or `dark` Brand color in hex format (e.g. `#4F46E5`) URL of the logo to use on light backgrounds URL of the logo to use on dark backgrounds Show a light/dark theme switcher on the public page Whether the page is publicly visible Allow email subscriptions ```json 201 theme={null} { "data": { "id": "550e8400-e29b-41d4-a716-446655440000", "name": "Acme Status", "slug": "acme", "description": "Current status of Acme services", "theme": "system", "primary_color": null, "enabled": true, "subscribers_enabled": false, "custom_domain": null, "domain_status": "none", "logo_light_url": null, "logo_dark_url": null, "url": "https://acme.status.larm.dev", "components": [], "inserted_at": "2025-03-01T12:00:00Z", "updated_at": "2025-03-01T12:00:00Z" } } ``` # Delete status page Source: https://docs.larm.dev/api-reference/status-pages/delete DELETE /api/v1/status-pages/{id} Deletes a status page Requires `status_pages:read_write` permission. Status page ID (UUID) ```json 204 theme={null} ``` # Get status page Source: https://docs.larm.dev/api-reference/status-pages/get GET /api/v1/status-pages/{id} Returns a single status page by ID, with its full components tree Requires `status_pages:read` permission. Status page ID (UUID) The `components` field is a polymorphic tree of `group` and `component` entries, ordered by `position`. Groups contain components (groups cannot nest). Ungrouped components appear at the top level. To replace the entire tree, use [PUT structure](/api-reference/status-pages/structure). For individual CRUD on components and groups, see the [Components](/api-reference/components/get) and [Component groups](/api-reference/component-groups/get) endpoints. ```json 200 theme={null} { "data": { "id": "550e8400-e29b-41d4-a716-446655440000", "name": "Acme Status", "slug": "acme", "description": "Current status of Acme services", "theme": "system", "primary_color": "#4F46E5", "enabled": true, "subscribers_enabled": true, "custom_domain": null, "domain_status": "none", "logo_light_url": null, "logo_dark_url": null, "url": "https://acme.status.larm.dev", "components": [ { "type": "group", "id": "880e8400-e29b-41d4-a716-446655440000", "name": "Backend", "position": 0, "components": [ { "type": "component", "id": "770e8400-e29b-41d4-a716-446655440000", "name": "API", "description": "REST API", "position": 0, "monitors": [ { "monitor_id": "660e8400-e29b-41d4-a716-446655440000", "down_status": "major_outage" } ], "inserted_at": "2025-03-01T12:00:00Z", "updated_at": "2025-03-01T12:00:00Z" } ], "inserted_at": "2025-03-01T12:00:00Z", "updated_at": "2025-03-01T12:00:00Z" }, { "type": "component", "id": "990e8400-e29b-41d4-a716-446655440000", "name": "Marketing site", "description": null, "position": 1, "monitors": [], "inserted_at": "2025-03-01T12:00:00Z", "updated_at": "2025-03-01T12:00:00Z" } ], "inserted_at": "2025-03-01T12:00:00Z", "updated_at": "2025-03-01T12:00:00Z" } } ``` # List status pages Source: https://docs.larm.dev/api-reference/status-pages/list GET /api/v1/status-pages Returns all status pages in the organization Requires `status_pages:read` permission. Returns a summary of each status page. The components tree is **not** included in the list response — use [Get status page](/api-reference/status-pages/get) to fetch a single page with its full structure. ```json 200 theme={null} { "data": [ { "id": "550e8400-e29b-41d4-a716-446655440000", "name": "Acme Status", "slug": "acme", "description": "Current status of Acme services", "theme": "system", "primary_color": "#4F46E5", "enabled": true, "subscribers_enabled": true, "custom_domain": null, "domain_status": "none", "logo_light_url": null, "logo_dark_url": null, "url": "https://acme.status.larm.dev", "inserted_at": "2025-03-01T12:00:00Z", "updated_at": "2025-03-01T12:00:00Z" } ] } ``` # Replace status page structure Source: https://docs.larm.dev/api-reference/status-pages/structure PUT /api/v1/status-pages/{id}/structure Atomically replaces the entire components-and-groups tree of a status page Requires `status_pages:read_write` permission. Replaces the page's full structure in a single transaction: creates new entries (omit `id`), updates existing entries by `id`, and deletes any entry not present in the body. Order is taken from the array (0-based position). Status page ID (UUID) Polymorphic tree of `group` and `component` entries. Groups contain components (groups cannot nest). Ungrouped components appear at the top level. ### Entry shapes **Group** | Field | Type | Notes | | ------------ | --------- | ------------------------------------------------------------- | | `type` | string | Must be `"group"` | | `id` | string | Omit to create a new group; provide to update an existing one | | `name` | string | Required | | `components` | object\[] | Components inside this group | **Component** | Field | Type | Notes | | ------------- | --------- | ------------------------------------------------------------------------------------------------------------------- | | `type` | string | Must be `"component"` | | `id` | string | Omit to create a new component; provide to update an existing one | | `name` | string | Required | | `description` | string | Optional | | `monitors` | object\[] | Each entry has `monitor_id` (UUID) and `down_status` (`degraded_performance` \| `partial_outage` \| `major_outage`) | ### Errors | Status | Reason | | ------ | ------------------------------------------------------------------------------------------------------- | | 404 | Status page not found | | 422 | Body is missing `components`, an entry has an invalid `type`, or a group is nested inside another group | ```json 200 theme={null} { "data": { "id": "550e8400-e29b-41d4-a716-446655440000", "name": "Acme Status", "slug": "acme", "components": [ { "type": "group", "id": "880e8400-e29b-41d4-a716-446655440000", "name": "Backend", "position": 0, "components": [ { "type": "component", "id": "770e8400-e29b-41d4-a716-446655440000", "name": "API", "description": null, "position": 0, "monitors": [ { "monitor_id": "660e8400-e29b-41d4-a716-446655440000", "down_status": "major_outage" } ], "inserted_at": "2025-03-01T12:00:00Z", "updated_at": "2025-03-01T12:00:00Z" } ], "inserted_at": "2025-03-01T12:00:00Z", "updated_at": "2025-03-01T12:00:00Z" } ], "inserted_at": "2025-03-01T12:00:00Z", "updated_at": "2025-03-01T14:30:00Z" } } ``` # Update status page Source: https://docs.larm.dev/api-reference/status-pages/update PATCH /api/v1/status-pages/{id} Updates an existing status page Requires `status_pages:read_write` permission. Only include the fields you want to change. Updates only the page's own fields. To modify components and groups, use the dedicated CRUD endpoints or replace the entire structure with [PUT structure](/api-reference/status-pages/structure). To attach a custom domain, use the custom-domain endpoint (separate from this one). Status page ID (UUID) Page name (1–255 characters) URL identifier (3–63 characters, lowercase alphanumeric and hyphens; cannot start or end with a hyphen) Brief description (up to 1000 characters) `system`, `light`, or `dark` Brand color in hex format (e.g. `#4F46E5`) URL of the logo to use on light backgrounds URL of the logo to use on dark backgrounds Show a light/dark theme switcher on the public page Whether the page is publicly visible Allow email subscriptions ```json 200 theme={null} { "data": { "id": "550e8400-e29b-41d4-a716-446655440000", "name": "Acme Status", "slug": "acme", "description": "Current status of Acme services", "theme": "dark", "primary_color": "#4F46E5", "enabled": true, "subscribers_enabled": true, "custom_domain": null, "domain_status": "none", "logo_light_url": null, "logo_dark_url": null, "url": "https://acme.status.larm.dev", "components": [], "inserted_at": "2025-03-01T12:00:00Z", "updated_at": "2025-03-01T14:30:00Z" } } ``` # Create webhook subscription Source: https://docs.larm.dev/api-reference/webhooks/create POST /api/v1/webhooks Creates a new webhook subscription Requires `monitors:read_write` permission. HTTPS endpoint URL to receive webhook events Events to subscribe to. At least one required. Valid values: `monitor.state_changed`, `monitor.created`, `monitor.updated`, `monitor.deleted`. Whether the subscription is active The response includes the signing `secret` — **this is only shown once**. Larm sends an `x-larm-signature-256` header on every delivery with the value `sha256=`, where `` is the lowercase HMAC-SHA256 of the raw JSON body using your secret as the key. ```json 201 theme={null} { "data": { "id": "550e8400-e29b-41d4-a716-446655440000", "url": "https://example.com/webhooks/larm", "events": ["monitor.state_changed", "monitor.created"], "enabled": true, "secret": "a1b2c3d4e5f6...", "inserted_at": "2025-03-01T12:00:00Z", "updated_at": "2025-03-01T12:00:00Z" } } ``` # Delete webhook subscription Source: https://docs.larm.dev/api-reference/webhooks/delete DELETE /api/v1/webhooks/{id} Deletes a webhook subscription Requires `monitors:read_write` permission. Webhook subscription ID (UUID) ```json 204 theme={null} ``` # Get webhook subscription Source: https://docs.larm.dev/api-reference/webhooks/get GET /api/v1/webhooks/{id} Returns a single webhook subscription by ID Requires `monitors:read` permission. Webhook subscription ID (UUID) ```json 200 theme={null} { "data": { "id": "550e8400-e29b-41d4-a716-446655440000", "url": "https://example.com/webhooks/larm", "events": ["monitor.state_changed", "monitor.created"], "enabled": true, "inserted_at": "2025-03-01T12:00:00Z", "updated_at": "2025-03-01T12:00:00Z" } } ``` # List webhook subscriptions Source: https://docs.larm.dev/api-reference/webhooks/list GET /api/v1/webhooks Returns all webhook subscriptions in the organization Requires `monitors:read` permission. ```json 200 theme={null} { "data": [ { "id": "550e8400-e29b-41d4-a716-446655440000", "url": "https://example.com/webhooks/larm", "events": ["monitor.state_changed", "monitor.created"], "enabled": true, "inserted_at": "2025-03-01T12:00:00Z", "updated_at": "2025-03-01T12:00:00Z" } ] } ``` # Update webhook subscription Source: https://docs.larm.dev/api-reference/webhooks/update PATCH /api/v1/webhooks/{id} Updates an existing webhook subscription Requires `monitors:read_write` permission. Only include the fields you want to change. Webhook subscription ID (UUID) HTTPS endpoint URL to receive webhook events Events to subscribe to. Valid values: `monitor.state_changed`, `monitor.created`, `monitor.updated`, `monitor.deleted`. Whether the subscription is active ```json 200 theme={null} { "data": { "id": "550e8400-e29b-41d4-a716-446655440000", "url": "https://example.com/webhooks/larm", "events": ["monitor.state_changed"], "enabled": false, "inserted_at": "2025-03-01T12:00:00Z", "updated_at": "2025-03-01T14:30:00Z" } } ``` # CLI Source: https://docs.larm.dev/guides/cli Manage Larm from your terminal with the official CLI The Larm CLI lets you manage monitors, alerts, status pages, disruptions, and webhooks from your terminal. Open source at [github.com/larmhq/larm-cli](https://github.com/larmhq/larm-cli). ## Install ```bash theme={null} brew install larmhq/tap/larm ``` Download from [GitHub Releases](https://github.com/larmhq/larm-cli/releases). ```bash theme={null} go install github.com/larmhq/larm-cli@latest ``` ## Authenticate ### Browser login (recommended) ```bash theme={null} larm auth login ``` Opens your browser for OAuth. Enter the code shown in your terminal, pick your organization, and approve. ### API key ```bash theme={null} larm auth login --with-token ``` Paste an API key from [Settings > API Keys](https://app.larm.dev/settings/api-keys). Or set the `LARM_API_KEY` environment variable. ## Usage ### Monitors ```bash theme={null} larm monitors list larm monitors show larm monitors create --name "API" --url https://example.com larm monitors update --name "New Name" larm monitors delete ``` ### Monitor stats ```bash theme={null} larm monitors state larm monitors uptime --range 7d larm monitors response-times larm monitors cert ``` ### Alert channels ```bash theme={null} larm alerts list larm alerts show larm alerts create --name "Slack" --type slack --config '{"webhook_url":"..."}' ``` ### Status pages ```bash theme={null} larm status-pages list larm status-pages show # renders the components tree larm status-pages create --name "Acme Status" --slug acme-status ``` ### Components and groups ```bash theme={null} larm components create --status-page-id --name "API" larm components create --status-page-id --name "Database" --group larm components update --group larm component-groups create --status-page-id --name "Backend" larm component-groups show larm component-groups update --name "Backend services" larm component-groups delete ``` ### Disruptions ```bash theme={null} larm disruptions list larm disruptions show larm disruptions create --title "API outage" --impact critical --message "Investigating" larm disruptions update --status resolved ``` ### Webhooks ```bash theme={null} larm webhooks list larm webhooks create --url https://example.com/hook --events monitor.state_changed ``` ### Raw API access ```bash theme={null} larm api GET /monitors larm api GET /monitors --field check_type=http larm api POST /monitors --field name=Test --field check_type=http ``` ## Output formats Table output in a terminal, JSON when piped. ```bash theme={null} larm monitors list # table larm monitors list --output json # JSON larm monitors list --output json --jq '.[].name' # JQ filter larm monitors list --fields name,check_type # select columns ``` ## Other flags | Flag | Description | | --------------- | -------------------------------------- | | `--quiet` | Suppress output on success | | `--dry-run` | Print request without sending | | `--yes` | Skip delete confirmation prompts | | `--output json` | Force JSON output | | `--fields` | Select columns for table output | | `--jq` | Filter JSON output with JQ expressions | ## For LLM agents The CLI has a `describe` command for machine discovery: ```bash theme={null} larm describe # full command schema as JSON larm describe monitors.list # single command schema ``` Always use `--output json` for machine-readable output. ## Source The CLI is open source: [github.com/larmhq/larm-cli](https://github.com/larmhq/larm-cli) # Connect to Make Source: https://docs.larm.dev/guides/connect-to-make Send Larm alerts to Make for workflow automation Make (formerly Integromat) can receive Larm alerts via the webhook alert channel using a Custom Webhook module. ## Setup ### 1. Create a scenario with a Custom Webhook In Make, create a new scenario. Add a **Webhooks** → **Custom webhook** module as the trigger. Click **Add** to create a new webhook, give it a name, and copy the URL. ### 2. Create a webhook alert channel in Larm In Larm, go to **Alert channels** and click **New alert channel**. Select **Webhook** as the type and paste the Make webhook URL. ### 3. Set a custom payload template Set a structured payload template so Make can parse each field individually: ```json theme={null} { "event": "{{event}}", "status": "{{status}}", "monitor_name": "{{monitor_name}}", "monitor_url": "{{monitor_url}}", "timestamp": "{{timestamp}}", "last_error": "{{last_error}}", "downtime_duration": "{{downtime_duration}}" } ``` See [Webhooks](/webhooks#template-variables) for all available variables. ### 4. Determine data structure In Make, click **Determine data structure** on the Custom Webhook module. Then in Larm, click **Send test** on the alert channel. Make will receive the test event and learn the payload structure automatically. ### 5. Add downstream modules Add modules after the webhook trigger to process the alert. ## Example: Log alerts to Google Sheets 1. Follow the setup above to create the webhook trigger 2. Add a **Google Sheets** → **Add a Row** module 3. Connect your Google account and select a spreadsheet 4. Map columns to webhook fields: * **A**: `timestamp` * **B**: `monitor_name` * **C**: `status` * **D**: `monitor_url` * **E**: `last_error` 5. Turn on the scenario Every Larm alert will be logged as a new row in your spreadsheet. # Connect to n8n Source: https://docs.larm.dev/guides/connect-to-n8n Send Larm alerts to n8n for workflow automation n8n can receive Larm alerts via the webhook alert channel using a Webhook trigger node. ## Setup ### 1. Add a Webhook node in n8n Create a new workflow in n8n. Add a **Webhook** node as the trigger. Set the HTTP method to **POST**. Copy the **production URL** (not the test URL). It looks like `https://your-n8n.example.com/webhook/...`. n8n has separate test and production URLs. Use the production URL in Larm — the test URL only works while the workflow editor is open. ### 2. Create a webhook alert channel in Larm In Larm, go to **Alert channels** and click **New alert channel**. Select **Webhook** as the type and paste the n8n production URL. ### 3. Set a custom payload template Set a structured payload template so each field is available as a separate property in n8n: ```json theme={null} { "event": "{{event}}", "status": "{{status}}", "monitor_name": "{{monitor_name}}", "monitor_url": "{{monitor_url}}", "timestamp": "{{timestamp}}", "last_error": "{{last_error}}", "downtime_duration": "{{downtime_duration}}" } ``` See [Webhooks](/webhooks#template-variables) for all available variables. ### 4. Send a test alert Activate the workflow in n8n, then click **Send test** on the alert channel in Larm. Check the n8n execution log to confirm the event was received. ### 5. Add downstream nodes Add nodes after the Webhook trigger to process the alert — send a message, create a ticket, update a spreadsheet, or anything else n8n supports. ## Example: Create a Jira ticket when a monitor goes down 1. Follow the setup above to create the Webhook trigger 2. Add an **If** node: check that `event` equals `monitor_down` 3. Add a **Jira** node on the true branch: **Create Issue** 4. Map the fields: * **Summary**: `[DOWN] {{monitor_name}}` * **Description**: `{{monitor_url}} went down at {{timestamp}}. Error: {{last_error}}` 5. Activate the workflow Larm will create a Jira ticket each time a monitor goes down. # Connect to Zapier Source: https://docs.larm.dev/guides/connect-to-zapier Send Larm alerts to Zapier for workflow automation Zapier can receive Larm alerts via the webhook alert channel. No custom Zapier app needed — use the built-in "Webhooks by Zapier" trigger. ## Setup ### 1. Create a Zap In Zapier, create a new Zap. For the trigger, choose **Webhooks by Zapier** and select **Catch Hook**. Click **Continue** — no filtering needed. Copy the webhook URL Zapier gives you (starts with `https://hooks.zapier.com/`). ### 2. Create a webhook alert channel in Larm In Larm, go to **Alert channels** and click **New alert channel**. Select **Webhook** as the type and paste the Zapier URL. ### 3. Set a custom payload template The default payload puts everything in a single `text` field, which is hard to work with in Zapier. Set a custom payload template so each field is available separately: ```json theme={null} { "event": "{{event}}", "status": "{{status}}", "monitor_name": "{{monitor_name}}", "monitor_url": "{{monitor_url}}", "timestamp": "{{timestamp}}", "last_error": "{{last_error}}", "downtime_duration": "{{downtime_duration}}" } ``` See [Webhooks](/webhooks#template-variables) for all available variables. ### 4. Send a test alert Click **Send test** on the alert channel in Larm. Then go back to Zapier and click **Test trigger** — it should pick up the test event and show the fields. ### 5. Add an action Configure your Zap's action step. You can map the individual fields (e.g. `monitor_name`, `status`) to your action's inputs. ## Example: Send alerts to a Slack channel 1. Follow the setup above to create the Zapier trigger 2. Add an action: **Slack** → **Send Channel Message** 3. Map the fields: * **Channel**: pick your alerts channel * **Message Text**: `{{monitor_name}} is {{status}} — {{monitor_url}}` 4. Turn on the Zap Every Larm alert will now post to your Slack channel through Zapier, where you can add formatting, filters, or additional actions. # Connect via MCP Source: https://docs.larm.dev/guides/mcp Use Larm from Claude Code, Cursor, or any MCP-compatible AI tool Larm has a built-in [MCP](https://modelcontextprotocol.io) server that lets AI tools manage your monitors, check uptime, create disruptions, and set up alerts — all through natural language. Available on all plans, including Free. ## Claude Code Run this command in your terminal: ```bash theme={null} claude mcp add larm --transport http https://app.larm.dev/mcp ``` Or add it to your project's `.mcp.json`: ```json theme={null} { "mcpServers": { "larm": { "type": "http", "url": "https://app.larm.dev/mcp" } } } ``` ## Claude Desktop Open **Settings > Developer > Edit Config** and add: ```json theme={null} { "mcpServers": { "larm": { "type": "http", "url": "https://app.larm.dev/mcp" } } } ``` ## Cursor Open **Settings > MCP Servers** and add a new server: * **Name:** `larm` * **Type:** `http` * **URL:** `https://app.larm.dev/mcp` Or add to your project's `.cursor/mcp.json`: ```json theme={null} { "mcpServers": { "larm": { "type": "http", "url": "https://app.larm.dev/mcp" } } } ``` ## VS Code Add to your project's `.vscode/mcp.json`: ```json theme={null} { "servers": { "larm": { "type": "http", "url": "https://app.larm.dev/mcp" } } } ``` VS Code uses `servers` as the root key, not `mcpServers`. MCP tools work in Copilot's Agent mode. ## Authentication The first time you use a Larm tool, your MCP client will open a browser window: 1. Log in with your Larm account (email, GitHub, or Google) 2. Approve the authorization request — "Full access to your Larm account" 3. Return to your editor — the connection is ready Tokens refresh automatically. You won't need to authorize again unless you revoke access. ## Available tools ### Read | Tool | Description | | ------------------------ | ------------------------------------------------------ | | `list_monitors` | List all monitors with their current state | | `get_monitor` | Full details: config, state, uptime %, p95, error rate | | `get_uptime_summary` | Fleet-wide uptime, disruption count, and MTTR | | `list_alert_channels` | All configured alert channels | | `list_state_transitions` | Monitor state changes in the last 24 hours | ### Write | Tool | Description | | ---------------------- | -------------------------------------------------------- | | `create_monitor` | Create a new HTTP monitor | | `update_monitor` | Change URL, interval, timeout, or enable/disable | | `create_alert_channel` | Create a webhook, email, Discord, or other channel | | `test_alert_channel` | Send a test notification | | `list_disruptions` | List status page disruptions | | `create_disruption` | Create a disruption, optionally publish to a status page | | `update_disruption` | Post updates, advance status, or resolve | ## Examples Ask your AI tool: * "What's the uptime of my monitors this week?" * "Create a monitor for [https://api.example.com/health](https://api.example.com/health)" * "Set up a Discord webhook for alerts" * "Create a disruption — the database is down — and publish it to the production status page" * "Resolve the database disruption" * "Pause the staging monitor" ## Rate limits 60 requests per minute per token. If you hit the limit, wait 60 seconds. # Introduction Source: https://docs.larm.dev/index Monitoring for engineering teams [Larm](https://larm.dev) is an uptime monitoring platform that checks your websites, APIs, and services from multiple global locations, detects outages using multi-probe voting to eliminate false positives, and alerts your team through the channels you already use. ## Get started Set up your first monitor, alert channels, and status page. Authenticate and interact with the Larm API. HTTP, TCP, DNS, and heartbeat monitor types. Slack, PagerDuty, email, webhooks, and more. # Monitors Source: https://docs.larm.dev/monitors Monitor types and configuration options Larm supports five monitor types. Each type has its own configuration, but they all share common settings for check intervals, timeouts, and disruption confirmation. ## Common settings These settings apply to all monitor types. | Setting | Default | Description | | ------------------ | ------- | ---------------------------------------------------------------------------------------- | | **Check interval** | 3 min | How often to run the check (minimum varies by plan: 3 min Free, 1 min Pro, 30s Business) | | **Timeout** | 10s | How long to wait for a response (1s–60s) | | **Confirm down** | 1 min | Minutes the monitor must stay failing before being marked down | | **Confirm up** | 3 min | Minutes the monitor must stay passing before being marked recovered | Confirmation windows help smooth out brief interruptions. Set **Confirm down** to a few minutes if you want to avoid alerts for momentary blips. ## HTTP Checks a URL and validates the response status code, headers, and body content. | Field | Description | | ------------------------- | --------------------------------------------------------------------- | | **URL** | The URL to check (http or https) | | **Method** | HTTP method (GET, POST, HEAD, etc.) | | **Expected status codes** | Status codes that count as healthy (e.g. 200, 301) | | **Follow redirects** | Whether to follow HTTP redirects | | **Headers** | Custom request headers (up to 20, each value up to 8KB) | | **Body** | Request body for POST/PUT/PATCH (up to 64KB) | | **Expected keyword** | A string that must appear in the response body (up to 1000 bytes) | | **Unexpected keyword** | A string that must not appear in the response body (up to 1000 bytes) | Larm checks your URL from multiple global locations simultaneously and uses majority voting to confirm the result — a single probe failure won't trigger a false alert. ## TCP Checks that a host is accepting TCP connections on a given port. | Field | Description | | -------- | ---------------------- | | **Host** | Hostname or IP address | | **Port** | TCP port number | Use this for databases, mail servers, game servers, or any service that listens on a TCP port. ## DNS Checks that a DNS record resolves to the expected values. | Field | Description | | -------------------- | ----------------------------------------------- | | **Host** | The domain to query | | **Record type** | DNS record type (A, AAAA, CNAME, MX, TXT, etc.) | | **Nameserver** | IP address of the nameserver to query | | **Expected records** | Values the DNS response should contain | Use this to verify DNS propagation, detect hijacking, or monitor record changes. ## Heartbeat Expects a periodic HTTP ping. If the ping stops arriving, the monitor goes down. | Field | Description | | ---------------------- | ------------------------------------------------------------- | | **Expected interval** | How often the ping should arrive (10s to 24h, plan-dependent) | | **Consecutive misses** | Number of missed intervals before alerting (default 2) | When you create a heartbeat monitor, you get a unique token and URL. Ping it from your cron jobs, scheduled tasks, or background workers: ```bash theme={null} curl https://app.larm.dev/api/heartbeat/YOUR_TOKEN ``` See the [heartbeat API reference](/api-reference/heartbeat) for details. ## Synthetic Synthetic monitoring is available on Pro and Business plans. Runs a Playwright browser script against your application. Use this for testing login flows, checkout processes, or any user journey that can't be verified with a simple HTTP request. | Field | Description | | ---------------------- | -------------------------------------------------------------------- | | **Script** | Playwright script to execute (up to 64KB) | | **Interval** | How often to run the check (minimum 5 min on Pro, 3 min on Business) | | **Confirm down after** | Consecutive failures before marking as down (default 3) | | **Confirm up after** | Consecutive passes before marking as recovered (default 1) | Synthetic monitors use count-based confirmation instead of time-based. A `confirm_down_after` of 3 means three consecutive failing checks before we alert you. This prevents flaky scripts or transient runner issues from triggering false alerts. # Plan limits Source: https://docs.larm.dev/plan-limits Technical limits for each plan ## Monitors | Limit | Free | Pro | Business | | -------------------------- | ------ | --------- | --------- | | **Monitors** | 15 | 100 | 500 | | **Min check interval** | 3 min | 1 min | 30 sec | | **Min heartbeat interval** | 60 sec | 30 sec | 10 sec | | **Min synthetic interval** | 5 min | 5 min | 3 min | | **Synthetic monitors** | 1 | Unlimited | Unlimited | ## Team | Limit | Free | Pro | Business | | -------------------- | ---- | --- | --------- | | **Team seats** | 1 | 10 | Unlimited | | **API write access** | Yes | Yes | Yes | ## Alerting | Limit | Free | Pro | Business | | -------------------------------- | ---- | ----- | --------- | | **Alert channels** | 10 | 25 | Unlimited | | **Daily alert limit** | 100 | 1,000 | Unlimited | | **SMS alerts** | No | Yes | Yes | | **SMS monthly cap** | — | 125 | 500 | | **SMS daily cap** | — | 20 | 60 | | **SMS hourly cap** | — | 5 | 15 | | **Daily email limit** | 50 | 500 | Unlimited | | **Email recipients per channel** | 1 | 5 | Unlimited | ## Status pages | Limit | Free | Pro | Business | | ------------------------- | ---- | --- | --------- | | **Status pages** | 1 | 3 | Unlimited | | **Components per page** | 5 | 25 | Unlimited | | **Custom domains** | No | Yes | Yes | | **Webhook subscriptions** | 0 | 10 | Unlimited | # Quickstart Source: https://docs.larm.dev/quickstart Set up monitoring in under five minutes ## 1. Sign up Create an account at [app.larm.dev](https://app.larm.dev). You can sign up with your email, GitHub, or Google. Email sign-ups get a confirmation link — click it to sign in. ## 2. Create a monitor Go to **Monitors** and click **New monitor**. The quickest way to start is with an HTTP monitor — enter a URL and Larm will check it from multiple global locations, using majority voting to confirm outages. See [Monitors](/monitors) for all monitor types (HTTP, TCP, DNS, Heartbeat) and configuration options. ## 3. Set up alert channels Go to **Alert channels** and click **New alert channel**. Larm integrates with Slack, PagerDuty, email, and [many more](/alert-channels). You can send a test notification to verify the configuration works. Each monitor can be linked to one or more channels. See [Alert channels](/alert-channels) for all channel types and configuration details. ## 4. Create a status page Go to **Status pages** and click **New status page**. Pick the monitors to display, choose a subdomain (`yourname.status.larm.dev`), and optionally connect a custom domain. Status pages are static HTML hosted on a global CDN — they stay up even if Larm itself has issues. # Status pages Source: https://docs.larm.dev/status-pages Public status pages for your services Status pages let your users see what's going on. Each page shows the current state of your components, active disruptions with their update timeline, and 90 days of uptime history. Pages are static HTML hosted on a global CDN. Every time a disruption is updated or a component changes state, the page is regenerated and pushed to edge nodes worldwide. It stays up even if Larm itself has issues. ## How status pages work Your status page is a view of your disruptions. When you create a disruption and post an update that affects a status page component, the page re-renders with the new state. When you resolve the disruption, the component goes back to operational and the disruption moves to the history section. **With monitors:** Monitors create disruptions automatically. If a status page component is linked to a monitor, the whole flow is hands-free — outage detected, disruption created, status page updated, subscribers notified, and resolved when the monitor recovers. **Without monitors:** Create disruptions yourself, post updates, choose which components are affected. You're in control of the timing and the messaging. You can also hit the **Post update** button directly on a status page to create a disruption in one step — it's a shortcut into the same disruption workflow. ## Creating a status page Go to **Status pages** and click **New status page**. Configure the settings, add components, and optionally customize the branding. Your page is published at `https://.status.larm.dev`. ## Page settings | Field | Description | | ----------------- | --------------------------------------------------------------------------------------------------------------------- | | **Name** | Display name of the status page | | **Slug** | URL identifier (e.g. `my-service` becomes `my-service.status.larm.dev`). Lowercase, hyphens allowed, 3–63 characters. | | **Description** | Optional brief description shown on the page (up to 1000 characters) | | **Theme** | System (follows visitor's preference), Light, or Dark | | **Primary color** | Brand color in hex format (e.g. `#4F46E5`) | | **Logo (light)** | Logo shown in light mode (PNG, JPG, or SVG, up to 1 MB) | | **Logo (dark)** | Logo shown in dark mode (PNG, JPG, or SVG, up to 1 MB) | | **Enabled** | Whether the page is publicly visible (defaults to disabled) | ## Components Components are the services or systems shown on your status page — "API", "Dashboard", "Payment processing", whatever makes sense for your users. Each component has a name, optional description, and a display position. A component can be linked to monitors for automatic updates, or left standalone. ### Component states | State | Meaning | | ------------------------ | ----------------------------------------- | | **Operational** | Everything is working normally | | **Degraded performance** | Slower than expected but still functional | | **Partial outage** | Some functionality is unavailable | | **Major outage** | Service is down | | **Under maintenance** | Planned maintenance in progress | Component state is set by disruptions. When a disruption update marks a component as "major outage", that's what your users see on the status page until the disruption is resolved or a newer update changes it. ## Custom domains Custom domains are available on paid plans. Serve your status page from your own domain (e.g. `status.example.com`). Apex domains are not supported — use a subdomain. 1. Enter your domain in the status page settings 2. Add a CNAME record pointing your domain to `.status.larm.dev` 3. If you're using Cloudflare, also add a TXT record: `_larm-verify.` with value `larm-verify=` (shown in the dashboard) 4. Click **Verify** — Larm checks DNS and provisions SSL automatically ## Email subscribers Visitors can subscribe to your status page by email. When a disruption is updated, subscribers are notified automatically. | Plan | Subscriber limit | | -------- | ---------------- | | Free | 100 | | Pro | 1,000 | | Business | 10,000 | # Webhooks Source: https://docs.larm.dev/webhooks Payload format, template variables, and signature verification The webhook alert channel POSTs a JSON payload to any HTTPS URL when a monitor changes state. This page covers the payload format, available template variables, and how to verify webhook signatures. For setup instructions, see [Alert channels — Webhook](/alert-channels#webhook). This page documents the **webhook alert channel** — an alerting integration that sends notifications when monitors go down or recover. Larm also has **webhook subscriptions**, a separate API feature that delivers events (monitor created, updated, deleted, state changed) to your endpoints. Both flows use the same `x-larm-signature-256` header format. See the [webhook subscriptions API reference](/api-reference/webhooks/list) for that surface. ## Events | Event | Description | | ------------------- | ------------------------------------------- | | `monitor_down` | A monitor has been confirmed down | | `monitor_recovered` | A monitor is back up | | `cert_expiring` | An SSL certificate is nearing expiry | | `test` | A manual test alert sent from the dashboard | ## Default payload Without a custom template, Larm sends: ```json theme={null} { "text": "{{monitor_name}} is {{status}}.{{last_error}}{{downtime_duration}}\nURL: {{monitor_url}}\nTime: {{timestamp}}" } ``` Which produces something like: ```json theme={null} { "text": "My API is down. Connection timeout\nURL: https://api.example.com\nTime: 2024-01-15 14:30:45 UTC" } ``` This is a single `text` field. If you need structured data (e.g. for automation platforms), use a custom payload template. ## Template variables Variables use `{{variable}}` syntax. Unknown variables are replaced with an empty string. | Variable | Description | Availability | | ------------------- | ------------------------------------------------------------------------- | ------------------------ | | `event` | Event type (`monitor_down`, `monitor_recovered`, `cert_expiring`, `test`) | All events | | `status` | Status string (`down`, `up`, `warning`, `test`) | All events | | `monitor_id` | Monitor UUID | All events | | `monitor_name` | Monitor name | All events | | `monitor_url` | URL or host from monitor config | All events | | `channel_name` | Alert channel name | All events | | `timestamp` | Timestamp in `2024-01-15 14:30:45 UTC` format | All events | | `last_error` | Error message (prefixed with a space) | `monitor_down` only | | `downtime_duration` | e.g. `" Was down for 5m 30s."` (prefixed with a space) | `monitor_recovered` only | | `cert_expiry_date` | Certificate expiry date in `2024-12-31` format | `cert_expiring` only | | `days_remaining` | Days until certificate expiry (as string) | `cert_expiring` only | `last_error` and `downtime_duration` include a leading space so they read naturally in the default template. When using a custom template, you may want to trim them. ## Custom payload templates Set a custom payload template in the alert channel config to control the JSON structure. The template must be valid JSON with `{{variable}}` placeholders. Recommended template for automation platforms: ```json theme={null} { "event": "{{event}}", "status": "{{status}}", "monitor_id": "{{monitor_id}}", "monitor_name": "{{monitor_name}}", "monitor_url": "{{monitor_url}}", "channel_name": "{{channel_name}}", "timestamp": "{{timestamp}}", "last_error": "{{last_error}}", "downtime_duration": "{{downtime_duration}}", "cert_expiry_date": "{{cert_expiry_date}}", "days_remaining": "{{days_remaining}}" } ``` Event-specific variables are empty strings when not applicable. ## Signature verification If you set a signing secret on the alert channel, Larm includes an `x-larm-signature-256` header with each request. The value is `sha256=` followed by the hex-encoded HMAC-SHA256 of the raw JSON body using your signing secret as the key. ### Node.js ```js theme={null} const crypto = require("crypto"); function verifySignature(body, secret, signatureHeader) { const expected = "sha256=" + crypto.createHmac("sha256", secret).update(body).digest("hex"); return crypto.timingSafeEqual( Buffer.from(expected), Buffer.from(signatureHeader) ); } // In your request handler: const signature = req.headers["x-larm-signature-256"]; const isValid = verifySignature(req.rawBody, process.env.LARM_SECRET, signature); ``` ### Python ```python theme={null} import hashlib import hmac def verify_signature(body: bytes, secret: str, signature_header: str) -> bool: expected = "sha256=" + hmac.new( secret.encode(), body, hashlib.sha256 ).hexdigest() return hmac.compare_digest(expected, signature_header) # In your request handler: signature = request.headers.get("x-larm-signature-256") is_valid = verify_signature(request.body, os.environ["LARM_SECRET"], signature) ``` ### curl To compute the expected signature for testing: ```bash theme={null} echo -n '{"event":"test"}' | openssl dgst -sha256 -hmac "your-secret" | awk '{print "sha256="$2}' ``` ## Headers Every webhook request includes: | Header | Value | | ---------------------- | ---------------------------------------------- | | `content-type` | `application/json` | | `user-agent` | `Larm/1.0` | | `x-larm-signature-256` | `sha256={hex}` (only if signing secret is set) | Custom headers set in the alert channel config are included as-is. ## Retries Delivery is attempted up to 3 times with exponential backoff. A `401` or `403` response is treated as a permanent failure — the delivery is not retried and the alert channel is automatically disabled. You'll receive an email notification and can re-enable the channel from the dashboard after fixing the issue.