Token scopes

A token carries a list of scopes. Every route checks for its scope and for the WordPress capability it needs before it runs, so a token can never do more than the account that created it. Give each token only what its job needs.

Plugin 1.7.024 scopes

On this page

How scopes work

  • Two checks, on every route. A request needs the route’s scope and the WordPress capability that route requires, such as edit_posts, upload_files, install_plugins or manage_options. A token made by an Editor cannot install plugins, whatever scopes it lists.
  • Read and write are separate. content:read never lets anything change. Writes need the matching …:write scope.
  • Publishing is its own scope. Without content:publish, a post or page created or updated with status “publish” is saved as a draft instead.
  • Dangerous scopes (marked below) are never in the default set, and the Tokens screen warns about each one when you tick it. The most destructive operations also ask for a confirmation step.
  • Some scopes are administrator-equivalent. fs:admin, db:write, cli:exec, system:backup, plugin:write, theme:write and admin:login let the token holder do what an administrator can. Treat a token that has any of them like an administrator password.

All scopes

Scopes marked default are the plugin’s suggested starting set for a content token. No dangerous scope is in it.

ScopeAllowsNotes
auth:readRead who the token belongs to (/whoami).default
audit:readRead the audit log and the debug.log tail.default · admin only
dashboard:readRead the dashboard statistics.default
content:readRead posts, pages, terms, search and multilingual data.default
content:writeCreate, edit and delete posts and pages (as drafts), create terms, set translations.default
content:publishPublish posts and pages directly.dangerous
media:readRead the media library and list unused media.default
media:writeUpload from a URL or base64, edit metadata, optimise and delete media, set media translations.default
seo:readRead SEO meta, analyse posts, audit, sitemap status and broken links.default
seo:writeChange SEO titles, descriptions and related meta; apply the safe fixes of an SEO audit.default
analytics:readRead traffic data from the site’s analytics plugin.default
theme:readRead the active theme and its files.
theme:writeWrite theme files, add custom CSS, switch theme.dangerous · administrator-equivalent
plugin:readList plugins (with available updates) and read plugin files.
plugin:writeWrite plugin files.dangerous · administrator-equivalent
plugin:installInstall from the WordPress.org directory, a URL or an uploaded zip; activate, deactivate, scaffold a new plugin.dangerous
site:readRead settings, menus, widgets, Customizer, performance data and maintenance status; list, read, search and download files.admin only for files
site:writeChange settings, menus, widgets and Customizer, toggle maintenance mode, clear debug.log, and change files inside the uploads folder only.dangerous · admin only for files and maintenance
fs:adminWith site:write: change any file under the site root, including code, except protected files.dangerous · admin only · administrator-equivalent
db:readRun SELECT queries through the SQL guard.admin only
db:writeRun INSERT, UPDATE and DELETE, each with a confirmation step.dangerous · admin only · administrator-equivalent
cli:execRun allow-listed WP-CLI commands. Off on every site until the operator enables it.dangerous · admin only · administrator-equivalent
system:backupCreate, list and restore full backups.dangerous · admin only · administrator-equivalent
admin:loginGet a one-time link, valid 60 seconds, that signs the token’s own user in to wp-admin.dangerous · admin only · administrator-equivalent

The two file powers

Since plugin 1.7.0, changing files takes one of two levels:

site:write

Changes files strictly inside wp-content/uploads, and only inert types: documents, images, audio, video and archives such as pdf, png, mp4, zip or docx. Anything else is refused with xaflo_fs_outside_uploads.

site:write + fs:admin

Changes any file under the site root, code included, except protected files (wp-config.php, .env, backups, the bridge’s own folder). Each overwrite, rename, delete and each executable or server-config write asks for confirmation first.

Reading files needs site:read and an administrator account. Secrets such as wp-config.php, .env files, backups, SQL dumps and debug.log are refused and hidden from listings at every level.

Sets that work

Reporting, read-only

Audits, analytics, SEO reviews. Cannot change anything.

auth:readcontent:readseo:readanalytics:readsite:read

Content editor

Drafts, SEO fixes and images. Nothing goes live without you.

content:readcontent:writemedia:readmedia:writeseo:readseo:write

Publisher

The editor set, plus the right to publish.

content:writecontent:publishmedia:writeseo:write

Xaflo Desktop, full control

Remote → Files beyond uploads, Deploy and “Open wp-admin” signed in. Administrator-equivalent: keep it on your own computer.

plugin:readplugin:installsite:readsite:writefs:adminadmin:login

Keep fs:admin, db:write, cli:exec and admin:login out of everyday tokens. If you need one, create a short-lived token for that job and revoke it when you are done.

Rate limits per scope

Every token can make 60 requests per minute by default; administrators signed in to wp-admin are limited the same way. Sensitive scopes have tighter limits of their own, per token:

ScopeRequests per minute
cli:exec5
system:backup5
db:write10
plugin:install10
theme:write20
plugin:write20
media:write30
content:publish30

Above the limit the API answers 429 with a Retry-After header. Site operators can change the global limit and the per-scope overrides in the plugin settings.

Lifetime and revocation

  • A token expires after the number of days you chose (1 to 365, default 30). Expired tokens are cleaned up by a daily job.
  • Revoke a token at any time from Xaflo → Tokens. It stops working on the next call.
  • A token only works on the site that issued it: its issuer must match the site address. A staging copy with a different address needs its own tokens.
  • Rotate secret in Xaflo → Settings invalidates every token at once. After updating to 1.7.0 this is required: see Upgrading to 1.7.0.