Public API
Use organization-owned API keys to manage monitors, incidents, status pages, maintenance windows and webhook subscriptions from your own systems.
Quick start
Create a key
Open Dashboard → API & webhooks. Give the key a clear name, choose read-only or full access, and set an expiry.
Copy it once
The key starts with
moon_and is shown only once. Store it in a secrets manager, never in browser code or source control.Make a request
curl https://www.moonitor.dev/api/v1/monitors \ -H "X-API-Key: moon_YOUR_KEY"
Note
Authorization: Bearer moon_YOUR_KEY is also accepted. Use one authentication header, not both.
Interactive reference
The complete OpenAPI 3.1 contract, request builder, schemas, examples and responses live in the Scalar API reference. The raw document is available at /openapi.json.
Endpoints
| Method | Path | Purpose |
|---|---|---|
GET | /api/v1/monitors | List monitors |
POST | /api/v1/monitors | Create a monitor |
GET | /api/v1/monitors/{monitorId} | Get a monitor |
PATCH | /api/v1/monitors/{monitorId} | Update a monitor |
DELETE | /api/v1/monitors/{monitorId} | Delete a monitor |
POST | /api/v1/monitors/{monitorId}/pause | Pause a monitor |
POST | /api/v1/monitors/{monitorId}/resume | Resume a monitor |
POST | /api/v1/monitors/{monitorId}/check | Run a monitor now |
GET | /api/v1/incidents | List incidents |
GET | /api/v1/incidents/{incidentId} | Get an incident |
POST | /api/v1/incidents/{incidentId}/acknowledge | Acknowledge an incident |
GET | /api/v1/status-pages | List status pages |
POST | /api/v1/status-pages | Create a status page |
GET | /api/v1/status-pages/{statusPageId} | Get a status page |
PATCH | /api/v1/status-pages/{statusPageId} | Update a status page |
DELETE | /api/v1/status-pages/{statusPageId} | Delete a status page |
GET | /api/v1/maintenance-windows | List maintenance windows |
POST | /api/v1/maintenance-windows | Create a maintenance window |
GET | /api/v1/maintenance-windows/{maintenanceId} | Get a maintenance window |
PATCH | /api/v1/maintenance-windows/{maintenanceId} | Update a maintenance window |
DELETE | /api/v1/maintenance-windows/{maintenanceId} | Delete a maintenance window |
GET | /api/v1/status-incidents | List published incidents |
POST | /api/v1/status-incidents | Publish an incident |
GET | /api/v1/status-incidents/{statusIncidentId} | Get a published incident |
PATCH | /api/v1/status-incidents/{statusIncidentId} | Edit a published incident |
DELETE | /api/v1/status-incidents/{statusIncidentId} | Delete a published incident |
POST | /api/v1/status-incidents/{statusIncidentId}/updates | Post an incident update |
GET | /api/v1/webhook-endpoints | List webhook endpoints |
POST | /api/v1/webhook-endpoints | Create a webhook endpoint |
GET | /api/v1/webhook-endpoints/{endpointId} | Get a webhook endpoint |
PATCH | /api/v1/webhook-endpoints/{endpointId} | Update a webhook endpoint |
DELETE | /api/v1/webhook-endpoints/{endpointId} | Delete a webhook endpoint |
POST | /api/v1/webhook-endpoints/{endpointId}/rotate-secret | Rotate a signing secret |
POST | /api/v1/webhook-endpoints/{endpointId}/test | Send a test event |
GET | /api/v1/webhook-deliveries | List webhook deliveries |
GET | /api/v1/webhook-deliveries/{deliveryId} | Get a delivery and its attempts |
POST | /api/v1/webhook-deliveries/{deliveryId}/retry | Retry a delivery |
Permissions and limits
- Read-only keys can list and fetch every resource, but cannot mutate anything.
- Full-access keys can read and write all documented resources. Revoke or replace a key at any time from the dashboard.
- Keys are scoped to one organization. A key can never select another tenant through a query or request body.
- Each key allows 120 requests per 60 seconds. Every response carries
RateLimit-Limit,RateLimit-RemainingandRateLimit-Reset, plus the structuredRateLimitandRateLimit-Policyfields, so a client can pace itself rather than discovering the limit by hitting it. A429addsRetry-After.
Pagination
List endpoints accept limit (1–100, default 25) and offset (default 0). Every list response includes the exact values and total count:
{
"data": [],
"pagination": { "limit": 25, "offset": 0, "total": 0 }
}Safe mutation retries
Add an Idempotency-Key header to POST, PATCH and DELETE requests that your client may retry. Moonitor binds the key to the method, path and validated body, then replays the same successful response for 24 hours instead of running the mutation twice.
curl -X POST https://www.moonitor.dev/api/v1/monitors \
-H "X-API-Key: moon_YOUR_KEY" \
-H "Idempotency-Key: deploy-2026-07-15-monitor-1" \
-H "Content-Type: application/json" \
-d '{"name":"Website","type":"HTTP","url":"https://example.com"}'A replay includes Idempotency-Replayed: true. Reusing the key for different input returns 409 idempotency_conflict.
Errors and request tracing
Errors always use one envelope. Keep the requestId when contacting support; it is also returned in the X-Request-ID header.
{
"error": {
"code": "validation_error",
"message": "The request is invalid",
"requestId": "…",
"details": [{ "path": "url", "message": "url is required for HTTP monitors" }]
}
}Branch on error.code, never on error.message: the codes below are a fixed set, published as an enum in the Error schema of the OpenAPI document, while the messages are written for humans and may be reworded.
| Status | error.code | Meaning |
|---|---|---|
| 400 | validation_error | Invalid JSON, content type, query, path or body. See error.details. |
| 400 | invalid_idempotency_key | The Idempotency-Key header is malformed or too long. |
| 401 | unauthorized | Missing, expired, disabled or invalid key. |
| 403 | forbidden | The key is read-only, or lacks permission for this resource. |
| 404 | not_found | No such endpoint, or no such resource in this organization. |
| 405 | method_not_allowed | The path exists but not for this method. See the Allow header. |
| 409 | conflict | The request conflicts with current state. |
| 409 | idempotency_conflict | The Idempotency-Key was already used for different input. |
| 409 | idempotency_in_progress | An earlier request with this key is still running. Retry shortly. |
| 422 | plan_limit | The plan's allowance for this resource is used up. |
| 422 | subscription_required | The organization has no active subscription. |
| 429 | rate_limited | Per-key rate limit reached. Wait for Retry-After. |
| 500 | internal_error | Unexpected server failure. Safe to retry with the same Idempotency-Key. |
Versioning and deprecation
The version is in the path. Everything documented here is /api/v1, and we treat that prefix as a promise.
- Additive changes happen within a version. New endpoints, new optional request fields and new response fields can appear at any time — so your client must ignore response fields it does not recognise rather than failing on them.
- Breaking changes ship as a new version. Removing a field, renaming one, tightening validation or changing a status code means
/api/v2./api/v1keeps working. - Removal is announced in the responses themselves. A deprecated operation returns a
Deprecationheader (RFC 9745) saying when it was deprecated, aSunsetheader (RFC 8594) with the earliest date it may stop working, and aLinkwithrel="deprecation"pointing at what to use instead. It is also markeddeprecatedin the OpenAPI document. - You get at least 180 days. That is the minimum between the first
Deprecationheader and the shutdown date, and we email account holders with active API keys as well.
Nothing is currently deprecated.