---
title: "Permissions by endpoint"
description: "Which role, token type and token scope each endpoint needs, and which error code a refused call returns."
---

Every call is checked in this order. The first check that fails decides the answer:

1. **Authentication.** No token, or a revoked, expired or mistyped one: `401 unauthorized`.
2. **Token type.** A customer-bound token on an organization-wide path: `403 customerScopedTokenForbidden`. A token with scopes that lacks the scope of the path: `403 apiTokenScopeForbidden`. The message and `data.requiredScope` name the missing scope, for example `api.write.monitors`. See [Token Scopes](/api/introduction/token-scopes-organization-vs-customer).
3. **Role.** An organization API token (`wsm_…`) acts with the **current** role of the user who created it. If that user is deactivated or deleted, the token acts as `readonly`. Old tokens without a recorded issuer act as `admin`. A role that is not allowed gets `403` with the code in the table below.
4. **Customer scope.** `readonly` users, editors assigned to customers and customer-bound tokens only reach their own customers. A specific resource outside that scope answers `404` with the resource's not-found code, never `403`. An API token, organization-wide or customer-bound, follows the **current** role and customer assignment of the user who created it: if that user is assigned to customers, the token reaches only those customers (a customer-bound token reaches its customer only while that user still has it). If the user is deactivated or deleted, the token reaches no customer at all.
5. **Module.** Status pages need the status pages module (`403 statusPagesModuleDisabled`). Incident Management must be enabled for the organization (`403 imNotEnabled`).

Every refused call carries a stable `data.code` and an English `statusMessage` that says what is missing. Branch on the code; the message may be reworded.

Roles: `admin` and `editor` are organization roles, `readonly` is the customer self-service role, `responder` exists for Incident Management only. Global supporters never change customer data (`403 forbidden`). Agent tokens (`wsma_…`, connected apps) reach only the paths their scopes allow; every other path answers `403 agentTokenReadOnly` with `data.reason`.

## Monitors

| Method | Path | Who may call it | Scope | Refused with |
|---|---|---|---|---|
| `GET` | `/api/websites/:id`, `/api/<type>-monitors/:id` | Any role within its customer scope | `api.read.monitors` | `404 websiteNotFound` / `monitorNotFound` |
| `POST` | `/api/websites`, `/api/<type>-monitors` | `admin`, `editor`. `readonly` and customer-bound tokens create `self_service` monitors for their own customer if the package allows self-service. Only `admin` may set `managementType`. | `api.write.monitors` | `forbidden`, `selfServiceNotAllowed`, `selfServiceQuotaReached`, quota codes |
| `PATCH` | `/api/websites/:id`, `/api/<type>-monitors/:id` | `admin`, `editor`. Customer-bound callers change `self_service` monitors, `managed` ones only with `canEditManaged`. Changing `managementType` needs an organization-wide `admin`. | `api.write.monitors` | `forbidden`, `managed_by_organization`, `managementTypeOrgOnly` |
| `DELETE` | `/api/websites/:id`, `/api/<type>-monitors/:id` | Like `PATCH`, but never `readonly` (nor a token its user created) | `api.write.monitors` | `readonlyMayNotDelete`, `managed_by_organization` |
| `POST` | `/api/websites/:id/heartbeat-token/rotate` | Like `PATCH` | `api.write.monitors` | as `PATCH` |
| `GET`, `POST`, `DELETE` | `/api/monitor-tags` | Any role within its customer scope | `api.read.monitors` / `api.write.monitors` | `forbidden`, `badRequest` |
| `GET` | `/api/tags`, `/api/tags/:id` | Any role in the organization | `api.read.monitors` | `404 tagNotFound` |
| `POST`, `PATCH`, `DELETE` | `/api/tags`, `/api/tags/:id` | Any role; customer-bound callers create and change tags of their customers only, never organization-wide tags | `api.write.monitors` | `forbidden`, `authorizingUserUnresolved` |
| `GET` | `/api/maintenance-windows/:id` | Any role within its customer scope | `api.read.monitors` | `forbidden` |
| `POST` | `/api/maintenance-windows` | Any role except global supporters. Customer-bound callers anchor the window to their customer. | `api.write.monitors` | `forbidden`, `tagOnlyNeedsCustomer` |
| `PATCH`, `DELETE` | `/api/maintenance-windows/:id` | Customer windows: within the customer scope. Organization-wide windows: `admin` or `editor` with organization-wide access. | `api.write.monitors` | `forbidden`, `customerScopedTokenForbidden` |
| `GET` | `/api/monitoring-locations/countries` | Any authenticated caller | `api.read.monitors` | - |

