Skip to content

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.

  1. In the dashboard open Team → API keys. Only organization owners and admins see this page.
  2. Name the key, pick a preset (or choose scopes yourself), and optionally set an expiry date.
  3. 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.

Send it in the Authorization header:

Terminal window
curl -H "Authorization: Bearer mon_live_<your-key>" https://api.monitorable.io/v1/me

A 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.

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 :read scope.
  • 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 no metrics:read or alerts:read, so it cannot read metrics, incidents or templates; add those scopes to the key when the job needs them.
  • Enrollment — servers:enroll only, 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.

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.

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.

Every endpoint needs a scope except where it says any key. Calls that change something additionally need an admin-role key.

Endpoint Scope
GET /v1/me any key
GET /v1/organization account:read
GET /v1/organization/members account:read
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
Endpoint Scope
GET /v1/servers/{id}/metrics/current metrics:read
GET /v1/servers/{id}/metrics metrics:read
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