REST API
Manage the same resources you manage in the app — uptime and cron monitors, groups, notification channels, integrations, status pages, and incidents — over a JSON HTTP API.
Every endpoint lives under the /api/v1 prefix and is authenticated by an organization-scoped API key. The
MCP server
uses the same keys and runs the same operations, so anything you can do here you can also do from an AI assistant.
Authentication
An organization owner creates an API key under Administration → API keys. The full token (it starts with wc_) is shown once, at creation time — store it securely, it cannot be displayed again. Send it as a bearer token on every request:
curl https://watchcat.io/api/v1/service_monitors \ -H "Authorization: Bearer wc_your_token_here"
A missing, unknown, or revoked token returns 401. Keys only ever see their own organization's data; a resource that belongs to another organization responds as if it does not exist.
Scopes
Each key has one of two scopes, chosen when it is created.
GET requests are allowed; any write returns 403.
Conventions
Requests and responses are JSON — send Content-Type: application/json on any request with a body. A successful response wraps its payload in a data key (an array for lists); errors wrap a message in an error key, with a fields map on validation errors.
{ "data": { "id": 1, "name": "Marketing site", "status": "up" } } { "error": { "message": "Url can't be blank", "fields": { "url": ["can't be blank"] } } }
Other conventions:
- Status codes:
200read/update/action,201create,204delete,4xxfor auth, scope, plan, validation, and not-found errors. - On
PATCH, only the fields you send are changed. - Timestamps are ISO 8601 in UTC. Secrets are never returned.
- Plan limits are enforced exactly as in the app — exceeding one returns
403. - The API is not paginated; list endpoints return the full set.
Example — create a monitor
curl -X POST https://watchcat.io/api/v1/service_monitors \ -H "Authorization: Bearer wc_your_token_here" \ -H "Content-Type: application/json" \ -d '{ "url": "https://example.com", "interval_seconds": 300, "group_name": "Public sites" }'
Endpoints
All paths are relative to /api/v1.
Uptime monitors
| GET | /api/v1/service_monitors | List monitors |
| POST | /api/v1/service_monitors | Create a monitor |
| GET | /api/v1/service_monitors/:id | Show a monitor |
| PATCH | /api/v1/service_monitors/:id | Update a monitor |
| DELETE | /api/v1/service_monitors/:id | Delete a monitor |
| POST | /api/v1/service_monitors/:id/pause | Pause |
| POST | /api/v1/service_monitors/:id/resume | Resume |
Writable fields: name, url, interval_seconds, http_method, timeout_seconds, check_ssl, follow_redirects, expected_status_codes, body_must_contain, body_must_not_contain, confirmation_period_seconds, recovery_period_seconds, headers.
name defaults to the URL when omitted. headers is a JSON object. Optional group_name assigns a group by name (created if it does not exist); notification_channel_ids sets the channels — omit it on create to use the organization's auto-assign channels.
Cron monitors
| GET | /api/v1/cron_monitors | List monitors |
| POST | /api/v1/cron_monitors | Create a monitor |
| GET | /api/v1/cron_monitors/:id | Show a monitor |
| PATCH | /api/v1/cron_monitors/:id | Update a monitor |
| DELETE | /api/v1/cron_monitors/:id | Delete a monitor |
| POST | /api/v1/cron_monitors/:id/pause | Pause |
| POST | /api/v1/cron_monitors/:id/resume | Resume |
| POST | /api/v1/cron_monitors/:id/regenerate_token | Issue a new ping token |
Writable fields: name, interval_seconds, grace_seconds, max_runtime_seconds, check_type, allow_overlapping_runs.
interval_seconds has a minimum of 60 (plan minimums apply). check_type is heartbeat or start_end. The same group_name and notification_channel_ids options apply; responses include the ping_token and its ping_path.
Monitor groups
| GET | /api/v1/groups | List groups |
| POST | /api/v1/groups | Create a group |
| PATCH | /api/v1/groups/:id | Rename a group |
| DELETE | /api/v1/groups/:id | Delete a group |
Writable fields: kind, name.
Service and cron groups share these endpoints and are told apart by kind (service or cron). kind is required on writes (as a query or body parameter) because the two id ranges are independent; on the list it is optional. Deleting a group leaves its monitors ungrouped.
Notification channels
| GET | /api/v1/notification_channels | List channels |
| POST | /api/v1/notification_channels | Create a channel |
| GET | /api/v1/notification_channels/:id | Show a channel |
| PATCH | /api/v1/notification_channels/:id | Update a channel |
| DELETE | /api/v1/notification_channels/:id | Delete a channel |
| POST | /api/v1/notification_channels/:id/pause | Pause |
| POST | /api/v1/notification_channels/:id/resume | Resume |
Writable fields: name, email_all_users, send_recovery_alert, auto_assign_to_new_monitors.
Recipients are set with user_ids (organization user ids) and integration_ids. When email_all_users is true, specific users are cleared.
Integrations
| GET | /api/v1/integrations | List integrations |
| POST | /api/v1/integrations | Create an integration |
| GET | /api/v1/integrations/:id | Show an integration |
| PATCH | /api/v1/integrations/:id | Update an integration |
| DELETE | /api/v1/integrations/:id | Delete an integration |
Writable fields: name, provider, webhook_url, bot_token, chat_id, enabled.
provider is one of slack, google_chat, discord, telegram, webhook and is fixed once set. Webhook-style providers take webhook_url; telegram takes bot_token and chat_id. Responses list configured setting names under configured_settings and never include the secret values.
Status pages
| GET | /api/v1/status_pages | List status pages |
| POST | /api/v1/status_pages | Create a status page |
| GET | /api/v1/status_pages/:id | Show a status page |
| PATCH | /api/v1/status_pages/:id | Update a status page |
| DELETE | /api/v1/status_pages/:id | Delete a status page |
Writable fields: name, slug, headline, description, logo_url, accent_color, brand_link_url.
name and headline are required on create; the public slug is derived from the name. service_monitor_ids is an ordered list of uptime monitors to display — pass it on the create request (or a later update) to set the page's monitors in one call, replacing any existing set. Status pages show uptime monitors only.
Status page updates
| GET | /api/v1/status_pages/:status_page_id/incidents | List updates |
| POST | /api/v1/status_pages/:status_page_id/incidents | Post an update |
| PATCH | /api/v1/status_pages/:status_page_id/incidents/:id | Edit an update |
| DELETE | /api/v1/status_pages/:status_page_id/incidents/:id | Delete an update |
Writable fields: title, description, status, started_at.
The manual updates shown on a status page, distinct from automatic monitor incidents. status is investigating, identified, monitoring or resolved; started_at defaults to now.
Incidents
| GET | /api/v1/incidents | List incidents, newest first |
| GET | /api/v1/incidents/:id | Show an incident |
| POST | /api/v1/incidents/:id/resolve | Resolve an open incident |
Automatic downtime and cron alerts. Filter the list with status (open or resolved) and monitor_type (ServiceMonitor or CronMonitor). Incidents normally resolve themselves when the monitor recovers; resolve closes one by hand.
Usage
| GET | /api/v1/usage | Plan, limits, and current usage |
A read-only summary of the organization's plan, its limits, and how many monitors and status pages are in use.
What the API does not cover
- It manages resources and reports incidents and usage. It does not expose individual uptime check results or response-time history.
- It mirrors the app's capabilities and adds nothing beyond them — for example, there is no request-body monitoring.
- There is no pagination yet.
Related
Start monitoring in minutes
Free plan available. No credit card required.