`<type>` is `dns`, `ftp`, `icmp`, `imap-pop`, `smtp`, `ssh` or `tcp`; all seven follow the same rules.

## Customers

| Method | Path | Who may call it | Scope | Refused with |
|---|---|---|---|---|
| `GET` | `/api/customers`, `/api/customers/:id` | Any role; restricted callers see their own customers | `api.read.customers` | `404 customerNotFound` |
| `POST` | `/api/customers` | `admin`, organization-wide `editor`. Not customer-bound tokens. Permission fields are applied for `admin` only. | `api.write.customers` | `forbidden`, `customerScopedTokenForbidden` |
| `PATCH` | `/api/customers/:id` | `admin`, `editor`. Changing the package or permission fields needs `admin`. | `api.write.customers` | `forbidden`, `packageOrgOnly` |
| `DELETE` | `/api/customers/:id` | `admin`, `editor` (an editor assigned to customers only within that scope, never the last of them; `userAction=delete` stays `admin`). Not customer-bound tokens. | `api.write.customers` | `forbidden`, `customerUserDeleteAdminOnly`, `cannotDeleteOwnLastCustomer` |
| `POST` | `/api/customers/:id/ips`, `/api/customers/:id/domains` | Any role within its customer scope, `readonly` included (as `self_service`, if the package allows it) | `api.write.customers` | `forbidden`, `selfServiceNotAllowed`, `selfServiceQuotaReached`, quota codes |
| `GET` | `/api/customer-ips/:id`, `/api/customer-domains/:id` | Any role within its customer scope | `api.read.customers` | `404 ipNotFound` / `domainNotFound` |
| `PATCH` | `/api/customer-ips/:id`, `/api/customer-domains/:id` | `admin`, `editor`; customer-bound callers for `self_service` entries | `api.write.customers` | `forbidden`, `managed_by_organization`, `managementTypeOrgOnly` |
| `DELETE` | `/api/customer-ips/:id`, `/api/customer-domains/:id` | Like `PATCH`, never `readonly` | `api.write.customers` | `readonlyMayNotDelete` |

## Organization

All paths in this section are closed to customer-bound tokens (`customerScopedTokenForbidden`), except `GET /api/organization` and `GET /api/package-configs`.

| Method | Path | Who may call it | Scope | Refused with |
|---|---|---|---|---|
| `GET` | `/api/organization`, `/api/package-configs` | Any role in the organization | `api.read.organization` | - |
| `PATCH` | `/api/organization` | `admin`. API tokens cannot change automatic upgrades or the MFA policy. | `api.write.organization` | `forbidden`, `nonUserSessionForbidden` |
| `GET` | `/api/users` | Any role; restricted callers see users of their customers | `api.read.organization` | - |
| `POST`, `GET`, `PATCH`, `DELETE` | `/api/users`, `/api/users/:id` | `admin` with organization-wide access | `api.read.organization` / `api.write.organization` | `forbidden`, `customerScopedTokenForbidden`, `globalUserProtected` |
| all | `/api/custom-fields`, `/api/custom-fields/:id` | Reading: any role. Changing: `admin`. | `api.read.organization` / `api.write.organization` | `forbidden` |
| all | `/api/escalation-config/:id` | `admin` with organization-wide access, reading included | `api.read.alerts` / `api.write.alerts` | `forbidden`, `customerScopedTokenForbidden` |
| `GET` | `/api/organization/reports/:id` | Any role in the organization | `api.read.reports` | `404 notFound` |
| `POST`, `PATCH`, `DELETE` | `/api/organization/reports`, `/api/organization/reports/:id` | `admin` | `api.write.reports` | `forbidden` |
| all | `/api/organization/smtp`, `/api/organization/whitelabel/**`, `/api/organization/sso/**` | `admin`. Closed to tokens with scopes: use a token without scopes. | - | `forbidden`, `ssoAdminOnly`, `apiTokenScopeForbidden` |

