skip to content
superbot.gg

Keys

Mint, list, edit and revoke scoped caller keys.

6 operations. Errors link to their row on the overview.

view .mdopenapi

List caller keyslink to List caller keys

GET /v1/keys

Every caller key on the account, revoked ones included. Never the hash. A caller key reads the list without person_email, prompt_history and person_limit_usd, which are the account owner's; a person key lists only its own person's keys.

A caller key holding keys:read (Authorization: Bearer sbc_… or x-api-key: sbc_…), or a signed-in session.

Operation id listKeys in Keys.

Response 200

The keys.

application/json: CallerKeyList.

  • object string required

    One of list.

  • data array of CallerKey required
    29 fields
    • id string required
    • user_id string required
    • name string required

      What the tool calls itself, 1-64 chars.

    • mask string required

      The only form shown after mint.

    • created_at string (date-time) required
    • last_used_at string (date-time)
    • revoked_at string (date-time)
    • daily_limit_tokens number

      Daily spend cap in whole credits.

    • monthly_limit_tokens number

      Monthly spend cap in whole credits.

    • caps_unit string

      One of credit.

    • allowed_models array of string

      Glob allow-list over model names; absent = every model. With models_listed: the exact canonical ids the key may dial, and empty = none.

    • models_listed boolean

      true = the listed reading: allowed_models are literal canonical ids (no globs), the key lists exactly those as its per-app picker names, and an empty list allows nothing.

    • model_pins object

      Canonical model id to the stable account id it is pinned to: a pinned model dials only that account, and one id pinned to two accounts gets two picker names.

    • model_aliases object

      Canonical model id (a member of allowed_models) to the custom name its picker shows: 1-64 characters of letters, numbers, dots, dashes or colons; no Cursor routing word (claude, gemini, anthropic, sonnet-, opus-, haiku-, grok, composer); not a house id (superbot, superbot-fast, superbot-omni); unique among this key's forwards; not another model's id. A refused name stores nothing. A custom name replaces the default name for that model.

    • app string

      Forwarding app this listed key's model names are spelled for: cursor, copilot-cli, cline, roo, qwen-code, hermes, openclaw, zazen, default. Set at creation, cannot be changed. Absent = cursor.

    • default_model string

      The model a call that names the bare house agent superbot (the default model of Zapier and n8n), or names no model, is answered by instead: superbot-fast, superbot-omni or a model of one of your own accounts. A call that names any other model is dialled as named. Absent = a call naming superbot gets superbot.

    • route string required

      One of byo, credits, auto.

    • mode string required

      One of model, agent.

    • incognito boolean required
    • device_id string
    • org_id string

      Set on a team key.

    • person_id string

      Set on a key minted for a person: per_ + 16 hex. Every key minted for the same person carries the same id. A person key has no device_id and no org_id, and is billed to the owner.

    • person_name string

      The person's display name, 1-64 characters. Present on every person key.

    • person_email string

      The person's email address, when the owner gave one.

    • person_group string

      A free-text grouping the owner sorts people by (a team, a class), 1-64 characters.

    • prompt_history PromptHistory

      What the owner told a person about their prompts, and how long they are kept. Absent on a key until the owner sets it: the person's prompts are then not visible to the owner and follow the account's own retention.

      3 fields
      • visible_to_owner boolean required

        The owner may read this person's prompts.

      • retention_days integer required

        Whole days the prompts are kept, 1-3650.

      • attested_at string (date-time) required

        ISO 8601 time the owner attested the person was told. The owner's own claim, stored as given and not verified; the answer normalises it to UTC.

    • paused_at string (date-time)

      Set while the owner holds this person: until a PATCH clears it the key answers 403 key_paused at the model gateway, the /v1/keys routes, the relay door and the Cosmos door; every other route does not recognise a held key and answers 401 unauthorized. Held is not revoked. It is written to every live key of the person.

    • person_limit_usd number

      The owner's monthly spend limit for this person, in US dollars to the cent. Set by the owner's PUT /v1/keys/person/{person_id}/limit (the Helper), written to every live key of the person, and absent while no limit is set.

    • scopes array of Scope required

      The EFFECTIVE scopes: stored list or the legacy set, team keys capped. One of gateway:invoke, usage:read, billing:read, keys:read, keys:write, endpoints:read, endpoints:write, teams:read, teams:write, devices:read, devices:write, runs:read, runs:write, mcp:invoke, turns:read, tools:invoke.

  • has_more boolean required
  • first_id string | null required

    Id of the first item on this page; pass as before_id for the previous page.

  • last_id string | null required

    Id of the last item on this page; pass as after_id for the next page.

  • keys array of CallerKey required

    Legacy: the same rows as data.

    29 fields
    • id string required
    • user_id string required
    • name string required

      What the tool calls itself, 1-64 chars.

    • mask string required

      The only form shown after mint.

    • created_at string (date-time) required
    • last_used_at string (date-time)
    • revoked_at string (date-time)
    • daily_limit_tokens number

      Daily spend cap in whole credits.

    • monthly_limit_tokens number

      Monthly spend cap in whole credits.

    • caps_unit string

      One of credit.

    • allowed_models array of string

      Glob allow-list over model names; absent = every model. With models_listed: the exact canonical ids the key may dial, and empty = none.

    • models_listed boolean

      true = the listed reading: allowed_models are literal canonical ids (no globs), the key lists exactly those as its per-app picker names, and an empty list allows nothing.

    • model_pins object

      Canonical model id to the stable account id it is pinned to: a pinned model dials only that account, and one id pinned to two accounts gets two picker names.

    • model_aliases object

      Canonical model id (a member of allowed_models) to the custom name its picker shows: 1-64 characters of letters, numbers, dots, dashes or colons; no Cursor routing word (claude, gemini, anthropic, sonnet-, opus-, haiku-, grok, composer); not a house id (superbot, superbot-fast, superbot-omni); unique among this key's forwards; not another model's id. A refused name stores nothing. A custom name replaces the default name for that model.

    • app string

      Forwarding app this listed key's model names are spelled for: cursor, copilot-cli, cline, roo, qwen-code, hermes, openclaw, zazen, default. Set at creation, cannot be changed. Absent = cursor.

    • default_model string

      The model a call that names the bare house agent superbot (the default model of Zapier and n8n), or names no model, is answered by instead: superbot-fast, superbot-omni or a model of one of your own accounts. A call that names any other model is dialled as named. Absent = a call naming superbot gets superbot.

    • route string required

      One of byo, credits, auto.

    • mode string required

      One of model, agent.

    • incognito boolean required
    • device_id string
    • org_id string

      Set on a team key.

    • person_id string

      Set on a key minted for a person: per_ + 16 hex. Every key minted for the same person carries the same id. A person key has no device_id and no org_id, and is billed to the owner.

    • person_name string

      The person's display name, 1-64 characters. Present on every person key.

    • person_email string

      The person's email address, when the owner gave one.

    • person_group string

      A free-text grouping the owner sorts people by (a team, a class), 1-64 characters.

    • prompt_history PromptHistory

      What the owner told a person about their prompts, and how long they are kept. Absent on a key until the owner sets it: the person's prompts are then not visible to the owner and follow the account's own retention.

      3 fields
      • visible_to_owner boolean required

        The owner may read this person's prompts.

      • retention_days integer required

        Whole days the prompts are kept, 1-3650.

      • attested_at string (date-time) required

        ISO 8601 time the owner attested the person was told. The owner's own claim, stored as given and not verified; the answer normalises it to UTC.

    • paused_at string (date-time)

      Set while the owner holds this person: until a PATCH clears it the key answers 403 key_paused at the model gateway, the /v1/keys routes, the relay door and the Cosmos door; every other route does not recognise a held key and answers 401 unauthorized. Held is not revoked. It is written to every live key of the person.

    • person_limit_usd number

      The owner's monthly spend limit for this person, in US dollars to the cent. Set by the owner's PUT /v1/keys/person/{person_id}/limit (the Helper), written to every live key of the person, and absent while no limit is set.

    • scopes array of Scope required

      The EFFECTIVE scopes: stored list or the legacy set, team keys capped. One of gateway:invoke, usage:read, billing:read, keys:read, keys:write, endpoints:read, endpoints:write, teams:read, teams:write, devices:read, devices:write, runs:read, runs:write, mcp:invoke, turns:read, tools:invoke.

