REST API overview
Authentication, shared conventions, and commonly used HowlOps API endpoints.
Base URL
All endpoints are under:
https://api.howlops.com/api/v1/
The current API uses the v1 path prefix. Treat response objects as extensible: clients should ignore fields they do not recognise.
Authentication
| Method | Used by | How to pass |
|---|---|---|
| Session cookie | Web platform and admin UI | ho_session HttpOnly cookie set by the login response |
| Workspace API token | Scripts, CI, integrations | Authorization: Bearer howlops_<hex> (token format, not a JWT) |
| Prober token | Prober agent | Authorization: Bearer <prober_token> |
Public endpoints (/api/v1/public/*, /health) require no authentication.
Your first call
Create a workspace API token under Settings → API tokens, then list your monitors:
curl "https://api.howlops.com/api/v1/monitors" \
-H "Authorization: Bearer $HOWLOPS_TOKEN"
Every endpoint in the table below expands to the same call written out for that route, next to the response it answers with.
Common request headers
| Header | When to send |
|---|---|
Authorization: Bearer <token> | All authenticated requests |
Content-Type: application/json | POST / PUT with a body |
Idempotency-Key: <uuid> | Selected billing mutations that explicitly document idempotency |
Common response headers
| Header | Meaning |
|---|---|
X-Request-Id | Unique request identifier for tracing |
X-RateLimit-Limit | Allowed requests in the active window, when the route uses this limiter |
X-RateLimit-Remaining | Remaining requests in that window |
X-RateLimit-Reset | Seconds until the current limit resets |
Cache-Control: no-store | Present on session-sensitive responses |
Response shapes
List response
Most collection endpoints use an envelope. Some older or specialised endpoints return an array directly, so use the response shape documented for the route you call.
{
"items": [...],
"total": 142,
"page": 1,
"per_page": 25,
"total_pages": 6
}
Pagination parameters and defaults vary by resource. Do not assume an endpoint accepts page or per_page unless its handler documents them.
Detail response
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"tenant_id": "...",
"created_at": "2026-05-01T12:00:00Z",
"updated_at": "2026-05-13T08:22:15Z"
}
Create (201) / Update (200) response
Create and update responses normally return the affected object. Some action endpoints return a smaller result or no body.
Delete response
Delete endpoints commonly return 204 No Content, but callers should follow the status code documented for the specific route.
Error response
{
"error": "monitor limit reached for your plan",
"code": "TIER_LIMIT_EXCEEDED"
}
See API errors reference for the full code catalog.
Common endpoints
This is a practical index for the resources most customers automate. It is not a complete dump of the application router. New product areas can add routes before this overview is updated; use the API annotations and the response returned by the running version as the contract for specialised endpoints.
Authentication
1 endpointMonitors
5 endpointsHeartbeats
8 endpointsIncidents
5 endpointsAlerts and routing
5 endpointsOn-call
10 endpointsNotifications
12 endpointsStatus pages
8 endpointsAnalytics
3 endpointsBilling
7 endpointsAccount and workspace
1 endpointPublic
5 endpointsRealtime and MCP
4 endpointsRegions
Several responses carry a probing region: effective_regions and prober_region_labels on a
monitor, region and affected_regions on an incident and its alerts. A region identifies a
place a check runs from, not the hardware behind it. Each region maps to a country, which is what
the flag beside it in the app comes from.
effective_regionsis the set of regions a monitor is actually checked from right now. It is the monitor's configured regions narrowed to those that currently have an online prober and clamped to what the plan allows, so it can be shorter than the regions you selected. A monitor with no explicit region configuration returns an empty array here.prober_region_labelsmaps each region code in the response to a human display name, so a client can show the name without carrying its own region table.regionandaffected_regionson an incident record where the failure was seen.
The region code is stable across hardware changes: we can replace the machines behind a region without the code changing, and your monitors and history carry on unbroken. What a region is, and what happens when one closes, is covered in Probing regions.
Incident status values
The lifecycle labels shown in the dashboard map onto a smaller set of raw status values
returned by the API. There is no acknowledged status: acknowledgement is a separate
timestamp (acknowledged_at) layered on top of an ongoing incident.
| Dashboard label | API status | Notes |
|---|---|---|
| Triggered / Ongoing | ongoing | The incident is open. acknowledged_at is null. |
| Acknowledged | ongoing + acknowledged_at set | Still ongoing; a responder has taken it. Escalation pauses. |
| Resolved | resolved | The underlying signal recovered (auto-resolve or recovery event). |
| Closed | resolved + manually_closed_at set | A person closed it by hand rather than it auto-recovering. The status column is still resolved; the manually_closed_at / manually_closed_by fields distinguish a manual close from an auto-recovery. |
The status field itself is only ever ongoing or resolved. Acknowledgement (acknowledged_at)
and a manual close (manually_closed_at) are timestamps layered on top, not distinct status
values. promoted_at (whether the alert became an incident) and is_major are likewise separate
flags: they do not change status. An alert and an incident share the same lifecycle values.
WebSocket
WSS /api/v1/ws?token=<workspace_api_token>
The token query parameter must be a workspace API token (howlops_<hex>), not an OAuth or JWT access token. Browser clients can use the ho_session cookie. The connection streams real-time incident and monitor status events. See the Events reference for event payload shapes.
Rate limits
See also
Was this page helpful?