Skip to content

API keys

API keys are bearer tokens for non-interactive access - scripts, CI pipelines, cron jobs, and the automation / MCP endpoint. Unlike a login JWT, a key does not expire, and you can scope it down to exactly what it needs.

All endpoints need a bearer token (JWT, or an API key that itself has apikeys permissions).

Token format

A key looks like mck_ followed by 64 hex characters. Send it exactly like any other bearer token:

http
Authorization: Bearer mck_1a2b3c...

The API works out whether you handed it a JWT or a key from the mck_ prefix - same header either way.

List keys

http
GET /api/api-keys/

Returns your keys. The secret token is never included - only metadata (the name, a short prefix, when it was last used):

json
[
  {
    "id": "...",
    "name": "ci-deploy",
    "prefix": "mck_1a2b3c4d",
    "allowedIps": ["203.0.113.4"],
    "permissions": ["pods:read", "pods:update"],
    "lastUsedAt": "...",
    "createdAt": "..."
  }
]

Create a key

http
POST /api/api-keys/
json
{
  "name": "ci-deploy",
  "allowedIps": ["203.0.113.4", "198.51.100.0/24"],
  "permissions": ["pods:read", "pods:update"]
}
FieldRequiredNotes
nameyesA label so you remember what it is for.
allowedIpsnoList of IPs or CIDR ranges. If set, the key only works from those addresses.
permissionsnoArray of resource:action (or resource:*) tokens. Leave it empty for full access, capped to your own grants.

Returns 201 with the plaintext token. This is the only time you will ever see it:

json
{
  "id": "...",
  "name": "ci-deploy",
  "prefix": "mck_1a2b3c4d",
  "token": "mck_1a2b3c4d...<64 hex>",
  "permissions": ["pods:read", "pods:update"],
  "createdAt": "..."
}

Copy it now

We store only a hash of the token, so we can't show it to you again. Copy it into your secret manager the moment you create it. Lost it? Delete the key and make a new one.

Revoke a key

http
DELETE /api/api-keys/:keyId

Deleting a key revokes it - the next request using it fails. There is no un-delete and no expiry to wait for, so this is how you retire a key.

What a key can and cannot do

  • Keys never expire. They work until you revoke them.
  • A key can never exceed your own permissions. Its effective access is the overlap of what you asked for and what you are actually allowed to do. If your own grants shrink later, the key shrinks with them.
  • Some things are off-limits to keys entirely. A key can never hold team, roles, or account permissions - inviting teammates, editing roles, and changing account settings are interactive, owner-level jobs, not automation. See Team & roles for the full permission catalogue.
  • IP binding is optional but worth it for a key that lives in one place, like a CI runner or a fixed server. A request from an address outside allowedIps returns 403.

Same key, MCP too

The same key authenticates the automation / MCP endpoint, so an MCP client (Claude and others) can drive your account under the exact permissions you granted. Scope the key down, IP-bind it, and you have a safe automation credential.

Validation errors

ProblemStatus
Missing name400
An allowedIps entry is not a valid IP or CIDR400
permissions contains an unknown token400

Example

bash
curl -X POST https://cloud-api.microapps.io/api/api-keys/ \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name":"ci-deploy","permissions":["pods:read","pods:update"]}'

Built for the long tail.