Errors

StatusCodeWhat to change
401unauthorized

Send a live caller key or session as Authorization: Bearer … or x-api-key. No key yet: create one at /account/api, or sign a user in at /auth.md.

403insufficient_scope

The key lacks the scope in required_scopes; mint a key that holds it.

view .mdopenapi
Request

curl

curl -sS -X GET "https://superbot.gg/v1/keys" \
  -H "Authorization: Bearer $SUPERBOT_API_KEY"

JavaScript

const res = await fetch(`https://superbot.gg/v1/keys`, {
  method: 'GET',
  headers: {
    Authorization: `Bearer ${process.env.SUPERBOT_API_KEY}`,
  },
});
console.log(res.status, await res.json());

Python

import os
import requests

res = requests.request(
    "GET",
    "https://superbot.gg/v1/keys",
    headers={
        "Authorization": f"Bearer {os.environ['SUPERBOT_API_KEY']}",
    },
)
print(res.status_code, res.json())
Response

200 The keys.

{
  "object": "list",
  "data": [
    {
      "id": "ck_9f2c41d0",
      "user_id": "your-user-id",
      "name": "your-name",
      "mask": "sbc_ab12…cd34",
      "created_at": "2026-09-01T00:00:00Z",
      "last_used_at": "2026-09-01T00:00:00Z",
      "revoked_at": "2026-09-01T00:00:00Z",
      "daily_limit_tokens": 0,
      "monthly_limit_tokens": 0,
      "caps_unit": "credit",
      "allowed_models": [
        "your-allowed-models"
      ],
      "models_listed": true,
      "model_pins": {},
      "model_aliases": {},
      "app": "your-app",
      "default_model": "your-default-model",
      "route": "byo",
      "mode": "model",
      "incognito": true,
      "device_id": "your-device-id",
      "org_id": "your-org-id",
      "person_id": "per_9f2c41d0a7b35e68",
      "person_name": "your-person-name",
      "person_email": "[email protected]",
      "person_group": "your-person-group",
      "prompt_history": {
        "visible_to_owner": true,
        "retention_days": 0,
        "attested_at": "2026-09-01T00:00:00Z"
      },
      "paused_at": "2026-09-01T00:00:00Z",
      "person_limit_usd": 0,
      "scopes": [
        "gateway:invoke"
      ]
    }
  ],
  "has_more": true,
  "first_id": "your-first-id",
  "last_id": "your-last-id",
  "keys": [
    {
      "id": "ck_9f2c41d0",
      "user_id": "your-user-id",
      "name": "your-name",
      "mask": "sbc_ab12…cd34",
      "created_at": "2026-09-01T00:00:00Z",
      "last_used_at": "2026-09-01T00:00:00Z",
      "revoked_at": "2026-09-01T00:00:00Z",
      "daily_limit_tokens": 0,
      "monthly_limit_tokens": 0,
      "caps_unit": "credit",
      "allowed_models": [
        "your-allowed-models"
      ],
      "models_listed": true,
      "model_pins": {},
      "model_aliases": {},
      "app": "your-app",
      "default_model": "your-default-model",
      "route": "byo",
      "mode": "model",
      "incognito": true,
      "device_id": "your-device-id",
      "org_id": "your-org-id",
      "person_id": "per_9f2c41d0a7b35e68",
      "person_name": "your-person-name",
      "person_email": "[email protected]",
      "person_group": "your-person-group",
      "prompt_history": {
        "visible_to_owner": true,
        "retention_days": 0,
        "attested_at": "2026-09-01T00:00:00Z"
      },
      "paused_at": "2026-09-01T00:00:00Z",
      "person_limit_usd": 0,
      "scopes": [
        "gateway:invoke"
      ]
    }
  ]
}

401 The bearer is missing, malformed or unknown.

{
  "error": "unauthorized",
  "message": "Send a live caller key or session as Authorization: Bearer … or x-api-key. No key yet: create one at /account/api, or sign a user in at /auth.md.",
  "doc_url": "https://superbot.gg/developers#errors-unauthorized",
  "request_id": "req_5f1c0a9e2b7d4c3a1e0f9b8d"
}

403 The key lacks a scope (insufficient_scope), is revoked, or may not call this route.

{
  "error": "insufficient_scope",
  "message": "The key lacks the scope in required_scopes; mint a key that holds it.",
  "doc_url": "https://superbot.gg/developers#errors-insufficient_scope",
  "request_id": "req_5f1c0a9e2b7d4c3a1e0f9b8d"
}

Create a caller keylink to Create a caller key

POST /v1/keys

Mint a key. The plaintext is returned once. A caller key can only mint keys within its own reach: no scope, route, cap or model it does not hold. With person the key is minted for someone else and billed to you: the row carries person_id, person_name and the rest, and name defaults to the person's name. A bad person answers 400 invalid_person. Only the account owner (a signed-in session, a device or the account key) mints a key for a person: a caller key that sends person answers 403 caller_key_forbidden, and so does a person key minting any key. A person key minted with no scopes or preset holds gateway:invoke alone. A paused caller key answers 403 key_paused.

A caller key holding keys:write (Authorization: Bearer sbc_… or x-api-key: sbc_…), or a signed-in session.

Operation id createKey in Keys.

Request body

