Mint a token
Prompt:
I need a token so GitHub Actions can deploy this app.
Also works:
- "Give the contractor a way to read this app's logs without my sign-in."
- "The token in the pipeline leaked. Kill it and make a new one."
- "Which tokens are still live on this account?"
What your tool does
- Calls
list_applicationsfor the application's identifier. Callslist_tokensfor the existing tokens, with their labels, scopes, grants, expiry, and last use, so it mints no duplicate and finds the one to revoke. - Calls
mint_tokenfrom your signed-in session. It usesscope_kindapplicationwith the application's identifier for work on one application, oraccountfor work across the account. - Requests no grant unless the task needs a destructive action, sets
expires_in_dayswhen the task has an end, and sets alabelthat identifies the consumer. - Gives you the value once, for the pipeline's secret store or the tool's credential settings, and writes it into no file it commits. If it keeps the value itself, it keeps it with its environment values.
- For a deploy pipeline, mints the token as A token for a CI job describes, and writes one step. The step runs the unattended deploy line of the turnzero-cloud command, with
TURNZERO_CLOUD_MINTED_TOKENset from the pipeline's secret store. - For a pipeline that deploys without the command, writes the pipeline's steps:
- upload the artifact to the storage routes with the headers
X-Acting-Identityandx-turnzero-cloud-environment, naming the environment the deploy goes to; POSTtohttps://turnzero.ai/api/v1/actions/deploywith the token as the bearer credential;- read
read_statusuntil the deploy ends.
- upload the artifact to the storage routes with the headers
- For an unattended
provision, a CI job or a script of your own, mints a token bounded to the application, as Running on your machine describes. A local run from your tool needs no token, because its line carries a grant. - On a leak, calls
revoke_tokenwith the token'sidfromlist_tokens, then mints a replacement and gives it to you the same way. - Asks you nothing before minting and asks for no browser approval, because
mint_tokenandrevoke_tokenare reversible-tier actions. A destructive action the token requests later is approved by a person in the browser, never by the token or the tool.
What you need
- A safe place to keep the token once it's created, such as your pipeline's secret store or your tool's credential settings. Never save it in a file you commit to your project.
- For a token with the
issuesgrant, a Turn Zero account holding Turn Zero Blueprint. During the private beta, Blueprint comes by invitation.
Before your AI starts
This section is for your AI tool: what it checks and gathers before it begins. You don't need to do these steps yourself.
- A signed-in session in your connected tool (Connect your tool). A minted token or an application's platform credential cannot mint.
- For an application-scoped token, the application's identifier from
list_applications.
Sign-in, sessions, and tokens explains what a minted token is and how it compares with the other credentials.
Steps
1. Mint it
Call mint_token from a signed-in session with these members:
| Member | What it contains |
|---|---|
scope_kind |
account or application. The scope is fixed at minting. |
application |
The application's identifier. Required for application scope, and refused for account scope. |
grants |
Optional. An array of destructive, super_admin, synthetic_seed_purge, synthetic_estate, publication, feedback_queue, and issues. Request only what the unattended task needs. |
space |
Only with the issues grant. The identifier of an issue space your account owns, as list_issue_spaces returns it. |
level |
Only with the issues grant. The grant level: report, contribute, or owner; see A token for one issue space. |
expires_in_days |
Optional. An integer from 1 to 3650. Without it, the token does not expire. |
label |
Optional. 1 to 120 characters, to identify the token later. Required with the issues grant. |
The token receives only the grants the minting session has and requests. With the destructive grant, a token can only request a destructive action, and a person approves it in the browser. The super_admin, synthetic_seed_purge, synthetic_estate, publication, and feedback_queue grants are for platform staff (Management action tiers and approvals). From any other session, the mint refuses each of them grant_not_held. An application-scoped token cannot have any of those, or the issues grant. A token cannot mint another token.
A token for one issue space
An issue space, such as a repository's issue list, stores issues and the reports filed about them. Your account can have up to fifty issue spaces. Feedback and ratings shows how to create one.
The issues grant lets a program work in one space without having that space's own credential, which the platform keeps. Any signed-in session of your account can mint a token with this grant. Give the space in space and the grant level in level:
reportfiles reports, confirms a report as a repeat, posts a test run's result, and reads the space, apart from its restricted issues. Your own issue spaces says what thereportlevel reads.contributedoes all of that and also works on issues: it updates them, comments on them, links related issues, and takes on and gives back work. It lists, reads, and works on restricted issues as on any other, but it cannot remove the restricted mark.ownercan use every operationrelay_issue_actaccepts, including settling issues, recording fixes and builds, configuring the space, and exporting it.
The grant and relay_issue_act need a Turn Zero account that has Turn Zero Blueprint. During the private beta, Blueprint comes by invitation. Without it, the mint is refused 403 blueprint_required, and so is every relayed call, whatever space it names. If Blueprint is later removed from the account, its next relayed call is refused the same way.
The label is required with this grant. It identifies who uses the token, such as a teammate's clone or a build step. The platform records every write made with the token under that label. It must use printable characters only. No other unrevoked token for the same space may have the same label.
A token with the issues grant can call relay_issue_act for its one space, list_tokens, and the public reads of the library and the published context. Every other action refuses it 403 issues_bounded. It cannot reach any storage area or upstream.
An application-scoped token works on its one application. It can call:
- actions whose subject is that application;
read_accountandread_plan_quotas;list_context,read_context, andread_documentation;- the read of a pending action whose subject is that application;
store_secretandrotate_secretwhen they name that application.
Every other action refuses it 403 token_scope_refused, list_secrets among them, because it lists the whole account. One action on its own application is also refused: halt_environment on production returns 403 account_credential_required, because stopping production is an account-level action. resume_environment is allowed.
The value is returned once. Store it in your tool's credential or environment settings. If it appears in a chat, a log, or a commit, revoke it and mint a replacement.
A token from Turn Zero Blueprint's command
The platform serves the request below for Turn Zero Blueprint's command. The command's released version does not make it, so the steps describe the request as the platform answers it.
Turn Zero Blueprint keeps a repository's issue list in one of your issue spaces. The request gets that space's token through your own browser, so no token passes through a chat or is typed into a terminal:
- The request opens the platform's sign-in page in your browser. If this browser signed in within the last 8 hours, you go straight to step 3.
- You sign in, or create an account where the sign-in page offers it.
- The confirm page says which account you are signed in as. If it is the wrong one, choose Not you? to sign this browser out and sign in again.
- The page lists your issue spaces, each with its creation date and the labels of its tokens. Choose one, or create a new space. If the request names a space, the page shows that space alone, and offers no new one.
- The page shows a request code and asks you to confirm only where it matches the code the program that opened the request shows on your computer. The page names the token's label, which identifies the clone the token is for, and the
ownergrant level.
Confirming sends that program a code, which it exchanges once at /approve/blueprint/token. The exchange mints the token, with the issues grant at the owner level for the space you chose. Nothing is created until the exchange, which must come within a minute of your confirmation, and that includes a new space you asked for. A code never exchanged leaves nothing behind.
If the platform creates the new space you asked for but cannot then mint its token, or your sign-in ends while the token is minted, the space stays, with no token. The exchange's refusal names that space. A new request can choose that space on the confirm page.
If the request code does not match the one shown on your computer, choose Cancel. Another program on this computer asked for that token.
Each request keeps its own confirmation in your browser for ten minutes. A website that keeps opening such requests while you are signed in can crowd out your browser's other turnzero.ai cookies, which signs you out of some pages. Nothing is exposed, and signing in again restores them.
Each clone keeps one label. When a request from the same clone exchanges its code, the new token replaces the clone's earlier one, which stops working at that exchange. The confirm page says so before you confirm. A token you minted with mint_token, and a token of another space or another account, is never replaced.
The token works as a token minted with the issues grant works. It can call relay_issue_act for its space, list_tokens, and the public reads. It has no expiry date and no refresh token. list_tokens lists it under its label, and revoke_token ends it.
The token also ends on its own in four ways:
- It goes 30 days without being used. Each call made with it counts as a use.
- You choose Sign out everywhere. Its answer counts these tokens as
exchange_tokens_revoked. - You undo a passkey change. The undo's answer counts them the same way.
- An operator suspends your account. Reinstating the account does not bring the token back.
A token you minted with mint_token ends in none of these ways. Once a clone's token has ended, make the authorization request again from that clone. It mints a new token under the same label. When you retire a clone, revoke its token with revoke_token rather than wait for the 30 days.
A refusal on the confirm page is shown in the browser and returned to the program that opened the request. A refusal at the exchange is answered to that program alone. Two refusals, rate_capped and internal, can come before the confirm page is read, and then appear in the browser alone. A new request, where a remedy below names one, starts again at step 1:
| Refusal | Cause | Remedy |
|---|---|---|
blueprint_required |
Your account does not have Turn Zero Blueprint. | Blueprint comes by invitation during the private beta. Make a new request once your account has it. |
space_not_owned |
The request names a space your account does not own, or your account no longer owns the space you chose. | Sign in with the account that owns the space, or make a new request and choose a space of yours. |
label_in_use |
A token you minted with mint_token has the same label in that space. |
Revoke that token with revoke_token, or choose another space. |
space_creation_ceiling |
You asked for a new space, and your account already has fifty. | Make a new request and choose one of your existing spaces. |
feedback_rate_limited |
You asked for a new space, and your account created as many spaces as it may within the minute. | Make a new request once the minute turns, or choose an existing space. |
issue_service_unreachable |
You asked for a new space, and the platform could not create it at the issue service. | Make a new request after a short wait. |
not_yet_provisioned |
The platform you reached serves no issue service, so it issues no issue space token. | Nothing on your side corrects this until that platform serves one. |
invalid_grant |
Your sign-in ended before the code was exchanged, for example because you chose Sign out everywhere, or the exchange came more than a minute after you confirmed. If your sign-in ended while the token was being minted, the token is ended and not sent. | Make a new request and sign in. |
account_suspended |
Your account is suspended. | Make a new request once an operator reinstates it. |
rate_capped |
Your network sent the platform more requests in the minute than it admits, so the confirm page or the exchange was refused. On the confirm page it appears in the browser alone. An IPv6 address counts as its whole /64 network. | Wait for the minute to pass, then make a new request. |
internal |
The platform failed while answering, for example because it could not read its records for the confirm page or the exchange. On the confirm page it appears in the browser alone. | Make a new request after a short wait. If it repeats, report the reference its detail names. |
access_denied |
You chose Cancel on the confirm page. | Make a new request when you want to connect. |
Sign-in, sessions, and tokens describes the request and the addresses it uses.
A token for a CI job
A continuous integration (CI) job that deploys runs with no person present, and its token stays in the job's settings for as long as the job exists. So mint that token with two limits:
scope_kindapplication, with the one application the job deploys. A copy of the token can then act on that application and on no other.expires_in_days, set to how long the job needs the token. A copy that leaks stops working at the expiry, even if no one notices the leak and revokes it. Mint a replacement before the expiry, and store it the same way.
Keep the value in the job's secret store, and have the job set it as the environment variable TURNZERO_CLOUD_MINTED_TOKEN. The turnzero-cloud command reads the token from that variable, never from an argument or a file. Deploying unattended gives the line the job runs and says where the command sends the token.
2. List and revoke
list_tokens returns each token's identifier, scope, grants, and label, without the value. A token with the issues grant also shows its space and level. It also returns three times: when the token was minted, when it expires, and when it was last used. A null last-use time means no request has used the token yet.
revoke_token revokes a token by its identifier. Requests using it are then refused at once on the Hypertext Transfer Protocol (HTTP) application programming interface (API) and the Model Context Protocol (MCP) endpoint. On the storage, logging, and egress routes, the refusal starts within the credential interval that Sign-in, sessions, and tokens gives. Revoking the same token again keeps the first revocation's time.
list_tokens lists a revoked or expired token for thirty days after it ended. The platform then deletes its row, and revoke_token naming it returns not_found.
3. Use it
Send the token as a bearer credential to the management HTTP API at https://turnzero.ai/api/v1/actions/<action_name>. Every action accepts POST, and observe actions also accept GET. The MCP server accepts the token too, with its scope and grants. So does the storage API, so a script can upload a deploy artifact.
A call that sends a member the action does not take is refused 400 invalid_request, and the refusal names the members the action takes.
A token belongs to no environment. So a call under it names the environment in the header x-turnzero-cloud-environment, development or production, on these routes:
- the storage file routes, the file list, and the transfer-grant mint (Store files);
- the keyed egress route;
- the session verification route, where the body member
environmentcan be sent instead.
Without it, the call is refused 400 environment_required.
The logging ingest reads the environment from each batch's own environment member, so it never refuses a batch as environment_required. If the header is also sent, it must match the member, or the batch is refused 403 environment_mismatch.
Every action a token performs is recorded under that token's own identity, so you can tell which consumer did what.
Expected result
mint_token returns the token record and the value, once. The record contains:
id,scope_kind,application(null for an account-scoped token),grants, andlabel;spaceandlevel, only on a token with theissuesgrant;created_at, andexpires_at(null when no expiry was set);revoked_at(null), andlast_used_at(null until a request uses the token).
list_tokens then lists the same record without the value. Each request the consumer makes is recorded under the token's identity. revoke_token returns the id and revoked_at, list_tokens shows the time, and a later request under the token is refused.
Refusals
A refusal states the action, gives its cause in detail, and mints or revokes nothing. The first eight rows belong to the three token actions; the rest are refusals a token meets in use.
| Refusal | Status | Cause | Remedy |
|---|---|---|---|
session_credential_required |
403 | mint_token was called under an account-scoped minted token. An application-scoped token is refused token_scope_refused first, and a platform credential app_credential_not_admitted. |
Call it from the signed-in session in your connected tool. An unattended provision runs under a token bounded to the application, minted with mint_token from your signed-in session. For other calls, the token you already have may work. An application-scoped token works on the storage, egress, logging, and action routes within its scope. An account-scoped token works on the storage routes, keyed upstreams, and the action routes. The logging routes and the platform's ai-allowance upstream require an application-scoped token. |
invalid_request |
400 | A member breaks the rules in step 1, or revoke_token has no id; detail names it. With the issues grant, this includes a missing space, level, or label, a label with a character that is not printable, and a label another unrevoked token for the same space already has. A space or level sent without the issues grant is refused here too, whether or not your account owns the space. |
Correct the named member and call again. |
space_not_owned |
403 | With the issues grant, space is not the identifier of a space your account owns. |
Use an identifier that list_issue_spaces returns, or create a space with create_issue_space. |
blueprint_required |
403 | With the issues grant, your account does not have Turn Zero Blueprint. A call through relay_issue_act or create_issue_space is refused the same way. |
Blueprint comes by invitation during the private beta. Once your account has it, mint again. read_account lists the products your account has. |
no_such_application |
404 | application names no application of your account. |
Use the identifier list_applications returns. |
grant_not_held |
403 | The minting session does not have the requested grant; the refusal's grant member names it. |
Leave the grant out, or mint from a session that has it. |
grant_scope_refused |
403 | super_admin, synthetic_seed_purge, synthetic_estate, publication, feedback_queue, or issues was requested for an application-scoped token. |
Leave the grant out, or mint an account-scoped token. |
not_found |
404 | revoke_token named an id that is not a token of your account, or a token whose row the platform deleted thirty days after it was revoked or expired. |
Use an id from list_tokens. A deleted token is already refused everywhere, so nothing is left to revoke. |
issues_bounded |
403 | A token with the issues grant called an action outside relay_issue_act, list_tokens, and the public reads; admitted lists what it can call. |
Call the action from your signed-in session, or under a token minted without the grant. |
synthetic_seed_purge_bounded |
403 | A token with the synthetic_seed_purge grant, a platform staff grant, called an action outside the three it can call and the public reads; admitted lists the three. |
Call the action from your signed-in session, or under a token minted without the grant. |
token_scope_refused |
403 | An application-scoped token named another application, or called an action outside the list in step 1. | Use a token for that application, or an account-scoped token. |
account_credential_required |
403 | halt_environment on production was called under an application-scoped token. |
Halt under your signed-in session or an account-scoped token. |
environment_required |
400 | A call under the token on a route listed in step 3 named no environment. | Send the header x-turnzero-cloud-environment with development or production, or the body member environment on the verification route. |
environment_mismatch |
403 | On the logging ingest, the header named a different environment from the batch's environment member. |
Make the two match, or drop the header. |
Related
- Sign-in, sessions, and tokens compares every credential and states what ends each one.
- What happens without asking lists the actions a token requests and a person approves.
- Management action tiers and approvals explains the tiers behind a token's grants.
- Running on your machine states the token an unattended
provisionruns under. - Store files states the environment header rule on the storage routes.
- mint_token, list_tokens, and revoke_token in the generated reference give each action's arguments and result.
- Glossary defines the terms used on this page.