---
title: "Keys and sign-in · API reference · Promigence"
description: "The Promigence API's keys and sign-in routes: 12 in all, with parameters, request bodies and answers."
url: "https://www.promigence.ai/docs/reference/api/keys-and-sign-in"
site: "Promigence"
---

[API reference](https://www.promigence.ai/docs/reference/api)

# Keys and sign-in

12 routes of the published API contract, generated from it.

### GET/v1/auth/claim

Auth: none

The page where the free credit is claimed, in a browser: the offer, the terms to accept, and the Claim button. Opened from the single-use link `POST /v1/credits/claim-link` makes (`promigence credits claim`); the link's token is the authority.

#### Parameters

tquery · string

#### Answer 200 · object · application/json

### GET/v1/auth/cli-callback

Auth: none

The page a browser lands on after sign-in; in headless mode it shows the code to paste back.

#### Parameters

codequery · string

errorquery · string

statequery · string

#### Answer 200 · string · text/html

### POST/v1/auth/cli/requests

Auth: none

Start `promigence login` through the console: register the sign-in request (the PKCE S256 challenge, the state, the local port the CLI listens on or none to paste the code, the computer's name and the new key's name) and get the authorize page to open for it. The page shows the signed-in person what is asking, and when and from where the request was made; it refuses a request that is more than ten minutes old or was already answered. `promigence login` does this for you.

#### Request body CliRequestCreate · application/json

code_challengerequiredstring

`base64url(sha256(code_verifier))`: the PKCE challenge (RFC 7636), 43 characters.

code_challenge_methodrequiredstring

`S256`, the only method accepted.

devicestring | null

The computer's name, shown on the page as the client reports it (at most 64 characters).

key_namestring | null

The new key's name (at most 64 characters; default `cli@<device>`).

portinteger | null

The local port the client listens on for the code: one of `GET /v1/auth/config`'s `loopback_redirect_uris`. Absent: the page shows the code, to paste into the client.

providerstring | null

`github` or `google`: a browser that is not signed in goes straight to that sign-in method.

refstring | null

A referral code, applied if this sign-in creates the account.

staterequiredstring

Handed back with the code, unchanged: 8 to 128 URL-safe characters.

#### Answer 201 · CliRequestCreated · application/json

authorize_urlrequiredstring

The authorize page for this request.

expires_in_srequiredinteger

Seconds the request waits to be authorized; after that the page refuses it.

request_idrequiredstring

`creq_…`: names the request.

### POST/v1/auth/cli/token

Auth: none

Finish `promigence login` after you authorized the CLI in the browser: exchange the one-time code the authorize page gave the CLI, with the PKCE verifier whose S256 challenge the CLI sent there, for an API key (`api_key`, in this answer only). A code works once, for five minutes, and only with its own verifier and the redirect it was delivered to; any other attempt uses it up. `promigence login` does this for you; `GET /v1/auth/config` names the authorize page in `console_authorize_url`.

#### Request body CliTokenCreate · application/json

coderequiredstring

The one-time code the authorize page handed the client (single use, five minutes).

code_verifierrequiredstring

The PKCE verifier whose S256 challenge the client sent to the authorize page.

redirect_uristring | null

The loopback redirect the code was delivered to; absent for a code that was pasted.

#### Answer 201 · Session · application/json

api_keystring | null

**The secret of the key that was minted, sent once.** Only when `mint_key` was asked for.

createdrequiredboolean

True when this call created the account.

keyKeyView | null

The key that was minted, without its secret. Only when `mint_key` was asked for.

orgrequiredSessionOrg

The organisation a sign-in lands in.

referralReferralApplied | null

Only when a first sign-in sent a referral code (`promigence login --ref`): what became of it. A code that does not apply never stops the sign-in.

trialSessionTrial | null

Only when the account was created: what the trial granted.

userrequiredUserView

A user, as the sign-in and organisation routes report one.

### GET/v1/auth/config

Auth: none

What `promigence login` needs to start a sign-in: the identity domain, client id and scopes, and the console page where you authorize the CLI (`console_authorize_url`, when it is offered).

#### Answer 200 · AuthConfig · application/json

authorize_urlrequiredstring

client_idrequiredstring

console_authorize_urlstring | null

Where a command-line client sends the browser to have the signed-in person authorize it (`promigence login`): the client registers its request first (`POST /v1/auth/cli/requests`, which answers the page's address for it); the page shows the request and asks for a click, then hands the client a one-time code it exchanges at `POST /v1/auth/cli/token`. Absent when that page is not offered; a client then signs in through `authorize_url` as before.

identity_providersrequiredmap of string

The sign-in methods to offer, as name -> label (`email`, `google`, `github`). A client that asks the sign-in pages for one method passes the label as their `identity_provider`, except `email`, which is the pages' own form and needs none.

invite_modeboolean

True while new accounts need an invite code: a client redeems one (`POST /v1/auth/invite`) before it starts the sign-in (`promigence signup`). An existing account signs in as before either way.

loopback_redirect_urisrequiredstring[]

The redirect URIs a command-line client may listen on.

paste_redirect_urirequiredstring

Where a headless sign-in lands instead, to show a code to paste back.

scopesrequiredstring[]

token_urlrequiredstring

### POST/v1/auth/invite

Auth: none

Redeem an invite code for one sign-in attempt, before the sign-in starts (`promigence signup` does it for you). Only while `GET /v1/auth/config` says `invite_mode`: the attempt with the same login nonce may then create an account within `expires_in_s`. Every code that does not redeem gets the same `403 invite_invalid`; attempts are rate limited per address.

#### Request body InviteRedeem · application/json

coderequiredstring

The invite code.

noncerequiredstring

The sign-in attempt's login nonce.

#### Answer 200 · InviteRedeemed · application/json

expires_in_srequiredinteger

Seconds the redeemed code holds this sign-in attempt's place (0 when invite mode is off).

invite_moderequiredboolean

False when invite mode is off: no code is needed and none was looked at.

### POST/v1/auth/invite/release

Auth: none

Give back the place a redeemed invite code holds for a sign-in attempt that ended without an account (it timed out or was cancelled), so the next attempt can redeem the code at once (`promigence signup` does it for you). Only the attempt's own login nonce names its hold, and a hold that already created an account is never given back. Always `200 {released}`; rate limited per address.

#### Request body InviteRelease · application/json

noncerequiredstring

The sign-in attempt's login nonce.

#### Answer 200 · InviteReleased · application/json

releasedrequiredboolean

True when this attempt held a place and gave it back; false when it held nothing (it never redeemed a code, its hold had lapsed, it already created the account, or invite mode is off).

### POST/v1/auth/session

Auth: sign-in token

Exchange an identity token for a Promigence API key. The first call for an identity creates the user, the org, its free credit offer (claimed later in a browser, `POST /v1/credits/claim-link`) and the first key, in one transaction. One account per verified email address: a first sign-in whose address already has an account through another sign-in method creates nothing and is answered `409 account_exists`, naming the method to sign in with. While invite mode is on, a first sign-in whose attempt redeemed no invite code (`POST /v1/auth/invite`) creates nothing and is answered `403 invite_required`; an existing account is never asked for a code.

#### Request body SessionCreate · application/json · optional

key_namestring | null

The minted key's name (default `cli`, at most 64 characters).

mint_keyboolean

Also mint an API key.

noncestring | null

The login nonce, when the sign-in was started with one.

refstring | null

A referral code.

#### Answer 200 · Session · application/json

api_keystring | null

**The secret of the key that was minted, sent once.** Only when `mint_key` was asked for.

createdrequiredboolean

True when this call created the account.

keyKeyView | null

The key that was minted, without its secret. Only when `mint_key` was asked for.

orgrequiredSessionOrg

The organisation a sign-in lands in.

referralReferralApplied | null

Only when a first sign-in sent a referral code (`promigence login --ref`): what became of it. A code that does not apply never stops the sign-in.

trialSessionTrial | null

Only when the account was created: what the trial granted.

userrequiredUserView

A user, as the sign-in and organisation routes report one.

### GET/v1/keys

Auth: API key

List your org's keys: with an API key, its own project's; with an identity token, every project's. `?all=1` includes revoked ones.

#### Parameters

allquery · string

#### Answer 200 · KeyList · application/json

keysrequiredKeyView[]

org_idrequiredstring

### POST/v1/keys

Auth: API key

Mint a key. `api_key` is in the 201 response and is never retrievable again. A key minted by a key stays in that key's project, and is revoked when that key is; a service key cannot mint. A key does not expire unless you give it an expiry; past it, the key answers `401 key_expired`, and the org's owners are mailed 14 and 3 days before.

#### Request body KeyCreate · application/json · optional

accessstring | null

`full` (the default) | `run` (sandboxes, runs and builds, whose runs can use the project's stored secrets; no changes to secrets, keys or billing) | `read` (reads everything in the project, file contents and command output included; changes nothing).

expires_atstring | null

A date (`2027-01-31`) or a UTC time ending in `Z`.

expires_in_daysinteger | null

1–3650.

namestring | null

Default `cli`, at most 64 characters.

#### Answer 201 · KeyView · application/json

accessstring

What the key may do: `full`, `run` (sandboxes, runs and builds, whose runs can use the project's stored secrets; no changes to secrets, keys or billing) or `read` (reads everything in the project, file contents and command output included; changes nothing).

also_revokedstring[] | null

Only on the answer to `DELETE /v1/keys/{key_id}`: the key ids this revocation also revoked, because the key had minted them (directly or further down). Absent when the key replaced itself (`?reason=replaced`), which revokes nothing it minted.

api_keystring | null

**The secret, and the only time it is ever sent.** Only on the 201 from `POST /v1/keys`; it cannot be retrieved afterwards.

created_atrequiredstring

RFC 3339.

created_bystring | null

The user who minted it; `null` for a key minted by another key.

currentboolean | null

True for the key this request was made with. Absent from the answer that mints a key, which is not yet the key you are calling with.

expires_atstring | null

RFC 3339: when the key stops working, as chosen when it was created. `null` = it does not expire (the default). An expired key answers `key_expired`.

key_idrequiredstring

last_used_atstring | null

RFC 3339; `null` for a key that has never been used.

minted_bystring | null

The key that minted this one; `null` for a key minted by a sign-in. Revoking a key revokes every key it minted, and every key those minted.

namerequiredstring

networksKeyNetwork[] | null

The networks the key was used from, most recent first (at most 20): each an IPv4 `/24` or an IPv6 `/64`, never a full address, with when it was first and last seen there. On the key list; absent elsewhere.

prefixrequiredstring

The first few characters, enough to recognise a key without holding it.

revokedboolean | null

Only on the answer to `DELETE /v1/keys/{key_id}`.

revoked_atstring | null

RFC 3339; `null` while the key still works.

### DELETE/v1/keys/{key_id}

Auth: API key

Revoke a key, and every key it minted (and every key those minted): `also_revoked` lists them. Your own key is yours to revoke; another member's key, or any service key, needs the owner role; a service key may revoke only itself. `?reason=replaced` or `?reason=logout` from the key itself (the CLI rotating or ending its session key) revokes only that key.

#### Parameters

key_idrequiredpath · string

reasonquery · string

#### Answer 200 · KeyView · application/json

accessstring

What the key may do: `full`, `run` (sandboxes, runs and builds, whose runs can use the project's stored secrets; no changes to secrets, keys or billing) or `read` (reads everything in the project, file contents and command output included; changes nothing).

also_revokedstring[] | null

Only on the answer to `DELETE /v1/keys/{key_id}`: the key ids this revocation also revoked, because the key had minted them (directly or further down). Absent when the key replaced itself (`?reason=replaced`), which revokes nothing it minted.

api_keystring | null

**The secret, and the only time it is ever sent.** Only on the 201 from `POST /v1/keys`; it cannot be retrieved afterwards.

created_atrequiredstring

RFC 3339.

created_bystring | null

The user who minted it; `null` for a key minted by another key.

currentboolean | null

True for the key this request was made with. Absent from the answer that mints a key, which is not yet the key you are calling with.

expires_atstring | null

RFC 3339: when the key stops working, as chosen when it was created. `null` = it does not expire (the default). An expired key answers `key_expired`.

key_idrequiredstring

last_used_atstring | null

RFC 3339; `null` for a key that has never been used.

minted_bystring | null

The key that minted this one; `null` for a key minted by a sign-in. Revoking a key revokes every key it minted, and every key those minted.

namerequiredstring

networksKeyNetwork[] | null

The networks the key was used from, most recent first (at most 20): each an IPv4 `/24` or an IPv6 `/64`, never a full address, with when it was first and last seen there. On the key list; absent elsewhere.

prefixrequiredstring

The first few characters, enough to recognise a key without holding it.

revokedboolean | null

Only on the answer to `DELETE /v1/keys/{key_id}`.

revoked_atstring | null

RFC 3339; `null` while the key still works.

### POST/v1/orgs/{org}/keys

Auth: API key

Mint a key in an organization you belong to, in one of its projects. With an API key, only in that key's own organization; with a sign-in, in any of yours. `service: true` (owners only) makes a project's key that keeps working when the member who minted it leaves, and that cannot manage the organization; any other key is revoked with its minter's membership.

#### Parameters

orgrequiredpath · string

#### Request body OrgKeyCreate · application/json · optional

accessstring | null

`full` (the default) | `run` (sandboxes, runs and builds, whose runs can use the project's stored secrets; no changes to secrets, keys or billing) | `read` (reads everything in the project, file contents and command output included; changes nothing).

defaultboolean

Also make this organization your default.

expires_atstring | null

A date or a UTC time ending in `Z`.

expires_in_daysinteger | null

1–3650.

expires_in_minutesinteger | null

1–1440: a short-lived key, its lifetime counted on the server's clock.

namestring | null

Default `cli`, at most 64 characters.

projectstring | null

A project id or name. Default: the calling key's project, or the default project.

serviceboolean

A service key: not tied to a person.

#### Answer 201 · OrgKeyView · application/json

accessstring

What the key may do: `full`, `run` (sandboxes, runs and builds, whose runs can use the project's stored secrets; no changes to secrets, keys or billing) or `read` (reads everything in the project, file contents and command output included; changes nothing).

api_keyrequiredstring

**The secret, and the only time it is ever sent.**

created_atrequiredstring

RFC 3339.

created_bystring | null

The user who minted it.

expires_atstring | null

RFC 3339: when the key stops working, as chosen when it was created. `null` = it does not expire (the default).

key_idrequiredstring

namerequiredstring

org_idrequiredstring

prefixrequiredstring

project_idrequiredstring

servicerequiredboolean

A service key (CI, a worker pool) keeps working when the member who minted it leaves; a member's own key is revoked with their membership.

[Every route](https://www.promigence.ai/docs/reference/api) · [what each error means and whether it was billed](https://www.promigence.ai/docs/errors)