application/json, required.

  • name string

    What the tool calls itself, 1-64 chars. Required unless person is given, then it defaults to the person's name.

  • person KeyPerson

    The person a key is minted for. Without id it makes a new person (name required); with id it adds a key to that person. A person key stamps no device (the minting device's logout never revokes it), takes no org_id and is billed to the owner.

    4 fields
    • name string

      The person's display name, 1-64 printable characters (no <, >, " or '). Required for a new person; with id it must equal the stored name or be left out.

    • email string

      The person's email address. With id it must equal the stored one or be left out.

    • group string

      A free-text grouping, 1-64 characters. With id it must equal the stored one or be left out.

    • id string

      The person_id of a person already on this account: adds another key for them, which inherits the stored name, email, group, prompt_history and paused_at (a paused person's new key is born paused). Rotating a key is a mint with the same id, then a revoke of the old key.

  • route string

    One of byo, credits, auto.

  • mode string

    One of model, agent.

  • daily_limit_tokens number

    Daily spend cap in whole credits.

  • monthly_limit_tokens number

    Monthly spend cap in whole credits.

  • allowed_models array of string

    Glob allow-list over model names; with models_listed, the exact canonical ids (no globs).

  • models_listed boolean

    true = the listed reading: the key dials exactly its allowed_models, listed as the per-app picker names; empty = none. A PATCH that omits it leaves it as it was.

  • model_pins object | null

    Canonical model id to the stable account id it is pinned to (non-empty strings). A PATCH replaces the whole map; null clears it.

  • model_aliases object | null

    Canonical model id (a member of allowed_models) to the custom name its picker shows (1-64 characters: letters, numbers, dots, dashes, colons). A PATCH replaces the whole map; null clears it. A refused name stores nothing and answers the reason. Removing a model from allowed_models drops its custom name.

  • default_model string | null

    The model a call that names the bare house agent superbot (the default model of Zapier and n8n), or names no model, is answered by instead: superbot-fast, superbot-omni, or a model of one of your own accounts (claude-sonnet-5-5, gpt-5.5, custom/<endpoint>/<id>). A call that names any other model is dialled as named. null or superbot clears it. A model of your own account needs a key on route auto or byo in mode model whose allowed_models admits it; a key on route credits takes a house model only, and a key with models_listed takes none. The write is judged on the key as it will be stored, so a PATCH that would leave the default unusable (route credits, mode agent, a narrower list) answers 400 invalid_default_model: send default_model: null with it. A PATCH that omits it leaves it as it was.

  • incognito boolean
  • scopes array of Scope

    Explicit scopes; wins over preset. One of gateway:invoke, usage:read, billing:read, keys:read, keys:write, endpoints:read, endpoints:write, teams:read, teams:write, devices:read, devices:write, runs:read, runs:write, mcp:invoke, turns:read, tools:invoke.

  • app string

    Forwarding app this listed key's model names are spelled for: cursor, copilot-cli, cline, roo, qwen-code, hermes, openclaw, zazen, default. Set at creation, cannot be changed. Absent = cursor.

  • preset string

    A named scope set. One of gateway, read_only, full.

Response 201

The new key.

application/json: CreatedKey.

  • key string required

    The plaintext sbc_… key, shown once.

  • row CallerKey required
    29 fields
    • id string required
    • user_id string required
    • name string required

      What the tool calls itself, 1-64 chars.

    • mask string required

      The only form shown after mint.

    • created_at string (date-time) required
    • last_used_at string (date-time)
    • revoked_at string (date-time)
    • daily_limit_tokens number

      Daily spend cap in whole credits.

    • monthly_limit_tokens number

      Monthly spend cap in whole credits.

    • caps_unit string

      One of credit.

    • allowed_models array of string

      Glob allow-list over model names; absent = every model. With models_listed: the exact canonical ids the key may dial, and empty = none.

    • models_listed boolean

      true = the listed reading: allowed_models are literal canonical ids (no globs), the key lists exactly those as its per-app picker names, and an empty list allows nothing.

    • model_pins object

      Canonical model id to the stable account id it is pinned to: a pinned model dials only that account, and one id pinned to two accounts gets two picker names.

    • model_aliases object

      Canonical model id (a member of allowed_models) to the custom name its picker shows: 1-64 characters of letters, numbers, dots, dashes or colons; no Cursor routing word (claude, gemini, anthropic, sonnet-, opus-, haiku-, grok, composer); not a house id (superbot, superbot-fast, superbot-omni); unique among this key's forwards; not another model's id. A refused name stores nothing. A custom name replaces the default name for that model.

    • app string

      Forwarding app this listed key's model names are spelled for: cursor, copilot-cli, cline, roo, qwen-code, hermes, openclaw, zazen, default. Set at creation, cannot be changed. Absent = cursor.

    • default_model string

      The model a call that names the bare house agent superbot (the default model of Zapier and n8n), or names no model, is answered by instead: superbot-fast, superbot-omni or a model of one of your own accounts. A call that names any other model is dialled as named. Absent = a call naming superbot gets superbot.

    • route string required

      One of byo, credits, auto.

    • mode string required

      One of model, agent.

    • incognito boolean required
    • device_id string
    • org_id string

      Set on a team key.

    • person_id string

      Set on a key minted for a person: per_ + 16 hex. Every key minted for the same person carries the same id. A person key has no device_id and no org_id, and is billed to the owner.

    • person_name string

      The person's display name, 1-64 characters. Present on every person key.

    • person_email string

      The person's email address, when the owner gave one.

    • person_group string

      A free-text grouping the owner sorts people by (a team, a class), 1-64 characters.

    • prompt_history PromptHistory

      What the owner told a person about their prompts, and how long they are kept. Absent on a key until the owner sets it: the person's prompts are then not visible to the owner and follow the account's own retention.

      3 fields
      • visible_to_owner boolean required

        The owner may read this person's prompts.

      • retention_days integer required

        Whole days the prompts are kept, 1-3650.

      • attested_at string (date-time) required

        ISO 8601 time the owner attested the person was told. The owner's own claim, stored as given and not verified; the answer normalises it to UTC.

    • paused_at string (date-time)

      Set while the owner holds this person: until a PATCH clears it the key answers 403 key_paused at the model gateway, the /v1/keys routes, the relay door and the Cosmos door; every other route does not recognise a held key and answers 401 unauthorized. Held is not revoked. It is written to every live key of the person.

    • person_limit_usd number

      The owner's monthly spend limit for this person, in US dollars to the cent. Set by the owner's PUT /v1/keys/person/{person_id}/limit (the Helper), written to every live key of the person, and absent while no limit is set.

    • scopes array of Scope required

      The EFFECTIVE scopes: stored list or the legacy set, team keys capped. One of gateway:invoke, usage:read, billing:read, keys:read, keys:write, endpoints:read, endpoints:write, teams:read, teams:write, devices:read, devices:write, runs:read, runs:write, mcp:invoke, turns:read, tools:invoke.

Errors

StatusCodeWhat to change
400invalid_request

A parameter or body field is invalid; param names it and issues lists every problem.

401unauthorized

Send a live caller key or session as Authorization: Bearer … or x-api-key. No key yet: create one at /account/api, or sign a user in at /auth.md.

403insufficient_scope

The key lacks the scope in required_scopes; mint a key that holds it.

view .mdopenapi
Request

curl

curl -sS -X POST "https://superbot.gg/v1/keys" \
  -H "Authorization: Bearer $SUPERBOT_API_KEY" \
  -H "content-type: application/json" \
  -d '{"name":"your-name","person":{"name":"your-name","email":"[email protected]","group":"your-group"},"route":"byo"}'

JavaScript

const res = await fetch(`https://superbot.gg/v1/keys`, {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.SUPERBOT_API_KEY}`,
    'content-type': 'application/json',
  },
  body: JSON.stringify({"name":"your-name","person":{"name":"your-name","email":"[email protected]","group":"your-group"},"route":"byo"}),
});
console.log(res.status, await res.json());

Python

import os
import requests

res = requests.request(
    "POST",
    "https://superbot.gg/v1/keys",
    headers={
        "Authorization": f"Bearer {os.environ['SUPERBOT_API_KEY']}",
        "content-type": "application/json",
    },
    json={"name":"your-name","person":{"name":"your-name","email":"[email protected]","group":"your-group"},"route":"byo"},
)
print(res.status_code, res.json())
Response

201 The new key.

{
  "key": "your-key",
  "row": {
    "id": "ck_9f2c41d0",
    "user_id": "your-user-id",
    "name": "your-name",
    "mask": "sbc_ab12…cd34",
    "created_at": "2026-09-01T00:00:00Z",
    "last_used_at": "2026-09-01T00:00:00Z",
    "revoked_at": "2026-09-01T00:00:00Z",
    "daily_limit_tokens": 0,
    "monthly_limit_tokens": 0,
    "caps_unit": "credit",
    "allowed_models": [
      "your-allowed-models"
    ],
    "models_listed": true,
    "model_pins": {},
    "model_aliases": {},
    "app": "your-app",
    "default_model": "your-default-model",
    "route": "byo",
    "mode": "model",
    "incognito": true,
    "device_id": "your-device-id",
    "org_id": "your-org-id",
    "person_id": "per_9f2c41d0a7b35e68",
    "person_name": "your-person-name",
    "person_email": "[email protected]",
    "person_group": "your-person-group",
    "prompt_history": {
      "visible_to_owner": true,
      "retention_days": 0,
      "attested_at": "2026-09-01T00:00:00Z"
    },
    "paused_at": "2026-09-01T00:00:00Z",
    "person_limit_usd": 0,
    "scopes": [
      "gateway:invoke"
    ]
  }
}

400 The request is malformed or a parameter is invalid; `param` names the field.

{
  "error": "invalid_request",
  "message": "A parameter or body field is invalid; param names it and issues lists every problem.",
  "doc_url": "https://superbot.gg/developers#errors-invalid_request",
  "request_id": "req_5f1c0a9e2b7d4c3a1e0f9b8d"
}

401 The bearer is missing, malformed or unknown.

{
  "error": "unauthorized",
  "message": "Send a live caller key or session as Authorization: Bearer … or x-api-key. No key yet: create one at /account/api, or sign a user in at /auth.md.",
  "doc_url": "https://superbot.gg/developers#errors-unauthorized",
  "request_id": "req_5f1c0a9e2b7d4c3a1e0f9b8d"
}

403 The key lacks a scope (insufficient_scope), is revoked, or may not call this route.

{
  "error": "insufficient_scope",
  "message": "The key lacks the scope in required_scopes; mint a key that holds it.",
  "doc_url": "https://superbot.gg/developers#errors-insufficient_scope",
  "request_id": "req_5f1c0a9e2b7d4c3a1e0f9b8d"
}

Get the calling keylink to Get the calling key

GET /v1/keys/whoami

The calling caller key’s own row and effective scopes, and its own metered usage in three windows (usage). A person key’s fields ride on row. Caller keys only; a session gets 403 caller_key_required. A revoked key gets 403 revoked_key, a paused one 403 key_paused.

Any live caller key (Authorization: Bearer sbc_… or x-api-key: sbc_…).

Operation id getCurrentKey in Keys.

Response 200

The key.

application/json: CurrentKey.

  • row CallerKey required
    29 fields
    • id string required
    • user_id string required
    • name string required

      What the tool calls itself, 1-64 chars.

    • mask string required

      The only form shown after mint.

    • created_at string (date-time) required
    • last_used_at string (date-time)
    • revoked_at string (date-time)
    • daily_limit_tokens number

      Daily spend cap in whole credits.

    • monthly_limit_tokens number

      Monthly spend cap in whole credits.

    • caps_unit string

      One of credit.

    • allowed_models array of string

      Glob allow-list over model names; absent = every model. With models_listed: the exact canonical ids the key may dial, and empty = none.

    • models_listed boolean

      true = the listed reading: allowed_models are literal canonical ids (no globs), the key lists exactly those as its per-app picker names, and an empty list allows nothing.

    • model_pins object

      Canonical model id to the stable account id it is pinned to: a pinned model dials only that account, and one id pinned to two accounts gets two picker names.

    • model_aliases object

      Canonical model id (a member of allowed_models) to the custom name its picker shows: 1-64 characters of letters, numbers, dots, dashes or colons; no Cursor routing word (claude, gemini, anthropic, sonnet-, opus-, haiku-, grok, composer); not a house id (superbot, superbot-fast, superbot-omni); unique among this key's forwards; not another model's id. A refused name stores nothing. A custom name replaces the default name for that model.

    • app string

      Forwarding app this listed key's model names are spelled for: cursor, copilot-cli, cline, roo, qwen-code, hermes, openclaw, zazen, default. Set at creation, cannot be changed. Absent = cursor.

    • default_model string

      The model a call that names the bare house agent superbot (the default model of Zapier and n8n), or names no model, is answered by instead: superbot-fast, superbot-omni or a model of one of your own accounts. A call that names any other model is dialled as named. Absent = a call naming superbot gets superbot.

    • route string required

      One of byo, credits, auto.

    • mode string required

      One of model, agent.

    • incognito boolean required
    • device_id string
    • org_id string

      Set on a team key.

    • person_id string

      Set on a key minted for a person: per_ + 16 hex. Every key minted for the same person carries the same id. A person key has no device_id and no org_id, and is billed to the owner.

    • person_name string

      The person's display name, 1-64 characters. Present on every person key.

    • person_email string

      The person's email address, when the owner gave one.

    • person_group string

      A free-text grouping the owner sorts people by (a team, a class), 1-64 characters.

    • prompt_history PromptHistory

      What the owner told a person about their prompts, and how long they are kept. Absent on a key until the owner sets it: the person's prompts are then not visible to the owner and follow the account's own retention.

      3 fields
      • visible_to_owner boolean required

        The owner may read this person's prompts.

      • retention_days integer required

        Whole days the prompts are kept, 1-3650.

      • attested_at string (date-time) required

        ISO 8601 time the owner attested the person was told. The owner's own claim, stored as given and not verified; the answer normalises it to UTC.

    • paused_at string (date-time)

      Set while the owner holds this person: until a PATCH clears it the key answers 403 key_paused at the model gateway, the /v1/keys routes, the relay door and the Cosmos door; every other route does not recognise a held key and answers 401 unauthorized. Held is not revoked. It is written to every live key of the person.

    • person_limit_usd number

      The owner's monthly spend limit for this person, in US dollars to the cent. Set by the owner's PUT /v1/keys/person/{person_id}/limit (the Helper), written to every live key of the person, and absent while no limit is set.

    • scopes array of Scope required

      The EFFECTIVE scopes: stored list or the legacy set, team keys capped. One of gateway:invoke, usage:read, billing:read, keys:read, keys:write, endpoints:read, endpoints:write, teams:read, teams:write, devices:read, devices:write, runs:read, runs:write, mcp:invoke, turns:read, tools:invoke.

  • scopes array of Scope required

    One of gateway:invoke, usage:read, billing:read, keys:read, keys:write, endpoints:read, endpoints:write, teams:read, teams:write, devices:read, devices:write, runs:read, runs:write, mcp:invoke, turns:read, tools:invoke.

  • usage KeyUsage required

    This key's own metered usage in three windows: day is the trailing 24 hours (the daily cap's window), week the trailing 7 days, month the current UTC calendar month (the monthly cap's window). Each window reports requests (every metered request), prompts (the requests that were the person's own text), tokens and billed_usd.

    3 fields
    • day KeyUsageWindow required
      6 fields
      • requests integer required

        Distinct metered requests (a request that dialed several times counts once). Every request the key made is one, an agent's tool legs, a title helper and a probe included: the call volume, not what the person asked.

      • prompts integer required

        Distinct answered prompts: requests whose last message was the person's own text and that were answered (the gateway marks the request's row only then), counted once per request id. A tool leg, a title helper, a probe and a refused or failed call are requests but not prompts. Only the dials the gateway wrote a row for are read, so the relay door's turns are not counted here.

      • prompts_truncated boolean

        Present (true) when prompts is a floor, not the window's count: the read of this key's rows behind it stopped at its row ceiling before it reached the window's start, or the read failed. prompts then counts the newest prompts the read reached. Absent when the read covered the whole window. One of true.

      • tokens number required

        Every metered leg: fresh input, output and both cache legs.

      • billed_usd number required

        What the window's calls are worth to the caps and the usage pages, USD: the router's settle once read back, else the metered list value.

      • clients object

        Distinct requests of the window made by Zapier or n8n, counted from the x-superbot-client tag (zapier/<v>, n8n/<v>) the request carried. A platform with no request in the window is absent, and the member is absent when neither made one.

        2 fields
        • zapier integer
        • n8n integer
    • week KeyUsageWindow required
      6 fields
      • requests integer required

        Distinct metered requests (a request that dialed several times counts once). Every request the key made is one, an agent's tool legs, a title helper and a probe included: the call volume, not what the person asked.

      • prompts integer required

        Distinct answered prompts: requests whose last message was the person's own text and that were answered (the gateway marks the request's row only then), counted once per request id. A tool leg, a title helper, a probe and a refused or failed call are requests but not prompts. Only the dials the gateway wrote a row for are read, so the relay door's turns are not counted here.

      • prompts_truncated boolean

        Present (true) when prompts is a floor, not the window's count: the read of this key's rows behind it stopped at its row ceiling before it reached the window's start, or the read failed. prompts then counts the newest prompts the read reached. Absent when the read covered the whole window. One of true.

      • tokens number required

        Every metered leg: fresh input, output and both cache legs.

      • billed_usd number required

        What the window's calls are worth to the caps and the usage pages, USD: the router's settle once read back, else the metered list value.

      • clients object

        Distinct requests of the window made by Zapier or n8n, counted from the x-superbot-client tag (zapier/<v>, n8n/<v>) the request carried. A platform with no request in the window is absent, and the member is absent when neither made one.

        2 fields
        • zapier integer
        • n8n integer
    • month KeyUsageWindow required
      6 fields
      • requests integer required

        Distinct metered requests (a request that dialed several times counts once). Every request the key made is one, an agent's tool legs, a title helper and a probe included: the call volume, not what the person asked.

      • prompts integer required

        Distinct answered prompts: requests whose last message was the person's own text and that were answered (the gateway marks the request's row only then), counted once per request id. A tool leg, a title helper, a probe and a refused or failed call are requests but not prompts. Only the dials the gateway wrote a row for are read, so the relay door's turns are not counted here.

      • prompts_truncated boolean

        Present (true) when prompts is a floor, not the window's count: the read of this key's rows behind it stopped at its row ceiling before it reached the window's start, or the read failed. prompts then counts the newest prompts the read reached. Absent when the read covered the whole window. One of true.

      • tokens number required

        Every metered leg: fresh input, output and both cache legs.

      • billed_usd number required

        What the window's calls are worth to the caps and the usage pages, USD: the router's settle once read back, else the metered list value.

      • clients object

        Distinct requests of the window made by Zapier or n8n, counted from the x-superbot-client tag (zapier/<v>, n8n/<v>) the request carried. A platform with no request in the window is absent, and the member is absent when neither made one.

        2 fields
        • zapier integer
        • n8n integer

Errors

StatusCodeWhat to change
401unauthorized

Send a live caller key or session as Authorization: Bearer … or x-api-key. No key yet: create one at /account/api, or sign a user in at /auth.md.

403insufficient_scope

The key lacks the scope in required_scopes; mint a key that holds it.

404not_found

No such resource on this account; check the id.

view .mdopenapi
Request

curl

curl -sS -X GET "https://superbot.gg/v1/keys/whoami" \
  -H "Authorization: Bearer $SUPERBOT_API_KEY"

JavaScript

const res = await fetch(`https://superbot.gg/v1/keys/whoami`, {
  method: 'GET',
  headers: {
    Authorization: `Bearer ${process.env.SUPERBOT_API_KEY}`,
  },
});
console.log(res.status, await res.json());

