Skip to content

API keys

Preview An API key is how a script, CI job, or integration authenticates to the managed.dev public API. Every key carries a set of scopes and, optionally, a resource constraint — together they decide exactly what the key can do, and the key can never do more than the person or team that minted it.

The prefix on a credential tells you its type and its mode at a glance — and, just as importantly, it tells secret scanners. The literal prefixes (mfk_live_, mfs_live_, mfo_at_) are registered with leak-detection partners, so a key pasted into a public repo is matched on the prefix and auto-revoked. See the security model for how leak detection works.

Family Prefix Acts as Use case
Personal key mfk_live_… / mfk_test_… a client (you) scripts, dashboards, the mf CLI, personal automation
Service token mfs_live_… a team (machine principal) CI/CD, Terraform, deploy bots — survives offboarding
OAuth token Roadmap mfo_at_… / mfo_rt_… an integrator app, delegated by a client or team marketplace integrations, third-party SaaS

A personal key dies with the client that owns it — revoke the person, and their keys stop working. A service token is bound to a team, so it keeps running when an individual leaves; that’s what you want for a deploy bot or a Terraform state. OAuth is on the roadmap for delegated, per-user access from third-party apps — design it into your mental model now, but personal and service keys are what ship first.

The _live_ and _test_ infix selects the mode the key operates in. A _test_ key targets test-mode resources and is the safe default for local development and CI dry runs; a _live_ key acts on your real sites and environments. Keep them separate the way you’d keep production and sandbox credentials apart anywhere else.

A key is shown once, at creation, and never again. managed.dev stores only a SHA-256 hash of the secret — the plaintext is never written to disk, so even a database compromise can’t reveal an existing key. If you lose a key, you don’t recover it; you revoke it and mint a new one.

Every key carries:

  • A TTL. Keys expire — the default is 90 days, the maximum is one year. Short-lived keys are a feature, not a nuisance: a leaked key has a deadline. Rotate before expiry.
  • Revocation. Revoke a key instantly from the dashboard or the API. Because keys are opaque and checked against the database on every request, revocation takes effect immediately — there’s no stateless token to wait out. See the security model for why this beats a self-contained JWT.
  • An optional IP allowlist. Constrain a key to a set of source addresses, so a service token only works from your CI runners or your office egress.
  • A mode and a prefix. As above — type, mode, and leak-detection identity, all encoded in the literal string.

Pass the key as a bearer token on the Authorization header. That’s the only transport — keys never go in query strings or request bodies.

Authenticate a request
curl https://api.managed.dev/v1/sites \
-H "Authorization: Bearer mfk_live_9aF2…" \
-H "Forge-Version: 2026-06-23"

A request with a missing or malformed key returns 401 authentication; a valid key that lacks the required scope for a resource you can see returns 403 insufficient_scope. The full mapping is in the errors reference.