Skip to content

Mint a system key

View as Markdown
POST
/v1/system/keys
curl --request POST \
--url https://example.com/v1/system/keys \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{ "scopes": [ "system:tenants" ], "label": "example", "expiresAt": "2026-04-15T12:00:00Z" }'

A system key (kgi_sy_…) is the operator’s, for a service that acts for it (sign-up, the orchestrator, billing, the license renewal), with the least scope that service needs. It acts in no tenant: it reaches /v1/system/* and the deployment’s license, and every other route refuses it (system-key-on-tenant-route). Every request it makes is recorded. Only the full system capability (kindgi:system: the deployment’s own token, or a full system key) mints one, and a key can’t outlive the key minting it. Returns the plaintext token exactly once. On a runtime serving one tenant, only the deployment’s own token reaches the system keys, and a key holds system:license alone: it reads GET /v1/license and GET /v1/license/usage, for the license renewal, and every other route refuses it.

Idempotency-Key
string
>= 1 characters

Caller-supplied idempotency key, scoped to the caller: the same key from someone else in the tenant is their own request (from 0.1.5). Retries with the same key return the original response byte-identical (per docs/API-ROUTE-CONVENTIONS.md §3.1). A retry sent while the first request still runs is answered 409 idempotency-key-in-flight with Retry-After, on a runtime whose store holds keys (from 0.1.5); retry after it, and you get the first request’s answer. An answer that carries a secret (a new API key or public run token, a session token, a generated signing secret) isn’t kept: a retry gets 409 idempotency-key-replay-withheld, with the first request’s status and when it succeeded (from 0.1.5).

Media typeapplication/json
object
scopes
required

The least the key’s service needs; kindgi:system alone for a full key.

Array<string>
>= 1 items unique items
Allowed values: system:tenants system:tenants:create system:tenants:image-prefix system:tenants:production system:tenants:limits system:tenants:contacts system:tenants:purge system:suspend system:deployments system:pack-env system:usage:read system:license kindgi:system
label
string
>= 1 characters <= 100 characters
expiresAt

When it stops working. A minter that expires mints only keys expiring no later than it.

string format: date-time

System key minted.

Media typeapplication/json

The new system key, plus its secret.

object
id
required

The key’s id.

string
label

What the key is for, as given at mint.

string
scopes
required
Array<string>
Allowed values: system:tenants system:tenants:create system:tenants:image-prefix system:tenants:production system:tenants:limits system:tenants:contacts system:tenants:purge system:suspend system:deployments system:pack-env system:usage:read system:license kindgi:system
createdAt
required
string format: date-time
expiresAt
string format: date-time
revokedAt
string format: date-time
mintedBy
required

Who minted it: a system key’s id, or boot for the deployment’s own token.

string
token
required

Plaintext bearer token (kgi_sy_…). Returned exactly once at mint time.

string
Example
{
"scopes": [
"system:tenants"
]
}

Malformed request body: no scopes, one that is not a system scope, a scope twice, kindgi:system beside another, a past expiresAt, or an empty label; on a runtime serving one tenant, any scope but system:license.

Media typeapplication/json
object
error
required
object
code
required

Stable machine-readable discriminant. Values match domain error codes (see docs/API-ROUTE-CONVENTIONS.md §4.3).

string
message
required
string
details

Optional, kind-specific.

object
key
additional properties
any
requestId
required

Server-assigned request id; also echoed via X-Request-Id header.

string
Examplegenerated
{
"error": {
"code": "example",
"message": "example",
"details": {},
"requestId": "example"
}
}

Missing / malformed / expired / revoked bearer token.

Media typeapplication/json
object
error
required
object
code
required

Stable machine-readable discriminant. Values match domain error codes (see docs/API-ROUTE-CONVENTIONS.md §4.3).

string
message
required
string
details

Optional, kind-specific.

object
key
additional properties
any
requestId
required

Server-assigned request id; also echoed via X-Request-Id header.

string
Examplegenerated
{
"error": {
"code": "example",
"message": "example",
"details": {},
"requestId": "example"
}
}

A tenant’s key or session (system-principal-required); a scoped system key (system-scope-missing, details.scope kindgi:system; on a runtime serving one tenant, system-key-scope-not-served for one holding anything but system:license); a key that would outlive the key minting it (token-expiry-exceeds-minter, its details.latestExpiresAt the latest allowed); a full key minted by another system key without expiresAt (system-key-expiry-required: only the deployment’s own token mints one that never expires).

Media typeapplication/json
object
error
required
object
code
required

Stable machine-readable discriminant. Values match domain error codes (see docs/API-ROUTE-CONVENTIONS.md §4.3).

string
message
required
string
details

Optional, kind-specific.

object
key
additional properties
any
requestId
required

Server-assigned request id; also echoed via X-Request-Id header.

string
Examplegenerated
{
"error": {
"code": "example",
"message": "example",
"details": {},
"requestId": "example"
}
}

Idempotency-Key reused with a different body (idempotency-key-body-mismatch), or a retry of a request that succeeded: its answer carried a secret, which isn’t kept (idempotency-key-replay-withheld).

Media typeapplication/json
object
error
required
object
code
required

Stable machine-readable discriminant. Values match domain error codes (see docs/API-ROUTE-CONVENTIONS.md §4.3).

string
message
required
string
details

Optional, kind-specific.

object
key
additional properties
any
requestId
required

Server-assigned request id; also echoed via X-Request-Id header.

string
Examplegenerated
{
"error": {
"code": "example",
"message": "example",
"details": {},
"requestId": "example"
}
}

The request body is over the API’s limit (request-too-large; details.maxBytes says how much).

Media typeapplication/json
object
error
required
object
code
required

Stable machine-readable discriminant. Values match domain error codes (see docs/API-ROUTE-CONVENTIONS.md §4.3).

string
message
required
string
details

Optional, kind-specific.

object
key
additional properties
any
requestId
required

Server-assigned request id; also echoed via X-Request-Id header.

string
Examplegenerated
{
"error": {
"code": "example",
"message": "example",
"details": {},
"requestId": "example"
}
}

Server error (unmapped domain code or framework crash).

Media typeapplication/json
object
error
required
object
code
required

Stable machine-readable discriminant. Values match domain error codes (see docs/API-ROUTE-CONVENTIONS.md §4.3).

string
message
required
string
details

Optional, kind-specific.

object
key
additional properties
any
requestId
required

Server-assigned request id; also echoed via X-Request-Id header.

string
Examplegenerated
{
"error": {
"code": "example",
"message": "example",
"details": {},
"requestId": "example"
}
}

The operator’s access record can’t be written, so nothing was done (access-record-unavailable): a request that changes something is recorded before it acts.

Media typeapplication/json
object
error
required
object
code
required

Stable machine-readable discriminant. Values match domain error codes (see docs/API-ROUTE-CONVENTIONS.md §4.3).

string
message
required
string
details

Optional, kind-specific.

object
key
additional properties
any
requestId
required

Server-assigned request id; also echoed via X-Request-Id header.

string
Examplegenerated
{
"error": {
"code": "example",
"message": "example",
"details": {},
"requestId": "example"
}
}

See also