Python

import os
import requests

res = requests.request(
    "GET",
    "https://superbot.gg/v1/keys/whoami",
    headers={
        "Authorization": f"Bearer {os.environ['SUPERBOT_API_KEY']}",
    },
)
print(res.status_code, res.json())
Response

200 The key.

{
  "row": {
    "id": "ck_9f2c41d0",
    "user_id": "your-user-id",
    "name": "your-name",
    "mask": "sbc_ab12…cd34",
    "created_at": "2026-09-01T00:00:00Z",
    "last_used_at": "2026-09-01T00:00:00Z",
    "revoked_at": "2026-09-01T00:00:00Z",
    "daily_limit_tokens": 0,
    "monthly_limit_tokens": 0,
    "caps_unit": "credit",
    "allowed_models": [
      "your-allowed-models"
    ],
    "models_listed": true,
    "model_pins": {},
    "model_aliases": {},
    "app": "your-app",
    "default_model": "your-default-model",
    "route": "byo",
    "mode": "model",
    "incognito": true,
    "device_id": "your-device-id",
    "org_id": "your-org-id",
    "person_id": "per_9f2c41d0a7b35e68",
    "person_name": "your-person-name",
    "person_email": "[email protected]",
    "person_group": "your-person-group",
    "prompt_history": {
      "visible_to_owner": true,
      "retention_days": 0,
      "attested_at": "2026-09-01T00:00:00Z"
    },
    "paused_at": "2026-09-01T00:00:00Z",
    "person_limit_usd": 0,
    "scopes": [
      "gateway:invoke"
    ]
  },
  "scopes": [
    "gateway:invoke"
  ],
  "usage": {
    "day": {
      "requests": 0,
      "prompts": 0,
      "prompts_truncated": true,
      "tokens": 0,
      "billed_usd": 0,
      "clients": {
        "zapier": 0,
        "n8n": 0
      }
    },
    "week": {
      "requests": 0,
      "prompts": 0,
      "prompts_truncated": true,
      "tokens": 0,
      "billed_usd": 0,
      "clients": {
        "zapier": 0,
        "n8n": 0
      }
    },
    "month": {
      "requests": 0,
      "prompts": 0,
      "prompts_truncated": true,
      "tokens": 0,
      "billed_usd": 0,
      "clients": {
        "zapier": 0,
        "n8n": 0
      }
    }
  }
}

