Skip to content

API Keys & Authentication

The Runnit REST API and MCP server authenticate with per-user API keys. A key belongs to one user in one organisation and acts with that user’s access. There is no service-account mode: every request made with a key is attributed to the person who owns it.

If you have just been invited to a new workspace, accept the invitation first. Create the key while that workspace is selected.

End impersonation before creating a key. A key-creation request refused while you are acting as a teammate is not repeated when you return to your own account. Review Your API keys, then start a new request if you still need a key.

  1. Sign in to Runnit.
  2. Open Settings → API Keys.
  3. Enter a Name that describes the integration, for example “CI integration”.
  4. Choose Expires in: 30 days, 90 days, 1 year, or 2 years. Two years is the maximum lifetime and the server enforces it.
  5. Select Create API key.

The full key starts with rnk_ and is shown once, immediately after creation. Copy it straight into a secret manager. After you dismiss the confirmation, Runnit only ever shows a hint (the first 8 and last 4 characters) so you can recognise the key later.

A key is bound to the organisation that was active when you created it. Organisation-scoped requests for any other organisation are rejected, even if you are a member of it. If you work across organisations, create a separate key in each one.

Nothing is baked into a key. On every request, Runnit resolves the owning user’s current role, capabilities, client assignments, and data-access restrictions, exactly as it does for a browser session. That means:

  • if your permissions change, every existing key follows immediately;
  • a key can never do more than you can do in the app; and
  • if your account is deactivated or you lose access to the organisation, the key stops working straight away.

Your key also pauses if you have not accepted the current Terms of Service. Sign in to Runnit in a browser and accept the current version, then retry with the same key. You accept each version once and do not need to replace the key.

There are three ways to present a key, in order of preference:

  1. Authorization header (recommended)

    Terminal window
    curl https://api.runnit.io/api/v1/projects \
    -H 'Authorization: Bearer rnk_your_key'
  2. x-runnit-api-key header

    Terminal window
    curl https://api.runnit.io/api/v1/projects \
    -H 'x-runnit-api-key: rnk_your_key'
  3. apiKey field in the JSON request body, on POST, PATCH, and PUT requests only:

    { "apiKey": "rnk_your_key", "name": "Draft homepage copy" }

The body option exists for tools that cannot set request headers. Prefer a header when you can: request bodies are more likely to be logged by intermediaries, and GET and DELETE requests have no body to carry the key. Runnit removes the apiKey field from the body before your request is processed.

The same key also authenticates the MCP server, either as an Authorization: Bearer rnk_... header or as the per-tool apiKey argument. For per-tool credentials, use /mcp?auth=apiKey as the server URL so discovery can run before a tool supplies the key. OAuth-capable clients can instead connect through browser sign-in without creating an API key. See MCP Server.

  • Keys live for at most 2 years; shorter expiries are safer for keys you can rotate easily.
  • Revoke your own keys at any time from Settings → API Keys using Revoke, then Confirm revoke.
  • Organisation admins and owners see every member’s keys in the Organisation API keys list on the same page and can revoke any of them.
  • A revoked or expired key fails immediately; there is no grace period.
  • The Last used column shows when each key last authenticated a request, which helps you spot unused or unexpected keys.

Each key can make up to 600 requests per minute by default (deployments can configure a different limit). Requests over the limit return 429. Spread bulk work out or batch it rather than retrying immediately.

StatusMeaning
401The key is missing, invalid, expired, or revoked, or the owning user is deactivated or no longer a member of the organisation.
403The key is valid but the request targets a different organisation, the owning user lacks permission, or the owning user has not accepted the current Terms of Service. For a Terms refusal, sign in to Runnit, accept the current version, then retry.
429The key exceeded its per-minute rate limit. Wait and retry.

Browser sessions are not an integration credential: use an API key for anything automated. If you do drive the sign-in routes yourself (a test harness, for instance), an account with two-factor authentication on answers the password step with a challenge instead of a session:

POST /api/auth/login
{ "email": "you@example.com", "password": "..." }
200 { "requiresTwoFactor": true, "challengeToken": "...", "expiresIn": 300 }

Redeem it with the six-digit code from the authenticator app or a recovery code:

POST /api/auth/2fa/verify
{ "challengeToken": "...", "code": "123456" }

A successful verify answers exactly what the password step would have (the user, the access token and the session cookies). The challenge lasts five minutes, works once, allows five attempts, and must be redeemed from the same network address that started it. A wrong code is 401 with code: "TWO_FACTOR_CODE_INVALID"; an expired, used or exhausted challenge is 401 with code: "TWO_FACTOR_CHALLENGE_EXPIRED", so start again from the password step. A signed-in session whose organisation requires two-factor for its role gets 403 with code: "TWO_FACTOR_REQUIRED" on every route outside /api/auth until two-factor is turned on.

Explore the endpoints in the REST API Overview, or connect an AI agent through the MCP server.

Destination preparation happens before maintenance. If preparation fails before maintenance starts, the workspace stays at its original address and existing API keys and MCP connections remain valid.

Keep using your workspace hostname through the move. Cached DNS continues to work; you do not need to change endpoints or clear your DNS cache.

During maintenance for a workspace move, REST and MCP requests return HTTP 503 with Retry-After: 30. Wait at least 30 seconds before retrying. Maintenance responses have Cache-Control: no-store, max-age=0 and this JSON body:

{
"error": "tenant_maintenance",
"message": "This site is under maintenance. Please try again shortly."
}

The workspace address and browser sign-in method stay the same. Google or Microsoft sign-in does not require password setup for the move. After the move, sign in again, create a new key for the workspace and replace it in your integration. Reconnect OAuth-based MCP clients as well. A key for another organisation does not gain access to the moved workspace. If a write was interrupted without a response, check its outcome before sending it again.

User-generated API and MCP credentials cannot create or delete deployments, provision tenants or configure fleet AI routing. These are operator actions in Deploy Manager. Your API and MCP requests continue to use the permissions and organisation attached to your credential. Deleting that tenant removes its credentials and data; deleting a deployment removes all of its tenants.