diff --git a/CHANGELOG.md b/CHANGELOG.md
index fcc41d7..3db0a64 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -29,6 +29,25 @@ ADR-007 and ADR-002.
with a create modal that reveals the secret once (copy button) and an admin
All Tokens section. Docs: `docs/IMPORT-API.md` and `docs/CONFIG.md` updated to
recommend a PAT for imports. Core feature; no plugin-contract change.
+- Optional permission scopes on personal API tokens. A token MAY carry a scopes
+ list (permission names, migration `7d22_apitokens_scopes` adds the nullable
+ `apitokens.scopes` JSON column); NULL keeps the original behavior (acts as its
+ owner). A scoped token grants ONLY the listed permissions, intersected with
+ what the owner actually holds at use time, and SUSPENDS the admin-role bypass,
+ so a scoped token minted by an admin is genuinely limited: it is denied on
+ role-gated (`require_role`) endpoints and gets no import mode. The shim mints
+ the request JWT with a `patscopes` claim that `require_permission`,
+ `require_role`, and `import_mode_active` read; normal login JWTs carry no such
+ claim and are unaffected (zero regression). Scopes are validated at write time
+ against the token OWNER's permissions (the scope ceiling - a token can never
+ grant more than its owner holds; when an admin edits another user's token the
+ ceiling is that owner's permissions), rejecting unknown or unheld names 400.
+ Minting/managing tokens now requires the new `apitokens.create` permission
+ (category `apitokens`; admins hold it by default, grantable via the roles UI)
+ rather than being open to any authenticated user. The Settings > API Tokens
+ create/edit modals gain a "Restrict permissions" section (a category-grouped
+ checkbox grid limited to the permissions the creator holds) and the token
+ lists show a full-access / N-permissions access chip.
- Vendor-model photos on asset detail heroes: computers and printers now
surface the linked model's `imageurl` in their extension payloads (the
field machines already exposed), and the machine, PC, printer, network
diff --git a/docs/CONFIG.md b/docs/CONFIG.md
index 5e51785..a1e0761 100644
--- a/docs/CONFIG.md
+++ b/docs/CONFIG.md
@@ -231,6 +231,15 @@ is stored; the secret is shown once at creation. This is the recommended
credential for long-running imports (see `docs/IMPORT-API.md`). There is no env
var to configure; PATs are managed entirely through the API/UI.
+Creating or managing a PAT requires the `apitokens.create` permission (admins
+hold it by default; grant it to other roles from Settings > Users & Roles). By
+default a PAT is unscoped and acts with the full authority of its owner. A PAT
+may optionally carry a scopes list (a subset of the owner's permissions, capped
+at what the owner actually holds): a scoped token grants ONLY those permissions,
+intersected with the owner's live permissions at use time, and suspends the
+admin bypass, so it is denied on role-gated (admin-only) endpoints and on import
+mode. Use an unscoped token for admin-only work and imports.
+
### identifiers (dynamic)
One boolean key per asset identifier per asset type, keyed
diff --git a/docs/IMPORT-API.md b/docs/IMPORT-API.md
index 1a99b6e..b6c6d50 100644
--- a/docs/IMPORT-API.md
+++ b/docs/IMPORT-API.md
@@ -55,6 +55,13 @@ mode) as its owning admin, exactly as a login JWT would, but without the hourly
expiry. Revoke it from the same Settings page (or `DELETE /api/apitokens/Authorization: Bearer shopdb_pat_.... Ideal for long-running
- imports that would otherwise die when the login JWT expires.
+ imports that would otherwise die when the login JWT expires. A token may
+ be restricted to a subset of your permissions; a restricted token cannot
+ reach admin-only (role-gated) endpoints or import mode.
{{ token.displayprefix }}...{{ token.displayprefix }}...