401 The bearer is missing, malformed or unknown.

{
  "error": "unauthorized",
  "message": "Send a live caller key or session as Authorization: Bearer … or x-api-key. No key yet: create one at /account/api, or sign a user in at /auth.md.",
  "doc_url": "https://superbot.gg/developers#errors-unauthorized",
  "request_id": "req_5f1c0a9e2b7d4c3a1e0f9b8d"
}

403 The key lacks a scope (insufficient_scope), is revoked, or may not call this route.

{
  "error": "insufficient_scope",
  "message": "The key lacks the scope in required_scopes; mint a key that holds it.",
  "doc_url": "https://superbot.gg/developers#errors-insufficient_scope",
  "request_id": "req_5f1c0a9e2b7d4c3a1e0f9b8d"
}

404 No such resource on this account.

{
  "error": "not_found",
  "message": "No such resource on this account; check the id.",
  "doc_url": "https://superbot.gg/developers#errors-not_found",
  "request_id": "req_5f1c0a9e2b7d4c3a1e0f9b8d"
}

Update a caller keylink to Update a caller key

PATCH /v1/keys/{id}

Edit a key’s name, route, mode, caps, models, default model or scopes. A bad default_model answers 400 invalid_default_model. On a person key, person_name, person_email, person_group, prompt_history and paused_at edit the person and are written to every live key of that person; on any other key they answer 400 not_a_person_key, and an invalid value answers 400 invalid_person. A person key is edited by the account owner only, and a person field is changed by the account owner only: a caller key that tries either answers 403 caller_key_forbidden. A person key cannot be renamed account. A paused caller key answers 403 key_paused.

A caller key holding keys:write (Authorization: Bearer sbc_… or x-api-key: sbc_…), or a signed-in session.

Operation id updateKey in Keys.

Path parameters

  • id string required

Request body

