{
  "openapi": "3.1.0",
  "info": {
    "title": "RoamAI API",
    "version": "v1",
    "description": "RoamAI has two groups of endpoints:\n\n- **Model calls** are compatible with the Anthropic Messages API and the OpenAI Chat Completions API. The Anthropic and OpenAI SDKs, Claude Code and Claude Desktop work with them unchanged.\n- **Management** endpoints return usage and balance, and create or revoke API keys.\n\n## Base URLs\n\n| Use | Base URL |\n| --- | --- |\n| Model calls | `https://cc-public.roamai.cloud:18443` |\n| Management | `https://roamai.cloud` |\n\nFor model calls, use the address shown under **Use this key** in the console: it is the one for your workspace. The address above works for every workspace.\n\n## Authentication\n\nEvery endpoint takes an API key created in the console (it starts with `rak1_`), in the `x-api-key` header or in `Authorization: Bearer`.\n\nAn API key spends your balance. Use it only from your own server: do not put it in web pages or apps. The management endpoints refuse calls from other sites' pages in the browser.\n\n## Errors\n\nErrors have the same shape as in the Anthropic API:\n\n```json\n{\"type\": \"error\", \"error\": {\"type\": \"invalid_request_error\", \"message\": \"…\"}}\n```\n\n`/v1/chat/completions` returns errors in the OpenAI shape. The message always says what went wrong.\n\n## Timeouts\n\nWhen the workspace is busy, a request can wait for a free slot before it starts. Set client timeouts to 10 minutes or more (the Anthropic and OpenAI SDKs default to 10 minutes)."
  },
  "servers": [
    {
      "url": "https://cc-public.roamai.cloud:18443",
      "description": "Model calls (use the address from the console for your workspace)"
    }
  ],
  "security": [
    {
      "ApiKey": []
    },
    {
      "Bearer": []
    }
  ],
  "tags": [
    {
      "name": "models",
      "x-displayName": "Model calls",
      "description": "Compatible with the Anthropic Messages API and the OpenAI Chat Completions API. Request and response formats, including streaming events, follow the official documentation; the differences are listed under each endpoint."
    },
    {
      "name": "usage",
      "x-displayName": "Usage",
      "description": "Server quotas, balance and spending, for your own dashboards and alerts."
    },
    {
      "name": "keys",
      "x-displayName": "Key management",
      "description": "Create, list and revoke this workspace's keys from your own program, for example one key for each user of your gateway, so that each one can be limited or revoked separately.\n\nThese endpoints need a key with **Manage keys with the API** turned on. An owner or admin turns it on, on the key's page in the console; only keys created by an owner or admin can have it. If that key has an IP allowlist, requests must come from an address in it.\n\nAnyone holding a manager key can create keys without limits. Give it an IP allowlist so it only works from your server.\n\nKeys created this way work like keys created in the console: they belong to the person who created the manager key, and count toward the workspace's 200 keys."
    }
  ],
  "paths": {
    "/v1/messages": {
      "post": {
        "tags": [
          "models"
        ],
        "operationId": "createMessage",
        "summary": "Create a message",
        "description": "Same as the Anthropic Messages API. Set `stream: true` for server-sent events.\n\n**Supported:** text, images (base64), your own tools and `tool_choice`, the web search tool (`web_search_*`, no extra charge), streaming.\n\n**Not supported:**\n- Documents (PDF and others) and images by URL. Send images as base64.\n- A last message from the assistant (prefill). The last message must be from the user.\n- `mcp_servers`.\n- Other server tools (`bash_*`, `web_fetch_*`, `code_execution_*`) are ignored.\n\n**Parameters:** `stop_sequences` work. `max_tokens` is used to estimate the cost of the request; it does not limit the length of the answer. `temperature`, `top_p` and `top_k` have no effect.\n\nThe key's model allowlist and effort cap apply: a higher effort is lowered to the cap.",
        "externalDocs": {
          "url": "https://docs.claude.com/en/api/messages"
        },
        "servers": [
          {
            "url": "https://cc-public.roamai.cloud:18443",
            "description": "Model calls (use the address from the console for your workspace)"
          }
        ],
        "parameters": [
          {
            "name": "anthropic-version",
            "in": "header",
            "required": false,
            "description": "Optional. Accepted for SDK compatibility.",
            "schema": {
              "type": "string",
              "example": "2023-06-01"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/MessageRequest"
              },
              "example": {
                "model": "claude-opus-5-5",
                "max_tokens": 1024,
                "messages": [
                  {
                    "role": "user",
                    "content": "Hello"
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The message. With `stream: true`, server-sent events in the Anthropic format.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Message"
                },
                "example": {
                  "id": "msg_roamai_8505248a3e24750ca2d8eda9",
                  "type": "message",
                  "role": "assistant",
                  "model": "claude-opus-5-5",
                  "content": [
                    {
                      "type": "text",
                      "text": "Hello! How can I help?"
                    }
                  ],
                  "stop_reason": "end_turn",
                  "stop_sequence": null,
                  "usage": {
                    "input_tokens": 12,
                    "output_tokens": 9,
                    "cache_read_input_tokens": 0,
                    "cache_creation_input_tokens": 0
                  }
                }
              },
              "text/event-stream": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "The request is not valid or uses something not supported; or the balance has run out (top up in the console). The message says which.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "type": "error",
                  "error": {
                    "type": "invalid_request_error",
                    "message": "messages.0.content.0: content block type \"document\" is not supported by roamai api"
                  }
                }
              }
            }
          },
          "401": {
            "description": "The API key is wrong, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "type": "error",
                  "error": {
                    "type": "authentication_error",
                    "message": "invalid api key (create one in the RoamAI console)"
                  }
                }
              }
            }
          },
          "403": {
            "description": "The key is paused or suspended, the request's IP is not in the key's allowlist, or the key or workspace does not allow this model.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "type": "error",
                  "error": {
                    "type": "permission_error",
                    "message": "this API key cannot use model \"claude-haiku-4-5\"; it allows models starting with: claude-opus"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Too many requests running on this key at once and none finished in time; a spend limit of the key (5h, 1d, 7d) is used up; or too many wrong keys from this IP.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "type": "error",
                  "error": {
                    "type": "rate_limit_error",
                    "message": "this API key already has 3 requests running, its concurrency limit; waited 300s for one to finish. Try again when they finish, or send fewer requests at once."
                  }
                }
              }
            }
          },
          "503": {
            "description": "No server can take the request right now. Retry later.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "type": "error",
                  "error": {
                    "type": "api_error",
                    "message": "No available accounts"
                  }
                }
              }
            }
          },
          "529": {
            "description": "All servers stayed busy while the request waited. Retry later.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "type": "error",
                  "error": {
                    "type": "overloaded_error",
                    "message": "waited 300s for a free slot; no free slot"
                  }
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X POST https://cc-public.roamai.cloud:18443/v1/messages \\\n  -H \"x-api-key: YOUR_API_KEY\" \\\n  -H \"content-type: application/json\" \\\n  -d '{\"model\":\"claude-opus-5-5\",\"max_tokens\":1024,\"messages\":[{\"role\":\"user\",\"content\":\"Hello\"}]}'"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import anthropic\n\nclient = anthropic.Anthropic(base_url=\"https://cc-public.roamai.cloud:18443\", api_key=\"YOUR_API_KEY\")\nmessage = client.messages.create(\n    model=\"claude-opus-5-5\",\n    max_tokens=1024,\n    messages=[{\"role\": \"user\", \"content\": \"Hello\"}],\n)\nprint(message.content[0].text)"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import Anthropic from \"@anthropic-ai/sdk\";\n\nconst client = new Anthropic({ baseURL: \"https://cc-public.roamai.cloud:18443\", apiKey: \"YOUR_API_KEY\" });\nconst message = await client.messages.create({\n  model: \"claude-opus-5-5\",\n  max_tokens: 1024,\n  messages: [{ role: \"user\", content: \"Hello\" }],\n});\nconsole.log(message.content[0].text);"
          }
        ]
      }
    },
    "/v1/messages/count_tokens": {
      "post": {
        "tags": [
          "models"
        ],
        "operationId": "countTokens",
        "summary": "Count tokens (estimate)",
        "description": "Same request as `/v1/messages`. The count is an **estimate**: a CJK character counts as 1 token, other text as 1 token per 3.5 characters, each image or document as 1,600. Good enough to check whether a request fits; not for billing. The response has the header `X-RoamAI-Token-Count: estimate`. Free.",
        "servers": [
          {
            "url": "https://cc-public.roamai.cloud:18443",
            "description": "Model calls (use the address from the console for your workspace)"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/MessageRequest"
              },
              "example": {
                "model": "claude-opus-5-5",
                "max_tokens": 1024,
                "messages": [
                  {
                    "role": "user",
                    "content": "Hello"
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The estimated count.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TokenCount"
                },
                "example": {
                  "input_tokens": 12
                }
              }
            }
          },
          "400": {
            "description": "The request is not valid or uses something not supported; or the balance has run out (top up in the console). The message says which.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "type": "error",
                  "error": {
                    "type": "invalid_request_error",
                    "message": "messages.0.content.0: content block type \"document\" is not supported by roamai api"
                  }
                }
              }
            }
          },
          "401": {
            "description": "The API key is wrong, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "type": "error",
                  "error": {
                    "type": "authentication_error",
                    "message": "invalid api key (create one in the RoamAI console)"
                  }
                }
              }
            }
          },
          "403": {
            "description": "The key is paused or suspended, the request's IP is not in the key's allowlist, or the key or workspace does not allow this model.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "type": "error",
                  "error": {
                    "type": "permission_error",
                    "message": "this API key cannot use model \"claude-haiku-4-5\"; it allows models starting with: claude-opus"
                  }
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X POST https://cc-public.roamai.cloud:18443/v1/messages/count_tokens \\\n  -H \"x-api-key: YOUR_API_KEY\" \\\n  -H \"content-type: application/json\" \\\n  -d '{\"model\":\"claude-opus-5-5\",\"max_tokens\":1024,\"messages\":[{\"role\":\"user\",\"content\":\"Hello\"}]}'"
          }
        ]
      }
    },
    "/v1/chat/completions": {
      "post": {
        "tags": [
          "models"
        ],
        "operationId": "createChatCompletion",
        "summary": "Create a chat completion (OpenAI-compatible)",
        "description": "Same as the OpenAI Chat Completions API, for clients that only speak OpenAI. Model names are the same as for `/v1/messages`.\n\n**Not supported:** `tools` and `functions`; `n` above 1; images by URL (send `data:` URLs with base64).\n\n`stop` works. `max_tokens` (or `max_completion_tokens`) is used to estimate the cost; it does not limit the length of the answer. `temperature` and `top_p` have no effect.\n\nWhen streaming, set `stream_options.include_usage: true` to get token usage in the last chunk.",
        "externalDocs": {
          "url": "https://platform.openai.com/docs/api-reference/chat"
        },
        "servers": [
          {
            "url": "https://cc-public.roamai.cloud:18443",
            "description": "Model calls (use the address from the console for your workspace)"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ChatRequest"
              },
              "example": {
                "model": "claude-opus-5-5",
                "messages": [
                  {
                    "role": "user",
                    "content": "Hello"
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The chat completion. With `stream: true`, server-sent events in the OpenAI format.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ChatCompletion"
                },
                "example": {
                  "id": "chatcmpl-roamai-8505248a3e24750ca2d8eda9",
                  "object": "chat.completion",
                  "created": 1793350000,
                  "model": "claude-opus-5-5",
                  "choices": [
                    {
                      "index": 0,
                      "message": {
                        "role": "assistant",
                        "content": "Hello! How can I help?"
                      },
                      "finish_reason": "stop"
                    }
                  ],
                  "usage": {
                    "prompt_tokens": 12,
                    "completion_tokens": 9,
                    "total_tokens": 21,
                    "prompt_tokens_details": {
                      "cached_tokens": 0
                    }
                  }
                }
              },
              "text/event-stream": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "The request is not valid or uses something not supported; or the balance has run out (top up in the console). The message says which.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "type": "error",
                  "error": {
                    "type": "invalid_request_error",
                    "message": "messages.0.content.0: content block type \"document\" is not supported by roamai api"
                  }
                }
              }
            }
          },
          "401": {
            "description": "The API key is wrong, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "type": "error",
                  "error": {
                    "type": "authentication_error",
                    "message": "invalid api key (create one in the RoamAI console)"
                  }
                }
              }
            }
          },
          "403": {
            "description": "The key is paused or suspended, the request's IP is not in the key's allowlist, or the key or workspace does not allow this model.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "type": "error",
                  "error": {
                    "type": "permission_error",
                    "message": "this API key cannot use model \"claude-haiku-4-5\"; it allows models starting with: claude-opus"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Too many requests running on this key at once and none finished in time; a spend limit of the key (5h, 1d, 7d) is used up; or too many wrong keys from this IP.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "type": "error",
                  "error": {
                    "type": "rate_limit_error",
                    "message": "this API key already has 3 requests running, its concurrency limit; waited 300s for one to finish. Try again when they finish, or send fewer requests at once."
                  }
                }
              }
            }
          },
          "503": {
            "description": "No server can take the request right now. Retry later.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "type": "error",
                  "error": {
                    "type": "api_error",
                    "message": "No available accounts"
                  }
                }
              }
            }
          },
          "529": {
            "description": "All servers stayed busy while the request waited. Retry later.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "type": "error",
                  "error": {
                    "type": "overloaded_error",
                    "message": "waited 300s for a free slot; no free slot"
                  }
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X POST https://cc-public.roamai.cloud:18443/v1/chat/completions \\\n  -H \"x-api-key: YOUR_API_KEY\" \\\n  -H \"content-type: application/json\" \\\n  -d '{\"model\":\"claude-opus-5-5\",\"messages\":[{\"role\":\"user\",\"content\":\"Hello\"}]}'"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from openai import OpenAI\n\nclient = OpenAI(base_url=\"https://cc-public.roamai.cloud:18443/v1\", api_key=\"YOUR_API_KEY\")\ncompletion = client.chat.completions.create(\n    model=\"claude-opus-5-5\",\n    messages=[{\"role\": \"user\", \"content\": \"Hello\"}],\n)\nprint(completion.choices[0].message.content)"
          }
        ]
      }
    },
    "/v1/models": {
      "get": {
        "tags": [
          "models"
        ],
        "operationId": "listModels",
        "summary": "List models",
        "description": "The models this key can use right now, default first. A model with a 1M-token context window is listed once, with `[1m]` at the end of its id. Requests also accept the id without `[1m]`, older model ids and aliases.",
        "servers": [
          {
            "url": "https://cc-public.roamai.cloud:18443",
            "description": "Model calls (use the address from the console for your workspace)"
          }
        ],
        "responses": {
          "200": {
            "description": "The models.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ModelList"
                },
                "example": {
                  "object": "list",
                  "data": [
                    {
                      "id": "claude-opus-5-5[1m]",
                      "type": "model",
                      "object": "model",
                      "display_name": "Opus 5.5",
                      "created_at": "2026-01-01T00:00:00Z",
                      "created": 0,
                      "owned_by": "roamai"
                    },
                    {
                      "id": "claude-sonnet-5-5",
                      "type": "model",
                      "object": "model",
                      "display_name": "Sonnet 5.5",
                      "created_at": "2026-01-01T00:00:00Z",
                      "created": 0,
                      "owned_by": "roamai"
                    }
                  ],
                  "has_more": false,
                  "first_id": null,
                  "last_id": null
                }
              }
            }
          },
          "401": {
            "description": "The API key is wrong, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "type": "error",
                  "error": {
                    "type": "authentication_error",
                    "message": "invalid api key (create one in the RoamAI console)"
                  }
                }
              }
            }
          },
          "503": {
            "description": "No server can take the request right now. Retry later.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "type": "error",
                  "error": {
                    "type": "api_error",
                    "message": "No available accounts"
                  }
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl https://cc-public.roamai.cloud:18443/v1/models \\\n  -H \"x-api-key: YOUR_API_KEY\""
          }
        ]
      }
    },
    "/api/v1/usage": {
      "get": {
        "tags": [
          "usage"
        ],
        "operationId": "getUsage",
        "summary": "Get usage and balance",
        "description": "Server quotas, balance, and spending of this key. What comes back depends on who created the key:\n\n| Key created by | Returns |\n| --- | --- |\n| owner or admin | All servers in the workspace, plan and balance, this key, and the usage of every key in the workspace (`keys`). |\n| member | The servers this key can use, plan and balance, this key. No `keys`. |\n\nRoles are as of now. Keys that are revoked, or whose creator left the workspace, get 401. Paused, suspended and expired keys still get an answer, with the reason in `key.status`.\n\nServer quotas change at most every 5 minutes; polling once a minute is enough. Times are UTC ISO 8601. Amounts are in the balance's US dollars. Fields with no data are `null`.",
        "servers": [
          {
            "url": "https://roamai.cloud",
            "description": "Management"
          }
        ],
        "parameters": [
          {
            "name": "from",
            "in": "query",
            "required": false,
            "description": "Optional. A date (`YYYY-MM-DD`, from 00:00 UTC) or an ISO time with a time zone. Requests at or after it are counted.",
            "schema": {
              "type": "string",
              "example": "2026-10-01"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "description": "Optional. Same format. Requests before it are counted. Only the totals in `usage` use `from` and `to`; quotas, balance and spending windows are always as of now.",
            "schema": {
              "type": "string",
              "example": "2026-11-01"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Usage and balance.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Usage"
                },
                "example": {
                  "object": "usage",
                  "scope": "workspace",
                  "generated_at": "2026-10-14T08:00:00.000Z",
                  "period": {
                    "from": "2026-10-13T00:00:00.000Z",
                    "to": null
                  },
                  "workspace": {
                    "plan": "vip_std",
                    "service": {
                      "active": true,
                      "until": "2026-11-02T00:00:00.000Z",
                      "renews": true
                    },
                    "balance": {
                      "usd": 187.42,
                      "enforced": true,
                      "refused": false
                    }
                  },
                  "servers": [
                    {
                      "name": "build-1",
                      "online": true,
                      "account": "ok",
                      "five_hour": {
                        "used_percent": 34,
                        "resets_at": "2026-10-14T10:13:00.000Z"
                      },
                      "seven_day": {
                        "used_percent": 41,
                        "resets_at": "2026-10-17T13:00:00.000Z"
                      },
                      "sampled_at": "2026-10-14T07:57:00.000Z",
                      "stale": false,
                      "api_reserve_percent": {
                        "five_hour": 50,
                        "seven_day": 80
                      },
                      "api_paused_until": null
                    },
                    {
                      "name": "build-2",
                      "online": true,
                      "account": "ok",
                      "five_hour": {
                        "used_percent": 52,
                        "resets_at": "2026-10-14T08:47:00.000Z"
                      },
                      "seven_day": {
                        "used_percent": 63,
                        "resets_at": "2026-10-19T10:00:00.000Z"
                      },
                      "sampled_at": "2026-10-14T07:56:00.000Z",
                      "stale": false,
                      "api_reserve_percent": {
                        "five_hour": 50,
                        "seven_day": 80
                      },
                      "api_paused_until": "2026-10-14T08:47:00.000Z"
                    }
                  ],
                  "key": {
                    "id": "5b0e2c1a-7d4f-4a8e-9c3b-1f2d3e4a5b6c",
                    "name": "ci-runner",
                    "prefix": "rak1_Qm7tK2",
                    "status": "active",
                    "created_at": "2026-09-02T03:15:00.000Z",
                    "last_used_at": "2026-10-14T07:58:41.000Z",
                    "expires_at": null,
                    "limits_usd": {
                      "total": null,
                      "5h": 20,
                      "1d": null,
                      "7d": null
                    },
                    "spend_usd": {
                      "total": 412.37,
                      "5h": 3.12,
                      "1d": 18.4,
                      "7d": 96.75
                    },
                    "exhausted": null,
                    "usage": {
                      "requests": 214,
                      "input_tokens": 2100000,
                      "output_tokens": 96000,
                      "cache_read_tokens": 28400000,
                      "cache_write_tokens": 1250000,
                      "web_searches": 3,
                      "cost_usd": 24.31,
                      "last_request_at": "2026-10-14T07:58:41.000Z",
                      "daily_tokens": {
                        "2026-10-13": 22415000,
                        "2026-10-14": 9431000
                      }
                    },
                    "allowed_models": null,
                    "max_effort": null,
                    "workspace_allowed_models": null,
                    "workspace_max_effort": null,
                    "recent_requests": [
                      {
                        "at": "2026-10-14T07:58:41.000Z",
                        "model": "claude-sonnet-5",
                        "input_tokens": 2140,
                        "output_tokens": 812,
                        "cache_read_tokens": 98200,
                        "cache_write_tokens": 1530,
                        "web_searches": 0,
                        "cost_usd": 0.0612
                      }
                    ]
                  },
                  "keys": [
                    {
                      "id": "5b0e2c1a-7d4f-4a8e-9c3b-1f2d3e4a5b6c",
                      "name": "ci-runner",
                      "prefix": "rak1_Qm7tK2",
                      "status": "active",
                      "created_at": "2026-09-02T03:15:00.000Z",
                      "last_used_at": "2026-10-14T07:58:41.000Z",
                      "expires_at": null,
                      "limits_usd": {
                        "total": null,
                        "5h": 20,
                        "1d": null,
                        "7d": null
                      },
                      "spend_usd": {
                        "total": 412.37,
                        "5h": 3.12,
                        "1d": 18.4,
                        "7d": 96.75
                      },
                      "exhausted": null,
                      "usage": {
                        "requests": 214,
                        "input_tokens": 2100000,
                        "output_tokens": 96000,
                        "cache_read_tokens": 28400000,
                        "cache_write_tokens": 1250000,
                        "web_searches": 3,
                        "cost_usd": 24.31,
                        "last_request_at": "2026-10-14T07:58:41.000Z",
                        "daily_tokens": {
                          "2026-10-13": 22415000,
                          "2026-10-14": 9431000
                        }
                      },
                      "creator_email": "lin@example.com",
                      "revoked_at": null,
                      "servers": []
                    },
                    {
                      "id": "c81f4b7e-2a90-4d3c-b6e5-8a7f9d0e1c2b",
                      "name": "design-laptop",
                      "prefix": "rak1_Vz3pN8",
                      "status": "active",
                      "created_at": "2026-09-20T09:40:00.000Z",
                      "last_used_at": "2026-10-14T07:41:05.000Z",
                      "expires_at": null,
                      "limits_usd": {
                        "total": null,
                        "5h": 5,
                        "1d": null,
                        "7d": null
                      },
                      "spend_usd": {
                        "total": 58.2,
                        "5h": 5,
                        "1d": 7.9,
                        "7d": 31.6
                      },
                      "exhausted": {
                        "window": "5h",
                        "limit_usd": 5,
                        "until": "2026-10-14T09:12:00.000Z"
                      },
                      "usage": {
                        "requests": 61,
                        "input_tokens": 640000,
                        "output_tokens": 31000,
                        "cache_read_tokens": 7900000,
                        "cache_write_tokens": 410000,
                        "web_searches": 0,
                        "cost_usd": 7.9,
                        "last_request_at": "2026-10-14T07:41:05.000Z",
                        "daily_tokens": {
                          "2026-10-13": 6120000,
                          "2026-10-14": 2861000
                        }
                      },
                      "creator_email": "chen@example.com",
                      "revoked_at": null,
                      "servers": [
                        "build-2"
                      ]
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "`from` or `to` is not a date or time, or `from` is not before `to`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "type": "error",
                  "error": {
                    "type": "invalid_request_error",
                    "message": "from / to must be dates (YYYY-MM-DD) or ISO times, from before to"
                  }
                }
              }
            }
          },
          "401": {
            "description": "The key is wrong or revoked, or the person who created it left the workspace.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "type": "error",
                  "error": {
                    "type": "authentication_error",
                    "message": "invalid x-api-key"
                  }
                }
              }
            }
          },
          "429": {
            "description": "More than 30 requests a minute from one key, or 60 from one IP.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "type": "error",
                  "error": {
                    "type": "rate_limit_error",
                    "message": "too many requests; poll at most once a minute"
                  }
                }
              }
            }
          },
          "500": {
            "description": "The request failed. Retry in a minute.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "type": "error",
                  "error": {
                    "type": "api_error",
                    "message": "internal error"
                  }
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl \"https://roamai.cloud/api/v1/usage?from=2026-10-01&to=2026-11-01\" \\\n  -H \"x-api-key: YOUR_API_KEY\""
          }
        ]
      }
    },
    "/api/v1/keys": {
      "get": {
        "tags": [
          "keys"
        ],
        "operationId": "listKeys",
        "summary": "List keys",
        "description": "Keys in this workspace that are not revoked, oldest first. `created_by_key` is the id of the manager key that created a key through this API (`null` = created in the console).",
        "servers": [
          {
            "url": "https://roamai.cloud",
            "description": "Management"
          }
        ],
        "responses": {
          "200": {
            "description": "The keys.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/KeyList"
                },
                "example": {
                  "object": "list",
                  "data": [
                    {
                      "id": "8d3f0c2e-61b4-4f7a-a2d9-0e5c7b1f4a36",
                      "name": "alice@example.com",
                      "prefix": "rak1_Hs8wQ2a",
                      "status": "active",
                      "created_at": "2026-10-30T10:12:04.511284+00:00",
                      "last_used_at": null,
                      "expires_at": null,
                      "revoked_at": null,
                      "servers": [],
                      "limits_usd": {
                        "total": null,
                        "5h": null,
                        "1d": 20,
                        "7d": null
                      },
                      "allowed_models": null,
                      "allowed_ips": null,
                      "max_concurrency": 3,
                      "max_effort": null,
                      "can_manage_keys": false,
                      "created_by_key": "5b0e2c1a-7d4f-4a8e-9c3b-1f2d3e4a5b6c"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "The key is wrong or revoked, or the person who created it left the workspace.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "type": "error",
                  "error": {
                    "type": "authentication_error",
                    "message": "invalid x-api-key"
                  }
                }
              }
            }
          },
          "403": {
            "description": "The key cannot manage keys; it is paused, suspended or expired; or the request's IP is not in its allowlist.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "type": "error",
                  "error": {
                    "type": "permission_error",
                    "message": "this API key is not allowed to manage keys; an owner or admin can turn on \"Manage keys with the API\" on its page in the RoamAI console"
                  }
                }
              }
            }
          },
          "429": {
            "description": "More than 120 requests a minute from one key or one IP.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "type": "error",
                  "error": {
                    "type": "rate_limit_error",
                    "message": "too many requests; slow down"
                  }
                }
              }
            }
          },
          "500": {
            "description": "The request failed. Retry in a minute.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "type": "error",
                  "error": {
                    "type": "api_error",
                    "message": "internal error"
                  }
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl https://roamai.cloud/api/v1/keys \\\n  -H \"x-api-key: YOUR_API_KEY\""
          }
        ]
      },
      "post": {
        "tags": [
          "keys"
        ],
        "operationId": "createKey",
        "summary": "Create a key",
        "description": "Only `name` is required. The response has the full key in `key`. **It is shown only this once: store it.** Unknown fields are refused, so a misspelled limit does not silently create a key without it.",
        "servers": [
          {
            "url": "https://roamai.cloud",
            "description": "Management"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateKey"
              },
              "example": {
                "name": "alice@example.com",
                "max_concurrency": 3,
                "limits_usd": {
                  "1d": 20
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The new key, with the full key in `key`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NewKey"
                },
                "example": {
                  "key": "rak1_Hs8wQ2aT…",
                  "id": "8d3f0c2e-61b4-4f7a-a2d9-0e5c7b1f4a36",
                  "name": "alice@example.com",
                  "prefix": "rak1_Hs8wQ2a",
                  "status": "active",
                  "created_at": "2026-10-30T10:12:04.511284+00:00",
                  "last_used_at": null,
                  "expires_at": null,
                  "revoked_at": null,
                  "servers": [],
                  "limits_usd": {
                    "total": null,
                    "5h": null,
                    "1d": 20,
                    "7d": null
                  },
                  "allowed_models": null,
                  "allowed_ips": null,
                  "max_concurrency": 3,
                  "max_effort": null,
                  "can_manage_keys": false,
                  "created_by_key": "5b0e2c1a-7d4f-4a8e-9c3b-1f2d3e4a5b6c"
                }
              }
            }
          },
          "400": {
            "description": "A field is missing or not valid. The message says which.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "type": "error",
                  "error": {
                    "type": "invalid_request_error",
                    "message": "unknown field: concurrency"
                  }
                }
              }
            }
          },
          "401": {
            "description": "The key is wrong or revoked, or the person who created it left the workspace.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "type": "error",
                  "error": {
                    "type": "authentication_error",
                    "message": "invalid x-api-key"
                  }
                }
              }
            }
          },
          "403": {
            "description": "The key cannot manage keys; it is paused, suspended or expired; or the request's IP is not in its allowlist.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "type": "error",
                  "error": {
                    "type": "permission_error",
                    "message": "this API key is not allowed to manage keys; an owner or admin can turn on \"Manage keys with the API\" on its page in the RoamAI console"
                  }
                }
              }
            }
          },
          "409": {
            "description": "The workspace already has 200 keys that are not revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "type": "error",
                  "error": {
                    "type": "invalid_request_error",
                    "message": "the workspace already has 200 active API keys; revoke some first"
                  }
                }
              }
            }
          },
          "413": {
            "description": "The request body is larger than 16 KB.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "type": "error",
                  "error": {
                    "type": "request_too_large",
                    "message": "request body too large"
                  }
                }
              }
            }
          },
          "429": {
            "description": "More than 120 requests a minute from one key or one IP.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "type": "error",
                  "error": {
                    "type": "rate_limit_error",
                    "message": "too many requests; slow down"
                  }
                }
              }
            }
          },
          "500": {
            "description": "The request failed. Retry in a minute.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "type": "error",
                  "error": {
                    "type": "api_error",
                    "message": "internal error"
                  }
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X POST https://roamai.cloud/api/v1/keys \\\n  -H \"x-api-key: YOUR_API_KEY\" \\\n  -H \"content-type: application/json\" \\\n  -d '{\"name\":\"alice@example.com\",\"max_concurrency\":3,\"limits_usd\":{\"1d\":20}}'"
          }
        ]
      }
    },
    "/api/v1/keys/{id}": {
      "delete": {
        "tags": [
          "keys"
        ],
        "operationId": "revokeKey",
        "summary": "Revoke a key",
        "description": "Revokes a key in this workspace (it can be the manager key itself). Requests made with it are refused within about a minute. This cannot be undone.",
        "servers": [
          {
            "url": "https://roamai.cloud",
            "description": "Management"
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The key's `id`.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The revoked key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Key"
                },
                "example": {
                  "id": "8d3f0c2e-61b4-4f7a-a2d9-0e5c7b1f4a36",
                  "name": "alice@example.com",
                  "prefix": "rak1_Hs8wQ2a",
                  "status": "revoked",
                  "created_at": "2026-10-30T10:12:04.511284+00:00",
                  "last_used_at": null,
                  "expires_at": null,
                  "revoked_at": "2026-10-31T02:00:00.000000+00:00",
                  "servers": [],
                  "limits_usd": {
                    "total": null,
                    "5h": null,
                    "1d": 20,
                    "7d": null
                  },
                  "allowed_models": null,
                  "allowed_ips": null,
                  "max_concurrency": 3,
                  "max_effort": null,
                  "can_manage_keys": false,
                  "created_by_key": "5b0e2c1a-7d4f-4a8e-9c3b-1f2d3e4a5b6c"
                }
              }
            }
          },
          "401": {
            "description": "The key is wrong or revoked, or the person who created it left the workspace.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "type": "error",
                  "error": {
                    "type": "authentication_error",
                    "message": "invalid x-api-key"
                  }
                }
              }
            }
          },
          "403": {
            "description": "The key cannot manage keys; it is paused, suspended or expired; or the request's IP is not in its allowlist.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "type": "error",
                  "error": {
                    "type": "permission_error",
                    "message": "this API key is not allowed to manage keys; an owner or admin can turn on \"Manage keys with the API\" on its page in the RoamAI console"
                  }
                }
              }
            }
          },
          "404": {
            "description": "No key with this id that is not revoked in this workspace.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "type": "error",
                  "error": {
                    "type": "not_found_error",
                    "message": "no active API key with this id in the workspace"
                  }
                }
              }
            }
          },
          "429": {
            "description": "More than 120 requests a minute from one key or one IP.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "type": "error",
                  "error": {
                    "type": "rate_limit_error",
                    "message": "too many requests; slow down"
                  }
                }
              }
            }
          },
          "500": {
            "description": "The request failed. Retry in a minute.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "type": "error",
                  "error": {
                    "type": "api_error",
                    "message": "internal error"
                  }
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X DELETE https://roamai.cloud/api/v1/keys/8d3f0c2e-61b4-4f7a-a2d9-0e5c7b1f4a36 \\\n  -H \"x-api-key: YOUR_API_KEY\""
          }
        ]
      }
    }
  },
  "components": {
    "securitySchemes": {
      "ApiKey": {
        "type": "apiKey",
        "in": "header",
        "name": "x-api-key",
        "description": "API key from the console, in the `x-api-key` header."
      },
      "Bearer": {
        "type": "http",
        "scheme": "bearer",
        "description": "The same API key, as `Authorization: Bearer rak1_…`."
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "const": "error",
            "description": "Always `error`."
          },
          "error": {
            "type": "object",
            "properties": {
              "type": {
                "type": "string",
                "description": "`invalid_request_error`, `authentication_error`, `permission_error`, `not_found_error`, `rate_limit_error`, `api_error` or `overloaded_error`."
              },
              "message": {
                "type": "string",
                "description": "What went wrong."
              }
            },
            "required": [
              "type",
              "message"
            ]
          }
        },
        "required": [
          "type",
          "error"
        ]
      },
      "MessageRequest": {
        "type": "object",
        "properties": {
          "model": {
            "type": "string",
            "description": "A model id from `/v1/models`, e.g. `claude-opus-5-5`."
          },
          "max_tokens": {
            "type": "integer",
            "minimum": 1,
            "description": "Required, as in the Anthropic API. Used to estimate the cost; does not limit the length of the answer."
          },
          "messages": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "The conversation. The last message must be from the user."
          },
          "system": {
            "oneOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "object"
                }
              }
            ],
            "description": "System prompt: a string or text blocks."
          },
          "stream": {
            "type": "boolean",
            "description": "`true` for server-sent events."
          },
          "stop_sequences": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Text that ends the answer."
          },
          "tools": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Your tools (`name`, `description`, `input_schema`), and the web search tool."
          },
          "tool_choice": {
            "type": "object",
            "description": "`auto`, `any`, `tool` (with `name`) or `none`."
          },
          "metadata": {
            "type": "object",
            "description": "As in the Anthropic API."
          }
        },
        "required": [
          "model",
          "max_tokens",
          "messages"
        ],
        "additionalProperties": true
      },
      "Message": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Message id."
          },
          "type": {
            "type": "string",
            "const": "message",
            "description": "Always `message`."
          },
          "role": {
            "type": "string",
            "const": "assistant",
            "description": "Always `assistant`."
          },
          "model": {
            "type": "string",
            "description": "The model that answered."
          },
          "content": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Content blocks: `text`, `tool_use`, web search results."
          },
          "stop_reason": {
            "type": [
              "string",
              "null"
            ],
            "description": "`end_turn`, `max_tokens`, `stop_sequence` or `tool_use`."
          },
          "stop_sequence": {
            "type": [
              "string",
              "null"
            ]
          },
          "usage": {
            "type": "object",
            "description": "Tokens: `input_tokens`, `output_tokens`, `cache_read_input_tokens`, `cache_creation_input_tokens`; with web search, `server_tool_use.web_search_requests`."
          }
        }
      },
      "TokenCount": {
        "type": "object",
        "properties": {
          "input_tokens": {
            "type": "integer",
            "description": "Estimated input tokens."
          }
        },
        "required": [
          "input_tokens"
        ]
      },
      "ChatRequest": {
        "type": "object",
        "properties": {
          "model": {
            "type": "string",
            "description": "A model id from `/v1/models`."
          },
          "messages": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "`system`, `user` and `assistant` messages. Content is a string or text and `image_url` parts."
          },
          "max_tokens": {
            "type": "integer",
            "description": "Used to estimate the cost; does not limit the length of the answer (`max_completion_tokens` also works)."
          },
          "stream": {
            "type": "boolean",
            "description": "`true` for server-sent events."
          },
          "stream_options": {
            "type": "object",
            "properties": {
              "include_usage": {
                "type": "boolean"
              }
            },
            "description": "`{\"include_usage\": true}` to get usage in the last streamed chunk."
          },
          "reasoning_effort": {
            "type": "string",
            "enum": [
              "minimal",
              "low",
              "medium",
              "high",
              "xhigh"
            ],
            "description": "`low`, `medium`, `high` or `xhigh`."
          }
        },
        "required": [
          "model",
          "messages"
        ],
        "additionalProperties": true
      },
      "ChatCompletion": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Completion id."
          },
          "object": {
            "type": "string",
            "const": "chat.completion",
            "description": "Always `chat.completion`."
          },
          "created": {
            "type": "integer"
          },
          "model": {
            "type": "string",
            "description": "The model that answered."
          },
          "choices": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "One choice, with the assistant's `message` and `finish_reason`."
          },
          "usage": {
            "type": "object",
            "description": "`prompt_tokens`, `completion_tokens`, `total_tokens`, and `prompt_tokens_details.cached_tokens`."
          }
        }
      },
      "Model": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Model id to put in `model`."
          },
          "type": {
            "type": "string",
            "const": "model"
          },
          "object": {
            "type": "string",
            "const": "model"
          },
          "display_name": {
            "type": "string",
            "description": "Display name."
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "created": {
            "type": "integer"
          },
          "owned_by": {
            "type": "string"
          }
        }
      },
      "ModelList": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "const": "list",
            "description": "Always `list`."
          },
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Model"
            },
            "description": "The models."
          },
          "has_more": {
            "type": "boolean"
          },
          "first_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "last_id": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "Window": {
        "type": "object",
        "properties": {
          "used_percent": {
            "type": "number",
            "minimum": 0,
            "maximum": 100,
            "description": "Percent used, 0 to 100."
          },
          "resets_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the window resets. A window that reset after sampling shows 0 and `null`."
          }
        }
      },
      "Server": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "description": "Server name."
          },
          "online": {
            "type": "boolean",
            "description": "Whether the server is online now."
          },
          "account": {
            "type": "string",
            "enum": [
              "ok",
              "banned",
              "login_invalid",
              "no_login",
              "unknown"
            ],
            "description": "Claude account: `ok`, `banned`, `login_invalid` (the login expired), `no_login` or `unknown` (not checked yet)."
          },
          "five_hour": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/Window"
              },
              {
                "type": "null"
              }
            ],
            "description": "The subscription's 5-hour window. `null` when the server has no data yet."
          },
          "seven_day": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/Window"
              },
              {
                "type": "null"
              }
            ],
            "description": "The subscription's 7-day window. `null` when the server has no data yet."
          },
          "sampled_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the quota was sampled. Servers update it while handling requests, and about hourly when idle; it reaches here within 5 minutes."
          },
          "stale": {
            "type": "boolean",
            "description": "`true` when the data is more than 75 minutes old."
          },
          "api_reserve_percent": {
            "type": "object",
            "properties": {
              "five_hour": {
                "type": [
                  "number",
                  "null"
                ]
              },
              "seven_day": {
                "type": [
                  "number",
                  "null"
                ]
              }
            },
            "description": "For each window, the line kept for the subscription owner. Once a window's use reaches it, the server takes no API requests until the window resets. `null` = no line."
          },
          "api_paused_until": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the server takes API requests again, if paused by `api_reserve_percent`. `null` when not paused."
          }
        }
      },
      "Workspace": {
        "type": "object",
        "properties": {
          "plan": {
            "type": "string",
            "description": "`vip_std`, `vip_plus` or `none` (pay as you go)."
          },
          "service": {
            "type": "object",
            "properties": {
              "active": {
                "type": "boolean",
                "description": "Whether the service is active."
              },
              "until": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time",
                "description": "When it ends. For card subscriptions that renew, the end of the current period. `null` when it has no end."
              },
              "renews": {
                "type": "boolean",
                "description": "Whether a card subscription renews."
              }
            }
          },
          "balance": {
            "type": "object",
            "properties": {
              "usd": {
                "type": "number",
                "description": "API balance."
              },
              "enforced": {
                "type": "boolean",
                "description": "Whether requests are refused once the balance runs out."
              },
              "refused": {
                "type": "boolean",
                "description": "Whether requests are being refused right now because the balance ran out."
              }
            }
          }
        }
      },
      "UsageKey": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Key id."
          },
          "name": {
            "type": "string",
            "description": "Key name."
          },
          "prefix": {
            "type": "string",
            "description": "The first characters of the key."
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "paused",
              "locked",
              "expired",
              "disabled",
              "revoked"
            ],
            "description": "`active`, `paused`, `locked` (contact support), `expired`, `disabled` (its creator left) or `revoked`."
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the key was created."
          },
          "last_used_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Time of the last API request."
          },
          "expires_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the key expires; `null` = never."
          },
          "limits_usd": {
            "type": "object",
            "properties": {
              "total": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "Total."
              },
              "5h": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "Last 5 hours."
              },
              "1d": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "Last 24 hours."
              },
              "7d": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "Last 7 days."
              }
            },
            "description": "Spend limits: total, 5 hours, 1 day, 7 days. `null` = no limit."
          },
          "spend_usd": {
            "type": "object",
            "properties": {
              "total": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "Total."
              },
              "5h": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "Last 5 hours."
              },
              "1d": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "Last 24 hours."
              },
              "7d": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "Last 7 days."
              }
            },
            "description": "Spending for the same four: all time, last 5 hours, last 24 hours, last 7 days."
          },
          "exhausted": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "window": {
                "type": "string",
                "enum": [
                  "total",
                  "5h",
                  "1d",
                  "7d"
                ]
              },
              "limit_usd": {
                "type": [
                  "number",
                  "null"
                ]
              },
              "until": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time"
              }
            },
            "description": "Set when a spend limit is used up: `window`, `limit_usd`, and `until` (when it can be used again; `null` for the total limit)."
          },
          "usage": {
            "type": "object",
            "properties": {
              "requests": {
                "type": "integer",
                "description": "Requests."
              },
              "input_tokens": {
                "type": "integer",
                "description": "Input tokens."
              },
              "output_tokens": {
                "type": "integer",
                "description": "Output tokens."
              },
              "cache_read_tokens": {
                "type": "integer",
                "description": "Cache read tokens."
              },
              "cache_write_tokens": {
                "type": "integer",
                "description": "Cache write tokens."
              },
              "web_searches": {
                "type": "integer",
                "description": "Web searches."
              },
              "cost_usd": {
                "type": "number",
                "description": "Cost."
              },
              "last_request_at": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time",
                "description": "Time of the last request in the period."
              },
              "daily_tokens": {
                "type": "object",
                "additionalProperties": {
                  "type": "integer"
                },
                "description": "Tokens per UTC day, only days with requests."
              }
            },
            "description": "Totals for the period."
          },
          "allowed_models": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "string"
            },
            "description": "The key's model allowlist (id prefixes). `null` = all."
          },
          "max_effort": {
            "type": [
              "string",
              "null"
            ],
            "description": "The key's effort cap. `null` = no cap."
          },
          "workspace_allowed_models": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "string"
            },
            "description": "The workspace's model allowlist. `null` = all."
          },
          "workspace_max_effort": {
            "type": [
              "string",
              "null"
            ],
            "description": "The workspace's effort cap. `null` = no cap."
          },
          "recent_requests": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "at": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "format": "date-time",
                  "description": "Time."
                },
                "model": {
                  "type": "string",
                  "description": "Model."
                },
                "input_tokens": {
                  "type": "integer"
                },
                "output_tokens": {
                  "type": "integer"
                },
                "cache_read_tokens": {
                  "type": "integer"
                },
                "cache_write_tokens": {
                  "type": "integer"
                },
                "web_searches": {
                  "type": "integer"
                },
                "cost_usd": {
                  "type": "number"
                }
              }
            },
            "description": "The last 20 requests."
          }
        }
      },
      "WorkspaceKey": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Key id."
          },
          "name": {
            "type": "string",
            "description": "Key name."
          },
          "prefix": {
            "type": "string",
            "description": "The first characters of the key."
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "paused",
              "locked",
              "expired",
              "disabled",
              "revoked"
            ],
            "description": "`active`, `paused`, `locked` (contact support), `expired`, `disabled` (its creator left) or `revoked`."
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the key was created."
          },
          "last_used_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Time of the last API request."
          },
          "expires_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the key expires; `null` = never."
          },
          "limits_usd": {
            "type": "object",
            "properties": {
              "total": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "Total."
              },
              "5h": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "Last 5 hours."
              },
              "1d": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "Last 24 hours."
              },
              "7d": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "Last 7 days."
              }
            },
            "description": "Spend limits: total, 5 hours, 1 day, 7 days. `null` = no limit."
          },
          "spend_usd": {
            "type": "object",
            "properties": {
              "total": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "Total."
              },
              "5h": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "Last 5 hours."
              },
              "1d": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "Last 24 hours."
              },
              "7d": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "Last 7 days."
              }
            },
            "description": "Spending for the same four: all time, last 5 hours, last 24 hours, last 7 days."
          },
          "exhausted": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "window": {
                "type": "string",
                "enum": [
                  "total",
                  "5h",
                  "1d",
                  "7d"
                ]
              },
              "limit_usd": {
                "type": [
                  "number",
                  "null"
                ]
              },
              "until": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time"
              }
            },
            "description": "Set when a spend limit is used up: `window`, `limit_usd`, and `until` (when it can be used again; `null` for the total limit)."
          },
          "usage": {
            "type": "object",
            "properties": {
              "requests": {
                "type": "integer",
                "description": "Requests."
              },
              "input_tokens": {
                "type": "integer",
                "description": "Input tokens."
              },
              "output_tokens": {
                "type": "integer",
                "description": "Output tokens."
              },
              "cache_read_tokens": {
                "type": "integer",
                "description": "Cache read tokens."
              },
              "cache_write_tokens": {
                "type": "integer",
                "description": "Cache write tokens."
              },
              "web_searches": {
                "type": "integer",
                "description": "Web searches."
              },
              "cost_usd": {
                "type": "number",
                "description": "Cost."
              },
              "last_request_at": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time",
                "description": "Time of the last request in the period."
              },
              "daily_tokens": {
                "type": "object",
                "additionalProperties": {
                  "type": "integer"
                },
                "description": "Tokens per UTC day, only days with requests."
              }
            },
            "description": "Totals for the period."
          },
          "creator_email": {
            "type": [
              "string",
              "null"
            ],
            "description": "Email of the person who created the key."
          },
          "revoked_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When it was revoked. Revoked keys are listed only when they have usage in the period."
          },
          "servers": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Servers the key is limited to. Empty = every server in the workspace."
          }
        }
      },
      "Usage": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "const": "usage",
            "description": "Always `usage`."
          },
          "scope": {
            "type": "string",
            "enum": [
              "workspace",
              "key"
            ],
            "description": "`workspace` for keys created by an owner or admin, otherwise `key`."
          },
          "generated_at": {
            "type": "string",
            "format": "date-time",
            "description": "When this answer was made."
          },
          "period": {
            "type": "object",
            "properties": {
              "from": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time"
              },
              "to": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time"
              }
            },
            "description": "The `from` and `to` used for the totals in `usage`; `null` when not given."
          },
          "workspace": {
            "$ref": "#/components/schemas/Workspace",
            "description": "Plan, service period and balance."
          },
          "servers": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Server"
            },
            "description": "Servers and their subscription quotas."
          },
          "key": {
            "$ref": "#/components/schemas/UsageKey",
            "description": "The key that made this request."
          },
          "keys": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WorkspaceKey"
            },
            "description": "Every key in the workspace. Only for keys created by an owner or admin."
          }
        },
        "required": [
          "object",
          "scope",
          "generated_at",
          "workspace",
          "servers",
          "key"
        ]
      },
      "Key": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Key id."
          },
          "name": {
            "type": "string",
            "description": "Key name."
          },
          "prefix": {
            "type": "string",
            "description": "The first characters of the key, to recognise it."
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "paused",
              "locked",
              "expired",
              "disabled",
              "revoked"
            ],
            "description": "`active`, `paused`, `locked` (contact support), `expired`, `disabled` (its creator left) or `revoked`."
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "When the key was created."
          },
          "last_used_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Time of the last API request; `null` = never used."
          },
          "expires_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the key expires; `null` = never."
          },
          "revoked_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When it was revoked; `null` = not revoked."
          },
          "servers": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Servers the key can use. Empty = every server in the workspace."
          },
          "limits_usd": {
            "type": "object",
            "properties": {
              "total": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "Total."
              },
              "5h": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "Last 5 hours."
              },
              "1d": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "Last 24 hours."
              },
              "7d": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "Last 7 days."
              }
            },
            "description": "Spend limits in US dollars: `total`, `5h`, `1d`, `7d`. `null` = no limit."
          },
          "allowed_models": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "string"
            },
            "description": "Model id prefixes the key can use, e.g. `claude-opus`. `null` = all."
          },
          "allowed_ips": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "string"
            },
            "description": "IP addresses or CIDRs the key can be used from. `null` = anywhere."
          },
          "max_concurrency": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": 1,
            "maximum": 50,
            "description": "Requests running at once. `null` = the default (3)."
          },
          "max_effort": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "low",
              "medium",
              "high",
              "xhigh"
            ],
            "description": "Highest effort: `low`, `medium`, `high` or `xhigh`. `null` = no cap."
          },
          "can_manage_keys": {
            "type": "boolean",
            "description": "Whether the key can call these key management endpoints."
          },
          "created_by_key": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "Id of the manager key that created it through this API; `null` = created in the console."
          }
        }
      },
      "NewKey": {
        "allOf": [
          {
            "type": "object",
            "properties": {
              "key": {
                "type": "string",
                "description": "The full key. Shown only this once."
              }
            },
            "required": [
              "key"
            ]
          },
          {
            "$ref": "#/components/schemas/Key"
          }
        ]
      },
      "KeyList": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "const": "list",
            "description": "Always `list`."
          },
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Key"
            },
            "description": "The keys."
          }
        }
      },
      "CreateKey": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 64,
            "description": "1 to 64 characters. Required."
          },
          "servers": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Names of the servers the key can use. Empty or missing = every server in the workspace."
          },
          "limits_usd": {
            "type": "object",
            "properties": {
              "total": {
                "type": [
                  "number",
                  "null"
                ],
                "minimum": 0.01,
                "maximum": 1000000
              },
              "5h": {
                "type": [
                  "number",
                  "null"
                ],
                "minimum": 0.01,
                "maximum": 1000000
              },
              "1d": {
                "type": [
                  "number",
                  "null"
                ],
                "minimum": 0.01,
                "maximum": 1000000
              },
              "7d": {
                "type": [
                  "number",
                  "null"
                ],
                "minimum": 0.01,
                "maximum": 1000000
              }
            },
            "additionalProperties": false,
            "description": "Spend limits in US dollars, each 0.01 to 1000000. Missing = no limit."
          },
          "expires_at": {
            "type": [
              "string",
              "null"
            ],
            "description": "A date (`YYYY-MM-DD`; the key expires at 23:59 UTC that day) or an ISO time with a time zone. Missing = never."
          },
          "allowed_models": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "maxItems": 20,
            "description": "Model id prefixes the key can use, e.g. `claude-opus` (at most 20). Missing = all models."
          },
          "allowed_ips": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "maxItems": 32,
            "description": "IP addresses or CIDRs the key can be used from (at most 32). Missing = anywhere."
          },
          "max_concurrency": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": 1,
            "maximum": 50,
            "description": "Requests running at once, 1 to 50. Missing = the default (3)."
          },
          "max_effort": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "low",
              "medium",
              "high",
              "xhigh"
            ],
            "description": "Highest effort: `low`, `medium`, `high` or `xhigh`. Missing = no cap."
          }
        },
        "required": [
          "name"
        ],
        "additionalProperties": false
      }
    }
  }
}