Skip to main content
This page is for whoever decides what each OpenType API key is allowed to do. It lists the nine scopes, shows which scopes each organization role holds, explains the rules that limit the scopes a new key can get, and gives ready-made scope sets for common workloads. For the full route-by-route table, see Scopes reference.

How authorization works

  1. Every protected route demands a scope. POST /v1/runs demands runs_write, for example. Creating a service-account key demands members_write on top of keys_write.
  2. A credential carries a set of scopes. An API key carries the scopes it was created with. A console session carries the scopes of your role.
  3. If the credential lacks the route’s scope, the request is refused with 403 scope_denied and the message names the missing scope.
The message reads “session” for API keys too. Branch on error.code, and read the scope name from the message when you need to show it to a person.

The nine scopes

Scope names are snake_case, exactly as below, in requests, responses and error messages.

Roles and the scopes they hold

Your role in an organization decides which scopes your console session holds, and so which scopes you can put on a key you create. A role that is not in this table holds no scopes, so every scoped route answers 403 scope_denied. What that means in practice:
  • Only owner and admin hold members_write, so only they can create a service-account key.
  • owner, admin and billing hold billing_write, so only they can buy credits or change auto-recharge.
  • A member can send runs and manage keys but cannot change billing.
  • A viewer can read runs, keys, usage and balance, and cannot create anything.
See Organizations and roles for how organizations and roles fit together.

Rules for a key’s scopes

The creator ceiling applies to whatever credential makes the call. A key that holds keys_write and runs_read can create keys with keys_write, runs_read or both, and nothing else.
Scopes are checked against the creator only once, when the key is created. If the person who created a key later moves to a role with fewer scopes, the keys they already created keep every scope they were given. When someone’s access shrinks, review the keys they created (created_by on each key) and revoke the ones they no longer should control.

Least-privilege scope sets

Start from the smallest set that works, and add a scope only when a request returns 403 scope_denied for a route the process really needs. Other habits that keep the blast radius small:
  • One key per process and per environment. A staging key should never be able to spend production credit.
  • Never give keys_write to a key that also runs production traffic. A key with keys_write can revoke your other keys, and a rotation returns the rotated key’s new secret.
  • Give runs_write and billing_write only where needed. They are the two scopes that spend money.
The console’s key form offers six scopes (runs_write, runs_read, keys_read, keys_write, usage_read, billing_read). To create a key with members_read, members_write or billing_write, use POST /v1/keys.

Principal: who a key acts as

Each key has a principal, {"type": "user" | "service_account", "id": "..."}, which records who the key acts as. You set it with the optional principal field on POST /v1/keys. The service-account id is a label you choose, such as svc-nightly-batch. OpenType does not keep a separate list of service accounts. Whatever the principal, the key’s scopes still cannot exceed yours, and created_by always records who created the key. Use a service-account key for keys that belong to a system rather than a person, so the principal on each key in GET /v1/keys shows which keys belong to workloads.

Errors