application/json, required.

  • name string
  • route string

    One of byo, credits, auto.

  • mode string

    One of model, agent.

  • daily_limit_tokens number

    Daily spend cap in whole credits.

  • monthly_limit_tokens number

    Monthly spend cap in whole credits.

  • allowed_models array of string

    Glob allow-list over model names; with models_listed, the exact canonical ids (no globs).

  • models_listed boolean

    true = the listed reading: the key dials exactly its allowed_models, listed as the per-app picker names; empty = none. A PATCH that omits it leaves it as it was.

  • model_pins object | null

    Canonical model id to the stable account id it is pinned to (non-empty strings). A PATCH replaces the whole map; null clears it.

  • model_aliases object | null

    Canonical model id (a member of allowed_models) to the custom name its picker shows (1-64 characters: letters, numbers, dots, dashes, colons). A PATCH replaces the whole map; null clears it. A refused name stores nothing and answers the reason. Removing a model from allowed_models drops its custom name.

  • default_model string | null

    The model a call that names the bare house agent superbot (the default model of Zapier and n8n), or names no model, is answered by instead: superbot-fast, superbot-omni, or a model of one of your own accounts (claude-sonnet-5-5, gpt-5.5, custom/<endpoint>/<id>). A call that names any other model is dialled as named. null or superbot clears it. A model of your own account needs a key on route auto or byo in mode model whose allowed_models admits it; a key on route credits takes a house model only, and a key with models_listed takes none. The write is judged on the key as it will be stored, so a PATCH that would leave the default unusable (route credits, mode agent, a narrower list) answers 400 invalid_default_model: send default_model: null with it. A PATCH that omits it leaves it as it was.

  • incognito boolean
  • scopes array of Scope

    Explicit scopes; wins over preset. One of gateway:invoke, usage:read, billing:read, keys:read, keys:write, endpoints:read, endpoints:write, teams:read, teams:write, devices:read, devices:write, runs:read, runs:write, mcp:invoke, turns:read, tools:invoke.

  • person_name string

    Rename the person (1-64 printable characters). Cannot be cleared. Does not rename the key (name).

  • person_email string | null

    Set the person's email address; null clears it.

  • person_group string | null

    Set the person's group; null clears it.

  • prompt_history PromptHistory & object | null
    3 fields
    • visible_to_owner boolean required

      The owner may read this person's prompts.

    • retention_days integer required

      Whole days the prompts are kept, 1-3650.

    • attested_at string (date-time) required

      ISO 8601 time the owner attested the person was told. The owner's own claim, stored as given and not verified; the answer normalises it to UTC.

  • paused_at boolean | string | null

    true pauses the person now (the edge stamps the time), an ISO 8601 time pauses from then (not in the future), false or null resumes. A paused person's keys answer 403 key_paused at the model gateway, the /v1/keys routes, the relay door and the Cosmos door; every other route does not recognise a held key and answers 401 unauthorized.

Response 200

The edited key.

application/json: UpdatedKey.

  • row CallerKey required
    29 fields
    • id string required
    • user_id string required
    • name string required

      What the tool calls itself, 1-64 chars.

    • mask string required

      The only form shown after mint.

    • created_at string (date-time) required
    • last_used_at string (date-time)
    • revoked_at string (date-time)
    • daily_limit_tokens number

      Daily spend cap in whole credits.

    • monthly_limit_tokens number

      Monthly spend cap in whole credits.

    • caps_unit string

      One of credit.

    • allowed_models array of string

      Glob allow-list over model names; absent = every model. With models_listed: the exact canonical ids the key may dial, and empty = none.

    • models_listed boolean

      true = the listed reading: allowed_models are literal canonical ids (no globs), the key lists exactly those as its per-app picker names, and an empty list allows nothing.

    • model_pins object

      Canonical model id to the stable account id it is pinned to: a pinned model dials only that account, and one id pinned to two accounts gets two picker names.

    • model_aliases object

      Canonical model id (a member of allowed_models) to the custom name its picker shows: 1-64 characters of letters, numbers, dots, dashes or colons; no Cursor routing word (claude, gemini, anthropic, sonnet-, opus-, haiku-, grok, composer); not a house id (superbot, superbot-fast, superbot-omni); unique among this key's forwards; not another model's id. A refused name stores nothing. A custom name replaces the default name for that model.

    • app string

      Forwarding app this listed key's model names are spelled for: cursor, copilot-cli, cline, roo, qwen-code, hermes, openclaw, zazen, default. Set at creation, cannot be changed. Absent = cursor.

    • default_model string

      The model a call that names the bare house agent superbot (the default model of Zapier and n8n), or names no model, is answered by instead: superbot-fast, superbot-omni or a model of one of your own accounts. A call that names any other model is dialled as named. Absent = a call naming superbot gets superbot.

    • route string required

      One of byo, credits, auto.

    • mode string required

      One of model, agent.

    • incognito boolean required
    • device_id string
    • org_id string

      Set on a team key.

    • person_id string

      Set on a key minted for a person: per_ + 16 hex. Every key minted for the same person carries the same id. A person key has no device_id and no org_id, and is billed to the owner.

    • person_name string

      The person's display name, 1-64 characters. Present on every person key.

    • person_email string

      The person's email address, when the owner gave one.

    • person_group string

      A free-text grouping the owner sorts people by (a team, a class), 1-64 characters.

    • prompt_history PromptHistory

      What the owner told a person about their prompts, and how long they are kept. Absent on a key until the owner sets it: the person's prompts are then not visible to the owner and follow the account's own retention.

      3 fields
      • visible_to_owner boolean required

        The owner may read this person's prompts.

      • retention_days integer required

        Whole days the prompts are kept, 1-3650.

      • attested_at string (date-time) required

        ISO 8601 time the owner attested the person was told. The owner's own claim, stored as given and not verified; the answer normalises it to UTC.

    • paused_at string (date-time)

      Set while the owner holds this person: until a PATCH clears it the key answers 403 key_paused at the model gateway, the /v1/keys routes, the relay door and the Cosmos door; every other route does not recognise a held key and answers 401 unauthorized. Held is not revoked. It is written to every live key of the person.

    • person_limit_usd number

      The owner's monthly spend limit for this person, in US dollars to the cent. Set by the owner's PUT /v1/keys/person/{person_id}/limit (the Helper), written to every live key of the person, and absent while no limit is set.

    • scopes array of Scope required

      The EFFECTIVE scopes: stored list or the legacy set, team keys capped. One of gateway:invoke, usage:read, billing:read, keys:read, keys:write, endpoints:read, endpoints:write, teams:read, teams:write, devices:read, devices:write, runs:read, runs:write, mcp:invoke, turns:read, tools:invoke.

Errors

StatusCodeWhat to change
400invalid_request

A parameter or body field is invalid; param names it and issues lists every problem.

401unauthorized

Send a live caller key or session as Authorization: Bearer … or x-api-key. No key yet: create one at /account/api, or sign a user in at /auth.md.

403insufficient_scope

The key lacks the scope in required_scopes; mint a key that holds it.

404not_found

No such resource on this account; check the id.

view .mdopenapi
Request

curl

curl -sS -X PATCH "https://superbot.gg/v1/keys/$ID" \
  -H "Authorization: Bearer $SUPERBOT_API_KEY" \
  -H "content-type: application/json" \
  -d '{"name":"your-name","route":"byo","mode":"model"}'

JavaScript

