Appearance
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"]
}| Field | Required | Notes |
|---|---|---|
name | yes | A label so you remember what it is for. |
allowedIps | no | List of IPs or CIDR ranges. If set, the key only works from those addresses. |
permissions | no | Array 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/:keyIdDeleting 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, oraccountpermissions - 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
allowedIpsreturns 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
| Problem | Status |
|---|---|
Missing name | 400 |
An allowedIps entry is not a valid IP or CIDR | 400 |
permissions contains an unknown token | 400 |
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"]}'