Reference

HTTP API

Auth, requests, and responses under the unified `/v1/*` route space.

All actions are exposed through the same shape:

POST /v1/{service}/{action}
GET  /v1/{service}/{action}

The bearer credential decides the request identity:

  • no token: guest
  • user_token: user
  • administrator session token: admin

Each action declares which identities it allows. The default is ["user"]; [] means guest access is allowed.

City Routes (common user-side routes)

RouteMethodPurposePathway
/v1/ai/modelsGETModel catalog—
/v1/ai/streamPOSTDowncity Model Protocol stream transportCityModel
/v1/ai/image/createPOSTCreate image generation jobSDK
/v1/ai/image/resultPOSTPoll image generation jobSDK
/v1/ai/videoPOSTVideo generationSDK
/v1/ai/ttsPOSTText-to-speechSDK
/v1/ai/asrPOSTSpeech recognitionSDK
/v1/ai/chat/completionsPOSTOpenAI-compatible endpointOpenAI
/v1/accounts/login/startPOSTCreate a login attempt; returns input, redirect, or done—
/v1/accounts/login/continuePOSTSubmit an input login step—
/v1/accounts/login/resultGETRead the login result and user_token—
/v1/accounts/meGETRead the current user and its verified Bureau—
/v1/accounts/oauth/callbackGETThird-party OAuth callback entry—
/v1/servicesGETRegistered service list—
/v1/{service}/{action}POSTGeneric action call—

/v1/accounts/oauth/callback is the fixed return URL for GitHub, Google, and other third-party OAuth providers. Product clients usually do not call it directly.

Admin Routes (same route space, admin credential required)

RouteMethodPurpose
/v1/bureaus/listGETList Bureaus
/v1/bureaus/createPOSTCreate a Bureau with required server_url
/v1/bureaus/pausePOSTPause a Bureau
/v1/bureaus/activatePOSTActivate a Bureau
/v1/bureaus/archivePOSTArchive a Bureau
/v1/bureaus/server/updatePOSTUpdate the Bureau's single Server entrypoint
/v1/bureaus/currentGETResolve the current Bureau from a User Token
/v1/accounts/tokens/issuePOSTIssue user_token
/v1/env/listGETView runtime env
/v1/env/upsertPOSTWrite env variable
/v1/env/removePOSTDelete env variable
/v1/env/importPOSTBulk import .env

Auth Header

Authorization: Bearer <user_token>
Content-Type: application/json

GET /v1/ai/models

The same route returns different visibility by identity:

  • with user_token: only currently callable models
  • with an administrator session token: the full code-registered model list plus env_requirements
{ "items": [
  { "id": "deepseek-v4-flash", "name": "DeepSeek V4 Flash",
    "description": "...", "modalities": ["text","stream"],
    "tags": ["deepseek"],
    "price": ["Input: 1 credit / 1K tokens", "Output: 3 credits / 1K tokens"],
    "meta": {},
    "reasoning": {
      "efforts": [
        { "id": "low", "name": "Low" },
        { "id": "high", "name": "High" }
      ],
      "default_effort": "low"
    } }
]}
{ "items": [
  { "id": "deepseek-v4-flash", "name": "DeepSeek V4 Flash",
    "description": "", "modalities": ["text","stream","openai"],
    "tags": ["deepseek"],
    "price": ["Input: 1 credit / 1K tokens", "Output: 3 credits / 1K tokens"],
    "meta": {},
    "env_requirements": [
      { "key": "DEEPSEEK_API_KEY", "description": "deepseek API Key", "required": true }
    ] }
]}

Federation resolves both the user and Bureau identity from the bearer user_token. The request body does not participate in identity resolution.

GET /v1/services

{
  "items": [
    { "id": "ai", "name": "AI", "env": [] },
    { "id": "accounts", "name": "Accounts", "env": [] }
  ]
}

env exposes the runtime env requirements declared by the service so admin or debugging surfaces can render dependencies.

POST /v1/ai/stream

This versioned Downcity Model Protocol transport accepts { protocol_version: 1, model_id, call }, where call is a ModelCall containing messages, tools, reasoning, and generation options. SSE returns { protocol_version: 1, event: ModelStreamEvent }. Product code should use the CityModel returned by the catalog or call city.ai.stream({ model, call }). Both paths consume the same standard event stream.

When supplied, call.reasoning.effort must match the final model catalog's reasoning.efforts. AIService validates it again after fallback selects the execution model.

POST /v1/ai/chat/completions

OpenAI-compatible endpoint. Accepts standard { model, messages, stream } format.

Non-streaming returns OpenAI chat.completion JSON. Streaming returns OpenAI SSE.

Fully compatible with OpenAI SDK:

const openai = new OpenAI({
  baseURL: "http://127.0.0.1:43127/v1/ai",
  apiKey: "ub_xxx",
});