const id = 'ID';
const res = await fetch(`https://superbot.gg/v1/keys/${id}`, {
  method: 'PATCH',
  headers: {
    Authorization: `Bearer ${process.env.SUPERBOT_API_KEY}`,
    'content-type': 'application/json',
  },
  body: JSON.stringify({"name":"your-name","route":"byo","mode":"model"}),
});
console.log(res.status, await res.json());

Python

import os
import requests

id = "ID"
res = requests.request(
    "PATCH",
    f"https://superbot.gg/v1/keys/{id}",
    headers={
        "Authorization": f"Bearer {os.environ['SUPERBOT_API_KEY']}",
        "content-type": "application/json",
    },
    json={"name":"your-name","route":"byo","mode":"model"},
)
print(res.status_code, res.json())
Response

200 The edited key.

{
  "row": {
    "id": "ck_9f2c41d0",
    "user_id": "your-user-id",
    "name": "your-name",
    "mask": "sbc_ab12…cd34",
    "created_at": "2026-09-01T00:00:00Z",
    "last_used_at": "2026-09-01T00:00:00Z",
    "revoked_at": "2026-09-01T00:00:00Z",
    "daily_limit_tokens": 0,
    "monthly_limit_tokens": 0,
    "caps_unit": "credit",
    "allowed_models": [
      "your-allowed-models"
    ],
    "models_listed": true,
    "model_pins": {},
    "model_aliases": {},
    "app": "your-app",
    "default_model": "your-default-model",
    "route": "byo",
    "mode": "model",
    "incognito": true,
    "device_id": "your-device-id",
    "org_id": "your-org-id",
    "person_id": "per_9f2c41d0a7b35e68",
    "person_name": "your-person-name",
    "person_email": "[email protected]",
    "person_group": "your-person-group",
    "prompt_history": {
      "visible_to_owner": true,
      "retention_days": 0,
      "attested_at": "2026-09-01T00:00:00Z"
    },
    "paused_at": "2026-09-01T00:00:00Z",
    "person_limit_usd": 0,
    "scopes": [
      "gateway:invoke"
    ]
  }
}

400 The request is malformed or a parameter is invalid; `param` names the field.

{
  "error": "invalid_request",
  "message": "A parameter or body field is invalid; param names it and issues lists every problem.",
  "doc_url": "https://superbot.gg/developers#errors-invalid_request",
  "request_id": "req_5f1c0a9e2b7d4c3a1e0f9b8d"
}

401 The bearer is missing, malformed or unknown.

{
  "error": "unauthorized",
  "message": "Send a live caller key or session as Authorization: Bearer … or x-api-key. No key yet: create one at /account/api, or sign a user in at /auth.md.",
  "doc_url": "https://superbot.gg/developers#errors-unauthorized",
  "request_id": "req_5f1c0a9e2b7d4c3a1e0f9b8d"
}

403 The key lacks a scope (insufficient_scope), is revoked, or may not call this route.

{
  "error": "insufficient_scope",
  "message": "The key lacks the scope in required_scopes; mint a key that holds it.",
  "doc_url": "https://superbot.gg/developers#errors-insufficient_scope",
  "request_id": "req_5f1c0a9e2b7d4c3a1e0f9b8d"
}

404 No such resource on this account.

{
  "error": "not_found",
  "message": "No such resource on this account; check the id.",
  "doc_url": "https://superbot.gg/developers#errors-not_found",
  "request_id": "req_5f1c0a9e2b7d4c3a1e0f9b8d"
}

Revoke a caller keylink to Revoke a caller key

DELETE /v1/keys/{id}

Revoke a key. Revoking an already-revoked key is a no-op (already: true). A person key is revoked by the account owner only; a caller key that tries answers 403 caller_key_forbidden.

A caller key holding keys:write (Authorization: Bearer sbc_… or x-api-key: sbc_…), or a signed-in session.

Operation id revokeKey in Keys.

Path parameters

  • id string required

Response 200

Revoked.

application/json: RevokedKey.

  • ok boolean required

    One of true.

  • already boolean

Errors

StatusCodeWhat to change
401unauthorized

Send a live caller key or session as Authorization: Bearer … or x-api-key. No key yet: create one at /account/api, or sign a user in at /auth.md.

403insufficient_scope

The key lacks the scope in required_scopes; mint a key that holds it.

404not_found

No such resource on this account; check the id.

view .mdopenapi
Request

curl

curl -sS -X DELETE "https://superbot.gg/v1/keys/$ID" \
  -H "Authorization: Bearer $SUPERBOT_API_KEY"

JavaScript

const id = 'ID';
const res = await fetch(`https://superbot.gg/v1/keys/${id}`, {
  method: 'DELETE',
  headers: {
    Authorization: `Bearer ${process.env.SUPERBOT_API_KEY}`,
  },
});
console.log(res.status, await res.json());

Python

import os
import requests

id = "ID"
res = requests.request(
    "DELETE",
    f"https://superbot.gg/v1/keys/{id}",
    headers={
        "Authorization": f"Bearer {os.environ['SUPERBOT_API_KEY']}",
    },
)
print(res.status_code, res.json())
Response

200 Revoked.

{
  "ok": true,
  "already": true
}

401 The bearer is missing, malformed or unknown.

{
  "error": "unauthorized",
  "message": "Send a live caller key or session as Authorization: Bearer … or x-api-key. No key yet: create one at /account/api, or sign a user in at /auth.md.",
  "doc_url": "https://superbot.gg/developers#errors-unauthorized",
  "request_id": "req_5f1c0a9e2b7d4c3a1e0f9b8d"
}

403 The key lacks a scope (insufficient_scope), is revoked, or may not call this route.

{
  "error": "insufficient_scope",
  "message": "The key lacks the scope in required_scopes; mint a key that holds it.",
  "doc_url": "https://superbot.gg/developers#errors-insufficient_scope",
  "request_id": "req_5f1c0a9e2b7d4c3a1e0f9b8d"
}

404 No such resource on this account.

{
  "error": "not_found",
  "message": "No such resource on this account; check the id.",
  "doc_url": "https://superbot.gg/developers#errors-not_found",
  "request_id": "req_5f1c0a9e2b7d4c3a1e0f9b8d"
}

Rotate a caller keylink to Rotate a caller key

POST /v1/keys/{id}/rotate

Replace a key with a new one of the same shape (name, scopes, route, mode, caps, models, pins, aliases, default model, incognito, the person it is for, the device that minted it) and revoke the old one. The new key is minted first and the old one revoked after, so a failure never leaves the account without a working key. The reply carries the new key in plaintext once (key), its row, and revoked, the id of the key revoked (null if that revoke failed after the mint: the new key is live, so revoke the old one with DELETE /v1/keys/{id}). No body. A key that is revoked already answers 409 revoked; an id this account does not hold answers 404 not_found; a team key answers 400 team_key (rotate it on the team pane). A person key is rotated by the account owner only; a caller key that tries answers 403 caller_key_forbidden. The new key has made no calls yet, so it lists under Zapier or n8n again with its first call.

A caller key holding keys:write (Authorization: Bearer sbc_… or x-api-key: sbc_…), or a signed-in session.

Operation id rotateKey in Keys.

Path parameters

  • id string required

Response 201

The new key, once.

