> ## Documentation index
> Fetch the complete documentation index at: https://rolter-ai-rolter.docs7.io/llms.txt
> Ask it with GET https://rolter-ai-rolter.docs7.io/ask?q=<keywords or question>. Short keywords rank best.
> Use these to discover all available pages before exploring further.

# Scoped API Tokens for Automation

> Mint a named control-plane token that holds one role at an organization, team or project, with an expiry, for CI jobs and provisioning scripts that should not run as the admin token or as a person.

A program that manages rolter through the control-plane API, such as a CI job that rotates a project key, a GitOps pipeline that applies routes or a script that creates a project per customer, used to choose between two credentials: the **admin token**, which is superadmin over the whole deployment and shared by everything that holds it, or a **person's session**, which belongs to a browser and expires. An **API token** is a third one: a named service account that holds **one role at one organization, team or project**.

The control plane resolves the token to that role, so every permission check works exactly as it does for a person holding it. A token with the `member` role on one project can do what a project member can do there and nothing else.

## What a token can and cannot do

- It holds one built-in role (`admin`, `member`, `viewer`) or one [custom role](/security/rbac#custom-roles-and-access-profiles) of the organization, at the scope it was minted for. It reaches that scope and everything below it, never a sibling or the level above.
- It **never** reaches deployment-wide settings (feature flags, the security settings, cluster nodes, alerting, the configuration export) and never holds a [deployment role](/security/rbac#deployment-roles). Those stay with the admin token, superadmins and the deployment roles.
- It **cannot manage tokens**: minting, listing, rotating and revoking answer `403` for a token, so a leaked one cannot mint a successor that outlives its own revocation.
- It reads request logs and analytics for the scope it holds, by the same rules as a person with that role: the rows of its project, team or org, and no others. The same read covers what shares that guard: the CSV export of the request log, the savings report, provider health, the log sampling rate and the MCP tool-call log. The captured request and response bodies are withheld unless the token's role reaches the project's `request_payload` floor: a `member` token or better reads them, and a `viewer` token reads them only on a project whose admin lowered the floor to `viewer` (`payload_min_role`). It is not a session: the dashboard's account endpoints answer `401`.
- It **never grants access**: adding, changing or removing a membership, sending or revoking an invitation, editing a custom role or its assignments, resetting a password, editing an account, and changing an SSO provider, an LDAP directory, a SCIM token, a group mapping or the org's sign-in policy all answer `403` for a token, whatever its role. It can still read them. Access a leaked token handed out would outlive the token's revocation, so these stay with people.
- Otherwise an `admin` token can do what an admin of its scope can do. Give automation the narrowest role that does the job.

It is not a virtual key (the data plane, `/v1/*`) and not a SCIM token (provisioning, `/scim/v2/*`); each is refused at the other's door. See [which key do I need](/security/which-key).

## In the dashboard

**Governance › API tokens** lists the organization's tokens with their scope, role, prefix, expiry, last use and state (active, expired or revoked), mints one (the secret is shown once, with a copy button), and rotates or revokes one after a confirmation. It takes the same roles as the API: minting, rotating and revoking need admin at the token's own scope. A revoked or expired token cannot be rotated.

## Mint a token

Minting takes an **admin of the token's own scope**: an org admin mints org-wide, team and project tokens, and a project admin mints tokens for that project only. A token therefore never holds more than the person who made it.

```bash
curl -s -X POST https://control.example.com/api/v1/orgs/$ORG_ID/api-tokens \
  -H "Authorization: Bearer $ROLTER_SESSION_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name": "ci-deploy", "project_id": "'$PROJECT_ID'", "role": "member", "expires_in_days": 30}'
```

| Field             | Meaning                                                                                           |
| ----------------- | ------------------------------------------------------------------------------------------------- |
| `name`            | required, at most 80 characters; it is what the audit log shows                                   |
| `team_id`         | scope the token to a team; omit both ids for an org-wide token                                    |
| `project_id`      | scope the token to a project (its team, if named, must match)                                     |
| `role`            | `admin`, `member` or `viewer`                                                                     |
| `custom_role_id`  | an org-defined role of this organization instead; give exactly one of `role` and `custom_role_id` |
| `expires_in_days` | `1` to `730`; **90** when omitted                                                                 |
| `never_expires`   | `true` opts out of the expiry; it cannot be combined with `expires_in_days`                       |

The response is the token row plus `secret`, a `rolter_api_…` value. **The secret is shown once.** Rolter stores only a peppered SHA-256 digest of it, the same way it stores sessions and virtual keys, so a lost secret is rotated, not looked up.

Use it like any control-plane credential:

```bash
curl -s https://control.example.com/api/v1/routes \
  -H "Authorization: Bearer rolter_api_…"
```

## List, rotate and revoke

| Request                                | Does                                                                                                                                                |
| -------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
| `GET /api/v1/orgs/{org_id}/api-tokens` | lists the organization's tokens, revoked and expired ones included, with the `token_prefix`, scope, role, expiry and `last_used_at`; never a secret |
| `POST /api/v1/api-tokens/{id}/rotate`  | returns a new `secret`; the old one stops working in the same instant. A revoked or expired token answers `409` `api_token_inactive`                |
| `DELETE /api/v1/api-tokens/{id}`       | revokes the token; it stops resolving on its next request                                                                                           |

An org admin lists every token of the organization; a team or project admin lists the tokens of the scopes they administer. A token also stops working when it expires, when its organization, team or project is deleted, or when its custom role is deleted.

A token outlives the person who minted it, so revoke the tokens of anyone who leaves: `created_by` names the minter.

## Audit

Minting, rotating and revoking write `api_token.create`, `api_token.rotate` and `api_token.revoke` to the organization's audit log, naming the token and its scope but never the secret. Everything else a token does that is audited has **no actor account** and carries the token's `id` and `name` in `detail.api_token`, so a pipeline's changes are told apart from a person's and from another pipeline's.
