Tokens
An API token is a bearer credential you create in the dashboard, not a byproduct of logging in. Every request to the REST API authenticates with one.
Account vs. server tokens
| Kind | Prefix | Where it works | Created from |
|---|---|---|---|
| Account | plx_acc_ | Every server you can currently reach | /account/api-tokens in the dashboard |
| Server | plx_srv_ | The one server it was created on | that server's API section |
Pick a server token when a script or bot only ever needs one server — a lost or leaked token can only touch that server. Pick an account token for tooling that spans your whole account (a CI job that deploys to several servers, for example).
Creating a token
- Go to
/account/api-tokens(account token) or your server's API section (server token). - Click Create Token.
- Select the scopes it needs — see the scope tables. Grant only what the integration actually uses.
- Optionally set an IP allowlist (a list of CIDR ranges the token will accept requests from) and an expiry.
- Name the token and confirm.
The token value is shown exactly once, right after creation. Plex Host stores only its hash, so if you lose it, revoke it and create a new one — there is no way to retrieve it again.
Scopes are capped by your team role
A token can never exceed what its owner can currently do. Granting a server token
canRestoreBackups only works if you hold canRestoreBackups on that server yourself; the same
intersection applies continuously, not just at creation — if your team role changes later, every
token you've issued is re-evaluated against the new role on each request.
IP allowlist
When set, requests from any other source address are rejected before the token is even checked against scopes. Leave it empty to allow any source address. Useful for pinning a token to a known server or office egress IP.
Expiry
A token with no expiry is valid until revoked. An expired token behaves like a revoked one —
requests fail with 401.
Rotating a token
There's no in-place "regenerate" — rotation is create-then-revoke:
- Create a new token with the same (or updated) scopes.
- Update your integration to use the new value.
- Confirm the new token is working.
- Revoke the old token.
This avoids a window where neither token works, at the cost of briefly having two live tokens for the same integration.
Revoking a token
Revoke from the same list you created it in (/account/api-tokens or the server's API
section). Revocation is immediate and irreversible — a revoked token's requests fail with 401
from that point on.
Plan changes
Token capacity and API access are plan entitlements, so a downgrade doesn't delete anything — it suspends:
- Plan drops below the plan's API-enabled tier — every token on the account is suspended with
API_DISABLED_FOR_PLAN. Requests fail with403until the plan is upgraded again, at which point the same tokens resume working with no need to recreate them. - Plan drops the token limit below what's already issued — the excess tokens are suspended
with
PLAN_LIMIT, oldest usage last, until the count is back under the new cap or the plan is upgraded and the cap rises again.
Leaving a team
Server tokens are scoped to the server, not to your session — but they still borrow your access. If you leave (or are removed from) the team that owns a server, every server token you created on it is revoked immediately. Account tokens are unaffected for servers you still have access to through other teams.
Introspection
Given a token, GET /api/v1/me/tokens/current reports what it is without exposing the token value
itself — its kind, scopes, expiry, and (for a server token) which server it's bound to. Useful for
an integration to confirm its own credential on startup.
Authorization
bearer In: header
Response Body
application/json
application/json
curl -X GET "https://example.com/api/v1/me/tokens/current"{
"data": {
"expiresAt": "string",
"kind": "server",
"name": "string",
"quota": {
"monthResetAt": "string",
"requestsPerMinute": 0,
"requestsPerMonth": 0,
"requestsThisMonth": 0,
"tokensPerServer": 0
},
"scopes": [
"string"
],
"serverId": "string",
"tokenId": "string"
},
"meta": {
"requestId": "string"
}
}{
"error": {
"code": "string",
"details": [
"string"
],
"message": "string",
"requestId": "string",
"retryAfterSeconds": 0
}
}