Migrating to categorical scopes
UTM moved from a long list of fine-grained scope literals (trades:read, signals:read:all, queues:write:all, and so on) to nine categorical scopes. This page is for anyone holding a token issued under the old model.
If you are issuing a new token, you do not need this page; go straight to the scope reference.
Your existing tokens keep working
You do not have to do anything. Every token issued under the old model was rewritten in place to the categorical scopes that cover the same access. The rewrite was a one-time migration over the stored token records, so a token that previously held, say, trades:read and positions:read now holds trading:read and authenticates exactly as before. No token was regenerated, so the token string in your integration is unchanged and continues to work.
The legacy X-API-Key: utm_* header also still authenticates tokens issued before the credential unification, against the same scope checks.
What changed and why
The old model had a separate read scope per resource (trades:read, positions:read, signals:read, and so on) and a parallel *:read:all family for cross-user admin reads. That was a large surface to reason about, and it conflated two genuinely different concerns: reading per-user data by an opaque userId, and resolving that userId to a real-world identity.
The categorical model collapses the per-resource reads into four personal-grant scopes and splits admin reads into pseudonymous (admin:read:user) and identity-bearing (admin:read:identity). The result is a shorter list that maps to how access actually clusters. See the scope reference for the full catalogue, including what each scope does not grant and the never-delegate list.
Mapping table
Every old scope maps to exactly one or, in two cases, two categorical scopes. No access was dropped without a replacement.
| Old scope | Now covered by | Notes |
|---|---|---|
signals:write | signals:write | Unchanged. |
accounts:read | accounts:read | Same name, broader: now also covers brokers, balances, reconciliation reads, and sync status. |
signals:read | trading:read | Folded into the general trading read. |
trades:read | trading:read | |
positions:read | trading:read | |
strategies:read | trading:read | |
logs:read | activity:read | Your own activity feed. |
trades:read:all | admin:read:user | Per-user reads keyed by opaque userId. |
positions:read:all | admin:read:user | |
orders:read:all | admin:read:user | |
signals:read:all | admin:read:user | |
strategies:read:all | admin:read:user | |
accounts:read:all | admin:read:user | |
brokers:read:all | admin:read:user | |
sync:read:all | admin:read:user | |
reconciliation:read:all | admin:read:user | |
apps:read:all | admin:read:user | |
notifications:read:all | admin:read:user | |
logs:read:all | admin:read:user | Audit and system logs, now pseudonymous by userId. |
activity:read:all | admin:read:user | |
users:read:all | admin:read:identity | Responses include email and name, so this is the identity scope. |
queues:read:all | admin:read | System-wide queue stats. |
health:read:all | admin:read plus admin:read:user | The catalogue endpoint stays system-wide; per-user invariant runs are pseudonymous. A holder gained both so no access was lost. |
queues:write:all | admin:write plus admin:destructive | Single-job control moved to admin:write; mass clear moved to admin:destructive. A holder gained both. |
Suggested action: re-issue for clearer audit trails
Re-issuing is optional, but worth doing. A token migrated automatically holds whatever the translation produced, which can be broader than the consumer actually uses. Issuing a fresh token through the categorical scope picker lets you grant the minimum the integration needs and gives you a cleaner audit trail keyed to the categorical names from day one.
- Review what the integration actually calls and pick the smallest set of categorical scopes that covers it. The common combinations table is a good starting point.
- Issue a new token with those scopes from Settings -> Access tokens.
- Update the integration to use the new token.
- Revoke the old token once the new one is in use.