application/json: RotatedKey.

  • key string required

    The new key in plaintext. Shown once.

  • row CallerKey required
    29 fields
    • id string required
    • user_id string required
    • name string required

      What the tool calls itself, 1-64 chars.

    • mask string required

      The only form shown after mint.

    • created_at string (date-time) required
    • last_used_at string (date-time)
    • revoked_at string (date-time)
    • daily_limit_tokens number

      Daily spend cap in whole credits.

    • monthly_limit_tokens number

      Monthly spend cap in whole credits.

    • caps_unit string

      One of credit.

    • allowed_models array of string

      Glob allow-list over model names; absent = every model. With models_listed: the exact canonical ids the key may dial, and empty = none.

    • models_listed boolean

      true = the listed reading: allowed_models are literal canonical ids (no globs), the key lists exactly those as its per-app picker names, and an empty list allows nothing.

    • model_pins object

      Canonical model id to the stable account id it is pinned to: a pinned model dials only that account, and one id pinned to two accounts gets two picker names.

    • model_aliases object

      Canonical model id (a member of allowed_models) to the custom name its picker shows: 1-64 characters of letters, numbers, dots, dashes or colons; no Cursor routing word (claude, gemini, anthropic, sonnet-, opus-, haiku-, grok, composer); not a house id (superbot, superbot-fast, superbot-omni); unique among this key's forwards; not another model's id. A refused name stores nothing. A custom name replaces the default name for that model.

    • app string

      Forwarding app this listed key's model names are spelled for: cursor, copilot-cli, cline, roo, qwen-code, hermes, openclaw, zazen, default. Set at creation, cannot be changed. Absent = cursor.

    • default_model string

      The model a call that names the bare house agent superbot (the default model of Zapier and n8n), or names no model, is answered by instead: superbot-fast, superbot-omni or a model of one of your own accounts. A call that names any other model is dialled as named. Absent = a call naming superbot gets superbot.

    • route string required

      One of byo, credits, auto.

    • mode string required

      One of model, agent.

    • incognito boolean required
    • device_id string
    • org_id string

      Set on a team key.

    • person_id string

      Set on a key minted for a person: per_ + 16 hex. Every key minted for the same person carries the same id. A person key has no device_id and no org_id, and is billed to the owner.

    • person_name string

      The person's display name, 1-64 characters. Present on every person key.

    • person_email string

      The person's email address, when the owner gave one.

    • person_group string

      A free-text grouping the owner sorts people by (a team, a class), 1-64 characters.

    • prompt_history PromptHistory

      What the owner told a person about their prompts, and how long they are kept. Absent on a key until the owner sets it: the person's prompts are then not visible to the owner and follow the account's own retention.

      3 fields
      • visible_to_owner boolean required

        The owner may read this person's prompts.

      • retention_days integer required

        Whole days the prompts are kept, 1-3650.

      • attested_at string (date-time) required

        ISO 8601 time the owner attested the person was told. The owner's own claim, stored as given and not verified; the answer normalises it to UTC.

    • paused_at string (date-time)

      Set while the owner holds this person: until a PATCH clears it the key answers 403 key_paused at the model gateway, the /v1/keys routes, the relay door and the Cosmos door; every other route does not recognise a held key and answers 401 unauthorized. Held is not revoked. It is written to every live key of the person.

    • person_limit_usd number

      The owner's monthly spend limit for this person, in US dollars to the cent. Set by the owner's PUT /v1/keys/person/{person_id}/limit (the Helper), written to every live key of the person, and absent while no limit is set.

    • scopes array of Scope required

      The EFFECTIVE scopes: stored list or the legacy set, team keys capped. One of gateway:invoke, usage:read, billing:read, keys:read, keys:write, endpoints:read, endpoints:write, teams:read, teams:write, devices:read, devices:write, runs:read, runs:write, mcp:invoke, turns:read, tools:invoke.

  • revoked string | null required

    The id of the key that was revoked, or null if that revoke failed after the mint.

Errors

StatusCodeWhat to change
400invalid_request

A parameter or body field is invalid; param names it and issues lists every problem.

401unauthorized

Send a live caller key or session as Authorization: Bearer … or x-api-key. No key yet: create one at /account/api, or sign a user in at /auth.md.

403insufficient_scope

The key lacks the scope in required_scopes; mint a key that holds it.

404not_found

No such resource on this account; check the id.

409conflict

The resource is not in a state that allows this change.

view .mdopenapi
Request

curl

curl -sS -X POST "https://superbot.gg/v1/keys/$ID/rotate" \
  -H "Authorization: Bearer $SUPERBOT_API_KEY"

JavaScript

const id = 'ID';
const res = await fetch(`https://superbot.gg/v1/keys/${id}/rotate`, {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.SUPERBOT_API_KEY}`,
  },
});
console.log(res.status, await res.json());

Python

import os
import requests

id = "ID"
res = requests.request(
    "POST",
    f"https://superbot.gg/v1/keys/{id}/rotate",
    headers={
        "Authorization": f"Bearer {os.environ['SUPERBOT_API_KEY']}",
    },
)
print(res.status_code, res.json())
Response

201 The new key, once.

{
  "key": "your-key",
  "row": {
    "id": "ck_9f2c41d0",
    "user_id": "your-user-id",
    "name": "your-name",
    "mask": "sbc_ab12…cd34",
    "created_at": "2026-09-01T00:00:00Z",
    "last_used_at": "2026-09-01T00:00:00Z",
    "revoked_at": "2026-09-01T00:00:00Z",
    "daily_limit_tokens": 0,
    "monthly_limit_tokens": 0,
    "caps_unit": "credit",
    "allowed_models": [
      "your-allowed-models"
    ],
    "models_listed": true,
    "model_pins": {},
    "model_aliases": {},
    "app": "your-app",
    "default_model": "your-default-model",
    "route": "byo",
    "mode": "model",
    "incognito": true,
    "device_id": "your-device-id",
    "org_id": "your-org-id",
    "person_id": "per_9f2c41d0a7b35e68",
    "person_name": "your-person-name",
    "person_email": "[email protected]",
    "person_group": "your-person-group",
    "prompt_history": {
      "visible_to_owner": true,
      "retention_days": 0,
      "attested_at": "2026-09-01T00:00:00Z"
    },
    "paused_at": "2026-09-01T00:00:00Z",
    "person_limit_usd": 0,
    "scopes": [
      "gateway:invoke"
    ]
  },
  "revoked": "your-revoked"
}

400 The request is malformed or a parameter is invalid; `param` names the field.

{
  "error": "invalid_request",
  "message": "A parameter or body field is invalid; param names it and issues lists every problem.",
  "doc_url": "https://superbot.gg/developers#errors-invalid_request",
  "request_id": "req_5f1c0a9e2b7d4c3a1e0f9b8d"
}

401 The bearer is missing, malformed or unknown.

{
  "error": "unauthorized",
  "message": "Send a live caller key or session as Authorization: Bearer … or x-api-key. No key yet: create one at /account/api, or sign a user in at /auth.md.",
  "doc_url": "https://superbot.gg/developers#errors-unauthorized",
  "request_id": "req_5f1c0a9e2b7d4c3a1e0f9b8d"
}

403 The key lacks a scope (insufficient_scope), is revoked, or may not call this route.

{
  "error": "insufficient_scope",
  "message": "The key lacks the scope in required_scopes; mint a key that holds it.",
  "doc_url": "https://superbot.gg/developers#errors-insufficient_scope",
  "request_id": "req_5f1c0a9e2b7d4c3a1e0f9b8d"
}

404 No such resource on this account.

{
  "error": "not_found",
  "message": "No such resource on this account; check the id.",
  "doc_url": "https://superbot.gg/developers#errors-not_found",
  "request_id": "req_5f1c0a9e2b7d4c3a1e0f9b8d"
}

409 The resource is not in a state that allows this change.

{
  "error": "conflict",
  "message": "The resource is not in a state that allows this change.",
  "doc_url": "https://superbot.gg/developers#errors-conflict",
  "request_id": "req_5f1c0a9e2b7d4c3a1e0f9b8d"
}