## Notification channels

| Method | Path | Who may call it | Scope | Refused with |
|---|---|---|---|---|
| `GET` | `/api/notification-channels`, `/api/notification-channels/:id` | Any role; restricted callers see channels of their customers and organization channels | `api.read.alerts` | `forbidden` |
| `POST`, `PATCH`, `DELETE` | `/api/notification-channels`, `/api/notification-channels/:id` | Organization channels: `admin`. Customer channels: `admin`, or `readonly` within its customer scope. `editor` cannot change channels. | `api.write.alerts` | `forbidden` |

## Status pages

The status pages module must be active. Customer-bound callers reach pages of their customers only; a page without a customer needs organization-wide access (`403 forbidden`).

| Method | Path | Who may call it | Scope | Refused with |
|---|---|---|---|---|
| `GET` | `/api/status-pages`, `/api/status-pages/:id`, `…/components`, `…/groups`, `/api/status-pages/maintenances/:id`, `/api/status-pages/domains/:id` | `admin`, `editor`, `readonly` | `api.read.statuspages` | `forbidden`, `404 statusPageNotFound` |
| `POST`, `PATCH`, `DELETE` | `/api/status-pages`, `/api/status-pages/:id`, components, groups, maintenances, `POST /api/status-pages/domains`, `DELETE /api/status-pages/domains/:id` | `admin`, `editor`; customer-bound users and tokens (also `readonly`) only `self_service` pages of their customers | `api.write.statuspages` | `forbidden`, `statusPageLimitReached`, `managed_by_organization` |
| `GET`, `PATCH` | `/api/status-pages/:id/design` | `admin`, `editor`, `readonly` | `api.read.statuspages` / `api.write.statuspages` | `forbidden` |
| `POST` | `/api/status-pages/domains/verify`, `/api/status-pages/domains/activate` | `admin` | `api.write.statuspages` | `forbidden` |

## Incident Management

Incident Management must be enabled for the organization (`403 imNotEnabled`; reading and changing `/api/im/org-settings` works without it). It needs the role `admin`, `editor` or `responder` without a customer assignment; `readonly` and customer-bound tokens get `403 imAccessDenied` or `403 customerScopedTokenForbidden`. Agent tokens cannot use Incident Management. Scopes: `api.read.incidents` for `GET`, `api.write.incidents` for every other method.

| Method | Path | Who may call it | Refused with |
|---|---|---|---|
| `GET` | every `/api/im/**` path below except the two admin-only ones | Any IM role (`admin`, `editor`, `responder`) | `imAccessDenied` |
| `POST`, `PATCH`, `DELETE` | `/api/im/teams/:id/**` (members, invite, tiers, escalations, overrides), `/api/im/schedules/**`, `/api/im/tiers/:id/schedules`, `/api/im/sources/**`, `/api/im/routing/**`, `/api/im/statuspage-rules/**` | `admin`, or a team admin (`imRole: admin`) of that team. Inviting a new user needs `admin`. | `imTeamWriteDenied`, `forbidden` |
| `POST` | `/api/im/teams` | `admin` | `imTeamWriteDenied` |
| `POST`, `PATCH`, `DELETE` | `/api/im/channels`, `/api/im/channels/:id` | Organization channel: `admin`. Team channel: `admin` or team admin. | `imChannelWriteDenied` |
| `POST`, `PATCH`, `DELETE` | `/api/im/outbound`, `/api/im/outbound/:id` | Organization integration: `admin`. Team integration: `admin` or team admin. | `imOutboundWriteDenied`, `imTeamWriteDenied` |
| `PATCH` | `/api/im/org-settings` | `admin` | `forbidden` |
| `GET`, `PUT` | `/api/im/notification-template`, `/api/im/users/:id/notification-settings` | `admin`, reading included | `forbidden` |

An API token is never a team admin: team admin rights belong to a user. Changing team resources with a token therefore needs a token created by an `admin`.
