API tokens and the HTTP API¶
A password belongs to a person at a browser. Everything else that calls the API uses a personal API token: a build job, a deployment script, another service.
Issue a token¶
Open the profile screen of the account and add a token. Give it a name, the scopes that it needs, and the number of days until it expires. Zero days means that it does not expire on its own.
Midair shows the token once, at the moment that it makes it, and it keeps only a hash. Nothing can show the token again. Copy it before you leave the screen.
midair token issue makes a token from the command line. See Command-line client.
A token looks like this:
mid_<id>_<secret>
Send it in the Authorization header:
Authorization: Bearer mid_<id>_<secret>
Scopes¶
A token is issued for named scopes, and never for everything. A token in a CI variable costs less to lose than the password that it stands in for, and that holds only while it can do less.
Scope |
What it opens |
|---|---|
|
Read the runs, the analyses, the comments and the log pages behind them. |
|
Start test runs and upload logs. |
|
Start and stop analyses. |
|
Write comments on results. |
|
Start and stop monitored devices, and send them commands. |
|
Upload builds to the distribution registries. |
|
Let an AI assistant use this account through the MCP endpoint. See MCP endpoint. |
A scope is a ceiling and not a grant. A call with a token acts as the owner of the token, and it is subject to the same team seats as the screens. See Users, teams and access.
The token list itself is out of reach of every token. Use a password to issue, list or revoke a token, so that the loss of one token cannot be turned into keeping one.
The collections¶
The item API of the core reads and writes the collections. A token with the
read scope reads these:
test, analysis, test_suite, workspace, runtime,
comment, team, notification, node, distribution,
distribution_test, distribution_runtime
A token writes a collection with the scope that the collection asks for:
Collection |
Scope to write |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
The routes¶
These routes belong to Midair itself. Each one names the scope that it needs.
Route |
Scope |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
The full description¶
The server describes its own HTTP surface. Two addresses serve it:
GET /openapi.jsonAn OpenAPI 3.1 document for this deployment, with the plugin routes in it.
GET /docsThe same document as a static page. It uses no scripts and no external files, so it works offline.
The server generates the document rather than shipping it, because half of the
surface exists only at run time. Both addresses are public. A description is
not a credential, and every endpoint in it still authenticates its own callers.
An instance that prefers not to publish the list starts the core with
--openapi-private, which serves both to administrators only.