Files
vantage-docs/docs/reference/api-tokens.md
T

8.4 KiB

id, title, sidebar_label
id title sidebar_label
api-tokens API tokens API tokens

A session cookie is fine for a browser. A script, a CI job or a cron task needs something it can hold onto instead - an API token.

Creating one

API Keys, in the Access group of the sidebar. The page is reachable at every role: any member may create and revoke their own keys, and owner and admin additionally see every key in the instance.

Create key opens a dialog with four decisions, in the order they matter:

  1. Name and role. The name says what will use the key - the CI pipeline, the script, the cluster. The role list offers your own role and everything below it, never above.
  2. Scopes. A grid of resources against read and write. Ticking write also ticks read, since write already satisfies read on the same resource. Read-only everywhere and Clear all set the whole grid at once.
  3. Restrict to servers tagged. Optional; see Tag restrictions below.
  4. Expiry. Each option names the date it resolves to, so "90 days" and "7 December 2026" are the same choice read two ways.

Beneath them sits a preview line that reads the key back as a sentence - "gitea-ci-deploy acts as admin, may read and write servers and workflows, read secrets, and stops working on 7 December 2026." Read it before you submit; an over-granted key is far easier to spot in a sentence than in a grid of ticks.

The value is shown once, in full, immediately after creation:

vt_8f2c1a9e4b6d0735a1c8e29f4b0d6e17...

That is the only time you will see it. Vantage stores a hash of the token, never the value itself, so if you lose it there is no support ticket that gets it back - create a new token and revoke the old one.

The panel showing it also carries a ready-made curl line and a summary of what was granted, so the key can go straight into a secret store without a second trip to the list.

Scopes

A token can reach only what its scopes name. Each resource has a :read and a :write scope, and holding :write on a resource also satisfies a :read requirement for it - you do not need to tick both.

Resource Covers
servers Fleet list, server detail, agent commands, tags
keys SSH key library and assignment
secrets The vault
workflows Steps, workflows, runs and their logs
monitors Monitors, incidents, uptime and notification channels
vulns Vulnerability findings, packages and scan rules
workloads Containers and systemd units, including control actions and logs
patching Maintenance windows, patch policies and patch runs. patching:write creates and edits them and starts or cancels runs
settings Instance settings, members, single sign-on, licence, and token management itself

A token created with only servers:read can list and inspect servers but cannot run a workflow against them, touch a key, or read a secret - each of those needs its own scope.

Tag restrictions

A key can be pinned to part of the fleet as well as part of the API. Restrict to servers tagged in the create dialog offers the tag keys and values already in use across your servers, and the key then reaches only servers carrying every pair listed - the restriction is an AND, not an OR. Leaving it empty is the opposite: no restriction at all, the whole fleet.

The restriction is fixed at creation, like the role and the scopes. Changing what a credential already deployed in CI can reach, with no record of what it could reach before, is worse than requiring a rotation - so to widen or narrow one, create a replacement and revoke the old key.

Restricted keys show their tags as chips beside their scopes in the list. Unrestricted keys show nothing there, which is the common case.

The restriction applies to every API token, not only ones handed to an MCP agent. A CI token, a monitoring script's token and an agent's token are all held to the same tag scope check wherever the service layer resolves servers - the mechanism does not know or care what kind of caller is holding the token.

Nor can a token created under a restricted token reach further than its creator: minting a new key from an already-restricted key can only narrow the tag set, never widen or drop it. A env=staging token cannot mint a token that also sees production.

Reading the key list

Each key is one record rather than a row of bare strings:

  • Key - the name, the vt_ prefix hint, the holder (when viewing all keys) and the role.

  • Scopes - one chip per resource, its access half tinted: rw in accent, r in grey. A key with nothing granted says so in words rather than showing a dash.

  • Lifetime - a bar showing how much of the key's issued life is left, with the date beside it. Four states, and the label always says which:

    Bar Means
    Green More than seven days left
    Amber Seven days or fewer - rotate it
    Red Already expired; the key no longer authenticates
    Grey, full width No expiry at all

    A key issued before the instance's maximum lifetime was tightened also carries "outside the current policy - rotate when convenient". That is a prompt, not a failure: the cap is never applied retroactively and the key keeps working.

  • Last call - when the key last authenticated, or Never used.

Above the list, four counts summarise the same thing at fleet scale: keys listed, keys expiring within seven days, keys that never expire, and keys never used since they were issued. They describe the list as filtered, so they change with the My keys / All keys toggle.

A token never outranks its owner

A token's role can be at most the role of the person who created it, and its effective role is recomputed on every request as the lower of the two - not fixed at creation. Demote the person from owner to member and every token they hold drops to member from that request onward. Remove the person and every token they hold stops working immediately: a token has no existence independent of its owner.

Expiry

An expiry is optional on a token you create. An instance can set a maximum key lifetime (Settings → Integrations) that caps how far out a new token's expiry may be set; when that cap is in place, a token with no expiry at all is refused, so there is no way to route around the policy by leaving the field blank.

Changing the maximum lifetime only affects tokens created afterwards. It does not shorten, extend or invalidate a token that already exists.

Using a token

Send it as a bearer token:

curl -H "Authorization: Bearer vt_…" https://acme.vantage.example.com/api/servers

Everything else about the REST API applies the same way it does to a session - JSON errors, audit logging, licence gating on writes - except that authority comes from the token's role and scopes rather than a signed-in person's role.

Rate limit

A token is limited to 600 requests per minute. Going over it gets a 429 with a Retry-After header naming how many seconds to wait. Cookie sessions are not subject to this limit; it exists so a runaway script cannot take an instance down, not as a general throttle.

Rotating a token

  1. Create the replacement token first, with the scopes and role you need.
  2. Deploy it wherever the old one was used, and confirm it works.
  3. Revoke the old one.

Doing it in that order means there is no gap where the credential in use has already been deleted.

The full reference

This page covers the token model. Every route, request and response shape is in the generated OpenAPI reference, served by your own instance at /api/docs - not this documentation site, since the routes and their shapes are specific to your install. The raw document is at /api/openapi.json.

:::danger Not the External Secrets token The bearer token read by GET /api/secrets/:group/values for the Kubernetes External Secrets Operator is a separate credential - a single instance-wide value, rotated from Settings, that reaches only that one endpoint. It is not an API token and an API token cannot be used in its place: the two are checked by different code, and neither substitutes for the other. See Secrets. :::