REST API reference
Complete endpoint inventory, authentication methods, request/response shapes, and versioning rules.
Base URL
All endpoints are under:
https://api.howlops.com/api/v1/
Versioning
- Current version: v1 (URL-prefixed
/api/v1/) - Non-breaking additions (new fields, new endpoints) ship without a version bump.
- Breaking changes require a
v2prefix; a 90-day deprecation window applies.
Authentication
| Method | Used by | How to pass |
|---|---|---|
| Session cookie | Web platform and admin UI | howlops_session HttpOnly Secure cookie (set by 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.
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> | Optional; POST / PUT; safe to retry on network failure |
If-None-Match: <etag> | GET; server returns 304 if resource unchanged |
Common response headers
| Header | Meaning |
|---|---|
X-Request-Id | Unique request identifier for tracing |
X-RateLimit-Limit | Allowed requests per window |
X-RateLimit-Remaining | Remaining requests in current window |
X-RateLimit-Reset | Unix timestamp when the window resets |
ETag | Hash for conditional GET |
Cache-Control: no-store | Present on session-sensitive responses |
Response shapes
List response
Every list endpoint returns a paginated envelope. A bare array is never returned.
{
"items": [...],
"total": 142,
"page": 1,
"per_page": 25,
"total_pages": 6
}
Default: page=1, per_page=25. Maximum per_page: 100.
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
Returns the complete object. Not just {"id": "..."}.
Delete response
204 No Content, empty body.
Error response
{
"error": "monitor limit reached for your plan",
"code": "TIER_LIMIT_EXCEEDED",
"details": { "current_count": 50, "tier_limit": 50 }
}
See API errors reference for the full code catalog.
Endpoint groups
| Group | Purpose | Mobile |
|---|---|---|
POST /api/v1/auth/login | Password login | Yes |
POST /api/v1/auth/register | Create account | Yes |
POST /api/v1/auth/logout | Invalidate session | Yes |
POST /api/v1/auth/forgot-password | Initiate password reset | Yes |
POST /api/v1/auth/reset-password | Complete password reset | Yes |
GET /api/v1/auth/verify-email | Verify email address (GET with token query param) | Yes |
GET /api/v1/auth/oauth/providers | List enabled OAuth providers | Yes |
GET /api/v1/auth/oauth/{provider} | Start OAuth flow (google, github, microsoft, apple) | Yes |
GET /api/v1/auth/oauth/{provider}/callback | OAuth callback handler | Yes |
POST /api/v1/auth/oauth/apple/native | Apple native sign-in with id_token | Yes |
GET /api/v1/oauth/authorize | PKCE authorization endpoint | Yes |
POST /api/v1/oauth/token | Token + refresh endpoint | Yes |
POST /api/v1/auth/sso/initiate | SAML SP-initiated SSO | No |
GET /api/v1/auth/me | Current authenticated user | Yes |
PUT /api/v1/settings/profile | Update profile | Yes |
GET /api/v1/sessions | List active sessions | Yes |
DELETE /api/v1/sessions/{id} | Revoke a session | Yes |
GET /api/v1/monitors | List monitors (paginated) | Yes |
POST /api/v1/monitors | Create monitor | Yes |
GET /api/v1/monitors/{id} | Get monitor (includes current status) | Yes |
PUT /api/v1/monitors/{id} | Update monitor | Yes |
DELETE /api/v1/monitors/{id} | Delete monitor | Yes |
GET /api/v1/heartbeats | List heartbeats | Yes |
POST /api/v1/heartbeats | Create heartbeat | Yes |
GET /api/v1/heartbeats/{id} | Get heartbeat | Yes |
PATCH /api/v1/heartbeats/{id} | Update heartbeat | Yes |
DELETE /api/v1/heartbeats/{id} | Delete heartbeat | Yes |
GET /api/v1/hb/{slug} | Heartbeat ping endpoint (GET, POST, and HEAD are all valid) | Yes |
POST /api/v1/hb/{slug} | Heartbeat ping endpoint | Yes |
HEAD /api/v1/hb/{slug} | Heartbeat ping endpoint | Yes |
GET /api/v1/incidents | List incidents (paginated) | Yes |
GET /api/v1/incidents/{id} | Get incident | Yes |
POST /api/v1/incidents/{id}/acknowledge | Acknowledge incident | Yes |
POST /api/v1/incidents/{id}/resolve | Resolve incident | Yes |
GET /api/v1/correlation-groups | List correlation groups | Yes |
GET /api/v1/alerts | List alert records | Yes |
GET /api/v1/alert-routing-rules | List routing rules | Yes |
POST /api/v1/alert-routing-rules | Create routing rule | Yes |
PUT /api/v1/alert-routing-rules/{id} | Update routing rule | Yes |
DELETE /api/v1/alert-routing-rules/{id} | Delete routing rule | Yes |
GET /api/v1/escalation-policies | List escalation policies | Yes |
POST /api/v1/escalation-policies | Create policy | Yes |
PUT /api/v1/escalation-policies/{id} | Update policy | Yes |
DELETE /api/v1/escalation-policies/{id} | Delete policy | Yes |
GET /api/v1/schedules | List on-call schedules | Yes |
POST /api/v1/schedules | Create schedule | Yes |
PUT /api/v1/schedules/{id} | Update schedule | Yes |
DELETE /api/v1/schedules/{id} | Delete schedule | Yes |
POST /api/v1/schedules/{id}/overrides | Create schedule override | Yes |
GET /api/v1/notification-channels | List notification channels | Yes |
POST /api/v1/notification-channels | Create channel | Yes |
PUT /api/v1/notification-channels/{id} | Update channel | Yes |
DELETE /api/v1/notification-channels/{id} | Delete channel | Yes |
POST /api/v1/notification-channels/{id}/test | Send test notification | Yes |
GET /api/v1/notification-log | Sent notification history | No |
GET /api/v1/notifications/feed | Per-user in-app feed (paginated + unread_count) | Yes |
GET /api/v1/notifications/feed/unread-count | Unread count | Yes |
POST /api/v1/notifications/feed/{id}/read | Mark one as read | Yes |
POST /api/v1/notifications/feed/read-all | Mark all as read | Yes |
GET /api/v1/users/me/notification-prefs | Get notification preferences | Yes |
PUT /api/v1/users/me/notification-prefs | Update notification preferences | Yes |
GET /api/v1/status-pages | List status pages | Partial |
POST /api/v1/status-pages | Create status page | Partial |
PATCH /api/v1/status-pages/{id} | Update status page | Partial |
DELETE /api/v1/status-pages/{id} | Delete status page | Partial |
GET /api/v1/maintenance-windows | List maintenance windows | Yes |
POST /api/v1/maintenance-windows | Create maintenance window | Yes |
PUT /api/v1/maintenance-windows/{id} | Update maintenance window | Yes |
DELETE /api/v1/maintenance-windows/{id} | Delete maintenance window | Yes |
GET /api/v1/analytics | Uptime and response-time stats | Partial |
GET /api/v1/analytics/sla-report | SLA report | Partial |
GET /api/v1/analytics/monitor-breakdown | Per-monitor breakdown | Partial |
GET /api/v1/billing/subscription | Current subscription | Yes |
POST /api/v1/billing/capability-checkout | Start capability-based Stripe checkout | Yes |
POST /api/v1/billing/capability-checkout-embedded | Embedded Stripe checkout for a capability | Yes |
POST /api/v1/billing/downgrade | Schedule downgrade {target_tier} | Yes |
DELETE /api/v1/billing/downgrade | Cancel scheduled downgrade | Yes |
POST /api/v1/billing/interval | Switch billing interval {interval} | Yes |
GET /api/v1/billing/invoices | List invoices (paginated) | Yes |
GET /api/v1/billing/tax-info | Get tax ID | Yes |
PUT /api/v1/billing/tax-info | Set tax ID {country, tax_id, tax_id_type} | Yes |
GET /api/v1/billing/currencies | Supported billing currencies | Yes |
POST /api/v1/account/export | Start a workspace-wide data export job (owner/admin only) | Yes |
POST /api/v1/account/export/personal | Start a personal-data-only export job (any member, GDPR Art. 15) | Yes |
GET /api/v1/account/export/{job_id} | Export job status; add ?download=1 once completed to stream the ZIP | Yes |
GET /api/v1/audit-log | Tenant audit log (paginated) | No |
GET /api/v1/feature-flags | Active feature flags for tenant | Yes |
GET /api/v1/feature-gates | List feature gates | Yes |
GET /api/v1/onboarding/status | Onboarding step status | Yes |
POST /api/v1/workspace/onboarding/step | Mark onboarding step complete | Yes |
GET /api/v1/push-tokens | List push tokens | Yes |
POST /api/v1/push-tokens | Register device push token | Yes |
DELETE /api/v1/push-tokens/{token} | Unregister device | Yes |
GET /api/v1/public/brand-settings | Public brand config | n/a |
GET /api/v1/public/status-pages/{slug} | Public status page | n/a |
POST /api/v1/public/status-pages/{slug}/subscribe | Subscribe to status page | n/a |
GET /api/v1/public/capability-plans | Capability plan catalog with pricing (drives the pricing page) | n/a |
GET /api/v1/public/tiers | Public tier summary with per-capability pricing | n/a |
GET /api/v1/public/tier-comparison | Plan comparison matrix | n/a |
GET /api/v1/public/billing/currencies | Supported currencies (public) | n/a |
POST /api/v1/mcp | Hosted MCP endpoint (JSON-RPC, bearer auth) | No |
GET /api/v1/mcp | MCP capability handshake | No |
GET /health | Health check | n/a |
WSS /api/v1/ws | WebSocket real-time events (token query param) | Yes |
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. Alternatively, pass the howlops_session cookie (browser clients). 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?