Skip to content

API keys

Preview This resource manages the keys that authenticate every other call. You can list, create, update, and revoke API keys programmatically, roll a key to a new secret with a grace window so nothing breaks mid-rotation, and read your current rate-limit budget. Creating a key reveals its secret exactly once — there’s no way to read it back later.

For what keys are, the credential families (mfk_live_…, mfs_live_…), and how to mint your first one in the dashboard, see API keys and creating keys. This page is the API for managing them once you’re automating.

Minting and rotating keys requires the keys:write scope.

keys:write

There is no admin scope. Keys are forced to Role=client, so a key — even one minted by an admin — can never act as platform admin. See the security model.

Method + path Scope Does
GET /v1/api-keys keys:write list your keys (metadata only — never the secret)
POST /v1/api-keys keys:write create a key → reveals the secret once
GET /v1/api-keys/{id} keys:write get one key’s metadata
PATCH /v1/api-keys/{id} keys:write update name, scopes, TTL, or IP allowlist
DELETE /v1/api-keys/{id} keys:write revoke a key immediately
POST /v1/api-keys/{id}/roll keys:write rotate to a new secret with a grace window
GET /v1/rate-limits any introspect your current rate-limit budget
Name Type Required Description
name string yes a human label, e.g. ci-deploy-bot
scopes string[] yes the scopes to grant, or a preset name
resource object no pin the key to a team, project, site, or env
expires_in string no TTL, default 90d, max 1y
ip_allowlist string[] no CIDRs the key may be used from

Worked example — create a key (reveal-once)

Section titled “Worked example — create a key (reveal-once)”

The secret comes back once, in the create response, in the secret field. Store it immediately; subsequent reads of the key return only its metadata.

Create a scoped deploy key
curl -X POST https://api.managed.dev/v1/api-keys \
-H "Authorization: Bearer mfk_live_9aF2…" \
-H "Forge-Version: 2026-06-23" \
-H "Content-Type: application/json" \
-d '{
"name": "ci-deploy-bot",
"scopes": ["sites:read", "deployments:write", "environments:write", "jobs:read"],
"resource": { "site": "site_01J7Q2" },
"expires_in": "90d"
}'
Response — the secret is revealed once
{
"data": {
"id": "key_01JF8R",
"name": "ci-deploy-bot",
"secret": "mfk_live_b1c4d8e2f6a0…", // shown once — store it now, it is hashed at rest
"prefix": "mfk_live_b1c4…",
"scopes": ["sites:read", "deployments:write", "environments:write", "jobs:read"],
"resource": { "site": "site_01J7Q2" },
"expires_at": "2026-09-22T01:10:00Z",
"created_at": "2026-06-24T01:10:00Z"
},
"request_id": "req_01JAC1"
}

POST /v1/api-keys/{id}/roll issues a new secret for the same key id while keeping the old secret valid for a grace window. Deploy the new secret to your runners, confirm traffic has moved over, and the old one expires on its own — no window where every caller is broken at once.

Roll a key with a 24h grace window
curl -X POST https://api.managed.dev/v1/api-keys/key_01JF8R/roll \
-H "Authorization: Bearer mfk_live_9aF2…" \
-H "Forge-Version: 2026-06-23" \
-H "Content-Type: application/json" \
-d '{ "grace": "24h" }'
Response — new secret revealed once, old one in grace
{
"data": {
"id": "key_01JF8R",
"secret": "mfk_live_9d3a71c0b8f4…", // the new secret — store it now
"prefix": "mfk_live_9d3a…",
"previous_prefix": "mfk_live_b1c4…",
"previous_expires_at": "2026-06-25T01:12:00Z" // old secret valid until here
},
"request_id": "req_01JAC9"
}
  1. Roll the key and capture the new secret.
  2. Deploy the new secret to every caller.
  3. Confirm the old prefix has gone quiet in the audit log.
  4. Let previous_expires_at lapse, or DELETE the key to cut the old secret off now.

GET /v1/rate-limits reports your current budget without spending a request against a real endpoint — useful for a client that wants to back off before it’s throttled. See rate limits for the headers on every response.

Read your rate-limit budget
curl https://api.managed.dev/v1/rate-limits \
-H "Authorization: Bearer mfk_live_9aF2…" \
-H "Forge-Version: 2026-06-23"
Response
{
"data": {
"buckets": [
{ "kind": "read", "limit": 1000, "remaining": 991, "reset": 1782192060 },
{ "kind": "write", "limit": 100, "remaining": 100, "reset": 1782192060 },
{ "kind": "create", "limit": 5, "remaining": 5, "reset": 1782192060 }
]
},
"request_id": "req_01JACF"
}