API Permission Model#
Misskey's API permission model has two layers: endpoint metadata flags that declare what privilege an endpoint requires, and runtime enforcement in ApiCallService that evaluates those flags against the caller's identity and roles. All permission checks run inside ApiCallService.call() before the endpoint handler executes.
Endpoint Metadata (IEndpointMeta)#
Every endpoint exports a meta object typed as IEndpointMeta, defined in packages/backend/src/server/api/endpoints.ts. The fields relevant to permissions are:
| Field | Effect |
|---|---|
requireCredential | Caller must be authenticated (logged-in user). |
requireModerator | Caller must hold a role with isModerator or isAdministrator, or be the root user. |
requireAdmin | Caller must hold a role with isAdministrator, or be the root user. |
requiredRolePolicy | Caller must satisfy a specific role policy key (e.g. drive capacity). |
kind | OAuth permission scope string (e.g. 'write:notes', 'read:admin:meta'). Required when any of the above flags is true. |
secure | Blocks requests made with a third-party app token; only session-authenticated requests are allowed. Mutually exclusive with the credential/admin/moderator flags at the type level. |
TypeScript enforces these constraints via a discriminated union: setting requireCredential, requireModerator, or requireAdmin to true requires kind to be set; setting secure: true is incompatible with those flags .
Permission Check Order (Runtime)#
Inside ApiCallService.call(), checks run in this order:
securecheck — ifmeta.secureand the request carries a token (rather than a first-party session), throwACCESS_DENIED.- Rate limiting — applied before auth checks .
- Credential check — if
requireCredential,requireModerator, orrequireAdmin, the user must be non-null and non-suspended . prohibitMovedcheck — rejects migrated accounts .- Role check — if
requireModeratororrequireAdmin, and the caller is not the root user,RoleService.getUserRoles()is called :requireModerator: at least one role must haveisModeratororisAdministratorset.requireAdmin: at least one role must haveisAdministratorset.
requiredRolePolicycheck — if set, the caller's policies are evaluated; administrators bypass this check .- OAuth scope check — if the request uses an access token, its
permissionarray must includemeta.kind.
The Root User — Special Implicit Privilege#
The root user is the first account created on an instance, stored as meta.rootUserId . The root user bypasses all role checks — it is always treated as both administrator and moderator — even without any roles assigned . This is enforced in both ApiCallService and directly in RoleService.isAdministrator() / RoleService.isModerator().
The admin/accounts/create endpoint demonstrates the root-user bootstrap case: if rootUserId is null (no accounts yet), the endpoint accepts an unauthenticated request to create the first account. Once rootUserId is set, only the root user — via a first-party session (no external token) — can call the endpoint .
Role Definitions#
Administrator and moderator privileges are flags on the MiRole model:
MiRole.isAdministrator— grants admin-level access.MiRole.isModerator— grants moderator-level access.
Administrators are a strict superset of moderators: RoleService.isModerator() returns true if the user has either isModerator or isAdministrator on any of their roles; RoleService.isAdministrator() requires isAdministrator specifically . Roles are resolved — including conditional/formula-based roles — via RoleService.getUserRoles().
Custom Inline Permission Logic#
Some endpoints do not rely solely on metadata flags and instead write additional checks inside the handler itself. admin/accounts/create is one example: the endpoint declares no requireAdmin or requireCredential flags and instead performs its own inline logic to cover both the initial-setup path and the subsequent admin-only path .
This pattern is appropriate when permission rules depend on runtime server state (e.g., whether setup has been completed) rather than the caller's role.
Key Source Files#
| File | Purpose |
|---|---|
packages/backend/src/server/api/endpoints.ts | IEndpointMeta type definition |
packages/backend/src/server/api/ApiCallService.ts | Central permission enforcement |
packages/backend/src/core/RoleService.ts | getUserRoles, isAdministrator, isModerator |
packages/backend/src/models/Role.ts | MiRole entity with isAdministrator / isModerator columns |
packages/backend/src/server/api/endpoints/admin/accounts/create.ts | Example of inline custom permission logic |
packages/backend/src/server/api/endpoints/admin/meta.ts | Example of requireAdmin: true |
packages/backend/src/server/api/endpoints/admin/reset-password.ts | Example of requireModerator: true |