Appearance
API Tokens
Last updated
An API token is a long-lived, revocable credential for the Configuration API at /api/v1. Use one for a provisioning job, a fleet audit or a CI pipeline — anything that runs without a person signing in.
A token is not a user account: it has no password, no session and no second factor, it does not expire when someone signs out, and revoking it affects nothing else. It does act on behalf of the admin who created it, with that user's access as it is now — see Whose access a token has below.
Note: API tokens work only on
/api/v1. The rest of the API (/api/...), the Public Data API and the Historian API do not accept them — those need a user sign-in (see REST API Reference).
Who can manage tokens
Only admin users. The page is System → API Tokens (/admin/api-tokens). It is part of every edition.
Create a token
- Open System → API Tokens and click New token.
- Enter a Name — (how you will recognize it later), for example
Fleet provisioning (CI). - Tick the Scopes the job needs. Leave
config:readticked (see the warning below). - Optionally pick an Expires date. Blank means never.
- Click Create token.
- The panel Copy this token now — it will not be shown again shows the token and a ready-made
curlline. Click Copy, store the token in your CI system's secret store, then click I have copied it.
| Field | What it does | Default | Rules |
|---|---|---|---|
| Name | Label shown in the list and in the audit log | empty | Required; leading/trailing spaces are trimmed |
| Scopes | What the token may do | config:read ticked | At least one |
| Expires | The last day the token works — it is refused from the end of that day, in your browser's time zone | blank (never) | Optional date; can't be in the past |
| Scope | Allows |
|---|---|
config:read | Every /api/v1 endpoint except import: the listings, /config/schema, /config/export, /config/preview |
config:write | /config/import, which changes configuration, and nothing else |
Each scope stands alone. A token with only config:write can import a bundle but gets 403 This token does not have the "config:read" scope. from every other endpoint, including /config/preview. A job that previews before it imports needs both scopes.
The token list
| Column | Meaning |
|---|---|
| Name | With a Revoked or Expired badge when it no longer works; dead tokens are dimmed |
| Token | The first characters, for example sk_scadaink_Ab3dE9… — enough to match a token found in a log |
| Scopes | :write scopes are highlighted |
| Last used | Updated on every accepted request; Never used usually means the integration was never finished |
| Expires | Date and time, or Never |
The heading shows how many tokens are active.
How tokens behave
- Format. Every token starts with
sk_scadaink_followed by 43 random characters (32 random bytes, base64url). The prefix lets secret scanners and people recognize it. - Shown once. The appliance stores only a SHA-256 hash. There is no way to display an existing token again; if one is lost, revoke it and create another.
- Header only. Send
Authorization: Bearer sk_scadaink_…. A token in the query string is ignored, because URLs end up in access logs, browser history andRefererheaders. - One error for every bad token. Missing, mistyped, revoked and expired tokens all get the same
401 A valid API token is required. Send it as: Authorization: Bearer <token>— the API does not tell a caller which of those it was. A valid token lacking a scope gets403naming the scope. - Expiry. A date picked on the page is stored as the end of that day in your browser's time zone, so a token set to expire on 31 December works all of 31 December. Through the API, a bare date such as
2027-01-01means the end of that day in the appliance's time zone; send a full ISO timestamp to set an exact moment. - Revocation takes effect on the next request and cannot be undone. Revoked tokens stay in the list so the audit trail still shows which credential made a change.
- Rate limit. Each token may make 120 requests per minute to
/api/v1. - Audit. Creating and revoking a token are recorded in the Audit Log under the admin who did it and in the system log. An import made with a token is logged as
v1.config.importwith the token's name. - Backups. Token hashes are part of the configuration database, so a restored backup brings its tokens (and their revocations) with it.
Whose access a token has
A token never sees more than the user who created it could see in the app. That user's role, dashboard permissions, dashboard view groups and feature restrictions are read on every request, so a change to the user changes what their tokens can do straight away.
| The creator is now… | What the token gets |
|---|---|
| An admin | Everything its scopes allow |
| Not an admin (the role was changed) | /api/v1/dashboards lists only the dashboards that user may open; /tag-udts, /local-tags and /expression-tags answer 403 if that user is restricted from the feature; /config/schema, /config/export, /config/preview and /config/import answer 403, because a bundle holds whole dashboards and pages whatever their access settings, and the app's own export is for admins only |
| Disabled or deleted | Every request is refused with 403 The user who created this token no longer has an active account. Create a new token. |
So when an admin leaves or stops being an admin, have another admin create replacement tokens before the old account is changed.
Rotate a token
There is no rotate button; rotation is create-then-revoke:
- Create a new token with the same scopes and a name that shows the date, for example
Fleet provisioning (CI) 2026-09. - Put the new value in your secret store and run the job once.
- Check that the new token's Last used has a time and the old one's has stopped changing.
- Revoke the old token: click the bin icon, then Revoke.
Revoke a token
Click the bin icon (Revoke this token) in the token's row, then Revoke to confirm. The API also offers:
| Method | Path | Purpose |
|---|---|---|
| GET | /api/admin/api-tokens | List tokens (never the secret) and the available scopes |
| POST | /api/admin/api-tokens | { name, scopes, expiresAt } → { token, plaintext } |
| DELETE | /api/admin/api-tokens/:id | Revoke |
These three need an admin user JWT — an API token cannot create or revoke tokens.
Troubleshooting
| Symptom | Cause | Fix |
|---|---|---|
401 A valid API token is required… | Token missing, mistyped, revoked, expired, sent as ?token=, or a user JWT sent to /api/v1 | Check the list for a Revoked/Expired badge; send it as a Bearer header |
403 This token does not have the "config:read" scope. | Only config:write was ticked | Create a token with both scopes |
403 This token does not have the "config:write" scope. | Read-only token used for import | Create a token with config:write as well |
403 The user who created this token no longer has an active account… | The creator was disabled or deleted | An admin creates a new token |
403 This endpoint needs a token created by a user who is currently an admin. | A bundle endpoint, and the creator is no longer an admin | An admin creates a new token |
403 The user who created this token does not have access to this feature. | The creator is restricted from Tag UDTs, Local Tags or Expression Tags | Lift the restriction, or use a token created by an admin |
/api/v1/dashboards leaves some dashboards out | The creator is not an admin and may not open them | Use a token created by an admin |
401 No token provided when calling /api/devices with the token | API tokens only work on /api/v1 | Use /api/v1/devices, or a user login for /api |
At least one scope is required. | No scope ticked (API callers) | Send a non-empty scopes array |
The expiry date could not be read. | expiresAt is not a date (API callers) | Send an ISO date such as 2027-01-01 |
The expiry date is already in the past. | The chosen date or time has passed | Pick a later date, or leave it blank |
| Create token is grayed out | Name is empty or no scope is ticked | Fill both |