API keys and scopes
Every request to the API carries an organization API key. A key belongs to your organization, not to the person who created it: it keeps working when its creator leaves the organization, and the owner can see who created it.
Create a key
Section titled “Create a key”- In the dashboard open Team → API keys. Only organization owners and admins see this page.
- Name the key, pick a preset (or choose scopes yourself), and optionally set an expiry date.
- Copy the key. It is shown once; Monitorable keeps only a hash, so a lost key cannot be shown again — create a new one and revoke the old.
A key looks like mon_live_ followed by random characters (mon_test_ on
staging). The fixed prefix lets secret scanners such as GitHub secret
scanning and gitleaks recognise a key that ends up in a repository.
Use a key
Section titled “Use a key”Send it in the Authorization header:
curl -H "Authorization: Bearer mon_live_<your-key>" https://api.monitorable.io/v1/meA key in a query string is refused with 400 key_in_query:
URLs end up in logs, so the header is the only accepted place. The
organization is implicit in the key — requests never name it.
Keep keys in a secret store or your CI’s secret variables, never in a repository. If a key was exposed, revoke it (below) and create a new one.
Scopes
Section titled “Scopes”A key can only call endpoints whose scope it holds. A call without the
right scope answers 403 insufficient_scope.
| Scope | Allows |
|---|---|
servers:read |
list/get servers, metadata, uptime, services, containers, disks, ports |
servers:write |
create, rename, remove servers; rotate a server’s agent key |
servers:enroll |
only POST /v1/enroll (see Add servers without the dashboard); cannot read anything |
metrics:read |
current + historical metrics |
alerts:read |
incidents, templates, notification channels (their settings are never returned) |
alerts:write |
acknowledge / unacknowledge incidents, mute/unmute, assign template |
account:read |
organization, members (emails visible to admin-role keys only), plan, usage; GET /v1/me needs no scope |
The dashboard offers four presets:
- Read-only — every
:readscope. - Automation —
servers:read servers:write alerts:write, for Terraform, Ansible and CI: create, rename, delete and rotate servers, assign templates, and mute or acknowledge incidents during maintenance. It holds nometrics:readoralerts:read, so it cannot read metrics, incidents or templates; add those scopes to the key when the job needs them. - Enrollment —
servers:enrollonly, for images and cloud-init. - Full — every scope.
Deletion lives in servers:write on purpose: an enrollment key can never
delete a server, an automation key can.
A key carries a role, admin (the default) or member, chosen at creation.
Scopes narrow the role further; they never widen it. A member key sees
what a member sees in the dashboard, and a write attempted with it answers
403 insufficient_role. Owner-only
actions — deleting the organization, changing member roles, channel secrets
— are not reachable through any scope.
Expiry and revoking
Section titled “Expiry and revoking”A key can have an expiry date; after it, the key answers 401
invalid_api_key. To stop a key
earlier, revoke it from Team → API keys: it stops working immediately.
Revoke and replace keys when a person or system that held one is retired.
The key list shows Last used for each key (updated at most once a minute) so you can spot keys nobody uses any more.
Audit log
Section titled “Audit log”Every call that changes something — creating, renaming or deleting a server, enrolling a host, rotating a key, acknowledging an incident, muting alerts — is recorded with the key, the method, the resource, the result and the request id. Organization owners and admins can read the last 90 days under Team → API keys.
Which scope each endpoint needs
Section titled “Which scope each endpoint needs”Every endpoint needs a scope except where it says any key. Calls that
change something additionally need an admin-role key.
Account
Section titled “Account”| Endpoint | Scope |
|---|---|
GET /v1/me |
any key |
GET /v1/organization |
account:read |
GET /v1/organization/members |
account:read |
Servers
Section titled “Servers”| Endpoint | Scope |
|---|---|
GET /v1/servers |
servers:read |
POST /v1/servers |
servers:write |
GET /v1/servers/{id} |
servers:read |
PATCH /v1/servers/{id} |
servers:write |
DELETE /v1/servers/{id} |
servers:write |
POST /v1/servers/{id}/agent-key:rotate |
servers:write |
GET /v1/servers/{id}/metadata |
servers:read |
GET /v1/servers/{id}/services |
servers:read |
GET /v1/servers/{id}/containers |
servers:read |
GET /v1/servers/{id}/disks |
servers:read |
GET /v1/servers/{id}/ports |
servers:read |
POST /v1/enroll |
servers:enroll |
Metrics
Section titled “Metrics”| Endpoint | Scope |
|---|---|
GET /v1/servers/{id}/metrics/current |
metrics:read |
GET /v1/servers/{id}/metrics |
metrics:read |
Incidents and alerting
Section titled “Incidents and alerting”| Endpoint | Scope |
|---|---|
GET /v1/incidents |
alerts:read |
GET /v1/incidents/{id} |
alerts:read |
POST /v1/incidents/{id}:acknowledge |
alerts:write |
POST /v1/incidents/{id}:unacknowledge |
alerts:write |
POST /v1/servers/{id}/alerts:mute |
alerts:write |
POST /v1/servers/{id}/alerts:unmute |
alerts:write |
GET /v1/alert-templates |
alerts:read |
PUT /v1/servers/{id}/alert-template |
alerts:write |
GET /v1/notification-channels |
alerts:read |
| Endpoint | Scope |
|---|---|
GET /v1/agent/commands |
any key |