Skip to content

API Reference

This page is the public reference for the server HTTP API. The code is the single source of truth — every path, method and authentication middleware is declared in one place, server/internal/router/router.go; where this page and that file disagree, the code wins.

Except for the product HTML surfaces (the portal at / and /portal, the Admin Console at /admin/*) and file downloads (installers, archives, channel assets), every endpoint returns JSON; failures always use the error envelope {"error":{"code":"...","message":"..."}}.

NamespacePurposeAuthentication
/api/client/v2/*Employee surface: desktop client and third-party integrationsBearer token (a few endpoints are public; see the tables)
/api/server/admin/*Admin surface: Admin Console, operations and auditAdmin session cookie + CSRF + an RBAC permission point
/v1/*Model gateway: OpenAI-compatible, Anthropic-compatible, and the Files APIBearer token + per-user in-flight gate
/updates/client/*Installer downloads (root path, not an API: large files with Range semantics)Public
/healthz, /readyzHealth probesPublic

Both business namespaces enforce a 1 MiB request body limit (including the unauthenticated login endpoints). A few routes are explicitly exempt and apply their own limits inside the handler: archive uploads, WASM app uploads, a single chunk of the chunked upload, and the app request envelope.

The gateway is additionally mounted without the /v1 prefix as the vendor-native form (base_url set to the server address itself): /chat/completions, /completions, /responses, /messages, /embeddings, /models, /files*. Authentication, rate limiting, gates and metering are identical to the /v1 forms.

ItemSemantics
How to obtainPOST /api/client/v2/auth/login (local / LDAP username and password), or a browser authorization flow (OIDC / OpenID) which the client exchanges
How to sendHeader Authorization: Bearer <token>
Lifetime90 days; the server stores only the hash, and sweeps expired rows when issuing
RevocationLogout revokes the current token; password change / privilege downgrade / disable revoke all of that user’s tokens in the same transaction; an administrator can also revoke individual tokens in the Admin Console
Forced password changeAfter an administrator resets a password, every business endpoint except password change, /auth/me and logout returns 403 PASSWORD_CHANGE_REQUIRED
Invalid token vs server troubleA rejected credential → 401 AUTH_FAILED (the client clears its session and deletes the local token); an unavailable dependency (storage failure, connection pool exhaustion, statement timeout) → 500 INTERNAL (the client keeps the token and retries). The distinction is deliberate: reporting a PG hiccup as 401 would sign every online employee out
ItemSemantics
How to obtainPOST /api/server/admin/login; accounts with TOTP enabled get mfa_required and call POST /api/server/admin/login/mfa as the second step
How to sendAn HttpOnly cookie (SameSite=Lax; Secure depends on the deployment protocol)
Lifetime12-hour hard TTL + 60-minute idle sliding expiry; the server stores only a hash of the session secret
CSRFEvery non-GET/HEAD request must carry X-CSRF-Token; a failed check returns 403 CSRF_EXPIRED (a dedicated code, so the front end refreshes the token and retries once instead of showing it as “no permission”)
RBACEach admin endpoint declares one permission point (user:read, gateway:write, …). Role super_admin has everything, auditor has a read-only subset, user has no admin access at all. Enforcement is server-side; hiding menu entries is only cosmetics

A failure response is always:

{ "error": { "code": "AUTH_FAILED", "message": "invalid or expired token" } }
codeHTTPMeaning
AUTH_REQUIRED401Missing authentication token / not signed in
AUTH_FAILED401Invalid or expired token / wrong credentials
CSRF_EXPIRED403CSRF check failed (non-GET on the admin surface)
FORBIDDEN403Insufficient permission (admin RBAC or role restriction)
PASSWORD_CHANGE_REQUIRED403In the forced-password-change state; business endpoints are blocked
NOT_FOUND404Resource does not exist (including strict deny-by-default for unauthorized content, which does not leak existence)
VALIDATION400Parameter validation failed
RATE_LIMITED429Rate limited, or over the per-user in-flight cap
BALANCE_EXHAUSTED429The balance gate refused, for one of three reasons: quantized balance ≤ 0, balance at or below the learned floor from the last settlement that failed for lack of funds while the balance did not grow, or balance below this request’s minimum charge; it also fails closed when the balance settings cannot be read (administrators are exempt)
MODEL_NOT_PRICED429The model cannot be priced (both input and output price empty or ≤ 0, or the minimum charge quantizes to zero); an administrator can allow it with a policy switch
UPSTREAM502Upstream model error
INTERNAL500Internal error (including a temporarily unavailable dependency)

Unmatched routes under the /api/ and /v1/ prefixes (including 405) always return JSON NOT_FOUND; they never fall back to HTML or an empty response. API requests with a trailing slash return 404 rather than a redirect.

Meaning of the “Authentication” column: Public = no authentication; Bearer = employee token; Session = admin session + CSRF + the listed permission point.

MethodPathAuthenticationPurpose and key fields
POST/api/client/v2/auth/loginPublicPassword sign-in (local / LDAP). Request {username, password}; response {token, user, must_change_password}
POST/api/client/v2/auth/logoutBearerRevokes the current token; responds {ok:true}
GET/api/client/v2/auth/meBearerCurrent user: {user:{id, username, display_name, email, role, permissions, status, source, password_changeable, password_must_change, mfa_enabled, balance_money, balance_activated}}
POST/api/client/v2/auth/passwordBearerSelf-service password change (local accounts only). All tokens are revoked afterwards, so the client must sign in again
GET/api/client/v2/auth/methodsPublicSign-in method discovery: {methods:[{name, configured, browser, hidden}]}. configured reflects the runtime provider registry, not merely the presence of a configuration key
GET/api/client/v2/auth/oidc/login, /api/client/v2/auth/oidc/callbackPublicBrowser authorization sign-in; the provider is resolved per request from the current auth configuration, so saving takes effect immediately
GET/api/client/v2/auth/openid/login, /api/client/v2/auth/openid/callbackPublicSame, under the other namespace
MethodPathAuthenticationPurpose and key fields
GET/api/client/v2/config/bootstrapBearerOne-shot post-login payload: {default_model, models[], skills[], web{}, connectors[], server_version}. models[] contains only usable models under enabled providers and carries input_modalities; connectors[] are connector definitions ({id, name, description, auth_mode, definition}) with no credential values
GET/api/client/v2/auth/usageBearerEmployee usage summary: balance_money, balance_activated, balance_enabled, balance_monthly, balance_mode, plus today_* / yesterday_* / monthly_* / total_* tokens and cost

There are no session endpoints on the server: sessions, context and approvals all live locally in the client (see System Architecture).

Channel content and client delivery (public)

Section titled “Channel content and client delivery (public)”

The sign-in page needs branding and installers before anyone is signed in, so this group needs no authentication.

MethodPathAuthenticationPurpose and key fields
GET/api/client/v2/channelPublicChannel content: channel id, title, sign-in/client names and taglines, accent colour
GET / HEAD/api/client/v2/channel/logoPublicChannel logo (light variant); 404 with a JSON envelope when unset
GET / HEAD/api/client/v2/channel/logo-darkPublicChannel logo (dark variant); 404 when unset
GET / HEAD/api/client/v2/channel/faviconPublicChannel favicon; 404 when unset
GET/api/client/v2/updates/manifestPublicClient version manifest: {schema:1, channel_id, server:{version}, client:{version, assets}}; assets are keyed mac-universal / win-x64 / linux-x64, each {url, sha256, size}. When no absolute https address can be produced it returns a client_unavailable reason. Responds Cache-Control: no-store
GET / HEAD/updates/client/<filename>PublicInstaller download: extension allowlist, only regular files inside the asset directory, explicit Content-Type + Content-Disposition: attachment + nosniff, Range resume, long cache. This route alone relaxes the write deadline so slow links can finish
MethodPathAuthenticationPurpose and key fields
GET/api/client/v2/marketplace/skillsBearerMarketplace skill catalogue (visible per grant)
GET/api/client/v2/marketplace/skills/:nameBearerMarketplace skill detail
GET/api/client/v2/marketplace/skills/:name/archiveBearerDownload a marketplace skill package; response headers X-Skill-Checksum / X-Skill-Version let the client verify integrity
GET/api/client/v2/skills/builtinBearerBuilt-in platform skills (shipped with the server image; the client installs them on demand)
GET/api/client/v2/skills/builtin/:name/archiveBearerDownload a built-in skill package
GET/api/client/v2/shared-skillsBearerOrganization shared skills: approved and granted content, plus everything you uploaded with its status
POST/api/client/v2/shared-skillsBearerUpload a shared skill (base64 archive with a top-level SKILL.md); it enters review
GET/api/client/v2/shared-skills/:name/:version/archiveBearerDownload a shared skill package
GET/api/client/v2/agent-presetsBearerOrganization shared agents (same visibility rules as shared skills)
POST/api/client/v2/agent-presetsBearerUpload a shared agent (with a top-level agent.cordis.yml)
GET/api/client/v2/agent-presets/:name/archive, /api/client/v2/agent-presets/:name/:version/archiveBearerDownload a shared agent package (latest / specific version)
GET/api/client/v2/capabilitiesBearerUnified Capability Hub catalogue; query parameters source=own|market|org, type=, q=. Marketplace and organization rows merge into one authoritative row (marketplace wins)
POST/api/client/v2/telemetry/skill-callBearerReport a skill invocation (counter, rate limit configurable)
POST/api/client/v2/telemetry/error-reportingBearerThe client reports the outcome of its own error-reporting setup; unknown states are accepted silently and not stored

Shared content uses a double gate: approved and granted (grants target a user or a department). Unauthorized content is always 404 and does not leak existence; administrators always see everything.

The employee surface receives connector definitions through bootstrap; credentials are collected and encrypted locally by the client per user scope, and the server neither receives nor delivers credential values. Creating, editing and enabling connectors all happen on the admin surface.

MethodPathAuthenticationPurpose and key fields
GET/api/client/v2/config/bootstrapBearerThe single source of the connector catalogue (see connectors[] above)

Apps open only inside the desktop client: the client wraps requests to <app origin scheme>://<app_id>/… in an envelope and sends it to the single entry point.

MethodPathAuthenticationPurpose and key fields
GET/api/client/v2/apps/wasm/catalogBearerApp catalogue: filters only “not deleted / not frozen / has an effective version” and delivers access and enabled (unlisted apps stay visible but are marked)
POST/api/client/v2/apps/wasm/validateBearerValidate a .wasm artifact (no publish, no version reservation, no upload quota consumed) and return a structured verdict
POST/api/client/v2/apps/wasm/:app_id/releasesBearerPublish a new version (single-shot path); it goes live or becomes pending according to the admin review switch
POST/api/client/v2/apps/wasm/uploadsBearerChunked upload: open a session and return an upload_id
PUT/api/client/v2/apps/wasm/uploads/:upload_id/chunks/:indexBearerUpload chunk index (application/octet-stream, per-chunk cap)
GET/api/client/v2/apps/wasm/uploads/:upload_idBearerResume query: which chunks have been received
POST/api/client/v2/apps/wasm/uploads/:upload_id/completeBearerAssemble and run the publish path; the client may declare its budget for this hop in a request header, and the platform may only shrink it, never enlarge it
DELETE/api/client/v2/apps/wasm/uploads/:upload_idBearerAbandon the upload and reclaim disk
POST/api/client/v2/apps/wasm/:app_id/requestBearerThe single entry point for app execution: the app request envelope is decoded and executed here, with identity injected by the client
POST/api/client/v2/apps/wasm/proofBearerIssue a proof of possession binding “which employee + which token + which app”
POST/api/client/v2/apps/wasm/:app_id/openBearerOpen validation and counting; response header X-PicoAide-App-Version is the sole source of the client’s content cache key
GET/api/client/v2/apps/wasm/:app_id/availabilityBearerIdentifier availability pre-check (read-only: no compile, no version reservation)
GET/api/client/v2/apps/wasm/:app_id/releasesBearerThe publisher’s own version history and review verdicts (including rejection reasons). Non-publishers always get 404, byte-identical to “app does not exist”
POST/api/client/v2/apps/wasm/:app_id/publish, /api/client/v2/apps/wasm/:app_id/unpublishBearerList / unlist (by the publisher)
POST/api/client/v2/apps/wasm/:app_id/freezeBearerFreeze
GET/api/client/v2/apps/wasm/:app_id/diagnosticsBearerRuntime diagnostics (publisher only)
GET/api/client/v2/apps/wasm/:app_id/schemaBearerThe app database’s tables, columns, row counts and size (no row values)
GET/api/client/v2/apps/wasm/:app_id/rowsBearerRead-only row browsing of the app database (publisher only; masked by default, and fetching raw values writes a different audit action)
GET/api/client/v2/apps/wasm/:app_id/exportBearerExport the app
DELETE/api/client/v2/apps/wasm/:app_idBearerDelete the app

Admin surface: authentication and sessions

Section titled “Admin surface: authentication and sessions”
MethodPathAuthenticationPurpose and key fields
POST/api/server/admin/loginPublicAdministrator sign-in. Response {csrf_token, user, must_change_password}; with TOTP enabled it returns {mfa_required:true, mfa_ticket}
POST/api/server/admin/login/mfaPublicSecond factor step: {mfa_ticket, code}
GET/api/server/admin/auth/methodsPublicSign-in method discovery; uses the same decision as the employee surface, so one server never tells two stories
GET/api/server/admin/meSessionCurrent administrator plus the current session’s CSRF token (so a page refresh can continue without signing in again)
POST/api/server/admin/logoutSessionSign out
POST/api/server/admin/me/passwordSessionChange your own password (old password + TOTP code; success revokes all sessions)
GET/api/server/admin/me/mfaSessionYour own MFA state
POST/api/server/admin/me/mfa/enable, /me/mfa/verify, /me/mfa/disableSessionEnable / verify / disable TOTP; disabling requires both the master password and a valid code
MethodPathAuthenticationPurpose and key fields
GET/api/server/admin/usersSession + user:readUser list (role, status, balance, password-change and MFA markers)
POST/api/server/admin/usersSession + user:writeCreate a user
PUT/api/server/admin/users/:idSession + user:writeUpdate a user (role, status, display name, email, password reset). Quota fields in the body were retired and are ignored
DELETE/api/server/admin/users/:idSession + user:writeDelete a user
PUT/api/server/admin/users/:id/mfaSession + user:writeReset someone else’s MFA (not your own; revokes all their sessions)
GET/api/server/admin/users/:id/groupsSession + user:readThe user’s departments
PUT/api/server/admin/users/:id/departmentSession + dept:writeSet department membership (group_ids array; multiple departments supported)
GET/api/server/admin/departmentsSession + dept:readDepartment tree
POST/api/server/admin/departmentsSession + dept:writeCreate a department
PUT/api/server/admin/departments/:idSession + dept:writeUpdate a department
DELETE/api/server/admin/departments/:idSession + dept:writeDelete a department
GET/api/server/admin/users/:id/tokensSession + user:readThat user’s sign-in tokens
POST/api/server/admin/tokens/:id/revokeSession + user:writeRevoke a specific token
MethodPathAuthenticationPurpose and key fields
POST/api/server/admin/users/:id/balanceSession + user:writeAdjust an employee’s balance (add / subtract / set); audited
GET/api/server/admin/users/:id/balance/ledgerSession + user:readThat user’s balance ledger
GET/api/server/admin/balanceSession + user:readBalance gate and monthly grant configuration
PUT/api/server/admin/balanceSession + user:writeUpdate balance configuration
POST/api/server/admin/balance/grantSession + user:writeTrigger a grant manually (idempotent across instances and restarts)
GET/api/server/admin/usageSession + usage:readUsage summary
GET/api/server/admin/usage/overviewSession + usage:readUsage centre overview (daily trend, departments, members, models)
GET/api/server/admin/usage/requestsSession + usage:readRequest-level detail (paginated, bounded window)
GET/api/server/admin/report-subscriptionsSession + report:readUsage report subscriptions. The list contains webhook credentials, so it uses a dedicated permission point and read-only auditors do not get it by default
POST/api/server/admin/report-subscriptionsSession + report:writeCreate a subscription
PUT / DELETE/api/server/admin/report-subscriptions/:idSession + report:writeUpdate / delete a subscription
POST/api/server/admin/report-subscriptions/:id/testSession + report:writeSend a test push

Admin surface: authentication configuration

Section titled “Admin surface: authentication configuration”
MethodPathAuthenticationPurpose and key fields
GET/api/server/admin/authSession + auth:readAuthentication configuration (sensitive fields masked)
PUT/api/server/admin/authSession + auth:writeSave authentication configuration (including client secret). Takes effect immediately, no restart
POST/api/server/admin/auth/testSession + auth:writeConnectivity test (LDAP directory statistics / OIDC discovery document)
MethodPathAuthenticationPurpose and key fields
GET/api/server/admin/providersSession + gateway:readUpstream provider list
POST/api/server/admin/providersSession + gateway:writeCreate a provider (API key stored encrypted)
PUT / DELETE/api/server/admin/providers/:idSession + gateway:writeUpdate / delete a provider
GET/api/server/admin/providers/:id/balanceSession + gateway:readUpstream account balance (when the vendor supports it)
POST/api/server/admin/providers/:id/sync, /api/server/admin/providers/sync-allSession + gateway:writeSync the model catalogue from upstream (disable instead of delete, so pricing survives)
GET/api/server/admin/modelsSession + gateway:readModel list (pricing, cache price, off-peak discount, input modalities)
POST/api/server/admin/modelsSession + gateway:writeCreate a model
PUT / DELETE/api/server/admin/models/:idSession + gateway:writeUpdate / delete a model
GET/api/server/admin/gatewaySession + gateway:readGateway configuration (default model, rate limits, peak windows, usage policy, unpriced-model policy)
PUT/api/server/admin/gatewaySession + gateway:writeUpdate gateway configuration; price and window changes only affect costs recorded afterwards
GET/api/server/admin/gateway/filesSession + gateway:readFiles API ownership ledger: usage per employee, search and sort
GET/api/server/admin/gateway/files/summarySession + gateway:readLedger summary
DELETE/api/server/admin/gateway/files/:file_idSession + gateway:writeDelete a single upstream file
POST/api/server/admin/gateway/files/purgeSession + gateway:writeBulk cleanup
POST/api/server/admin/gateway/error-reporting/testSession + gateway:writeThe server sends one test event (to verify the error-tracking path)
GET/api/server/admin/gateway/error-reporting/clientsSession + gateway:readAggregated client reporting state (N enabled / M failed)
GET/api/server/admin/channelsSession + gateway:readChannel list (read-only diagnostics; channel content is injected at build time and cannot be edited online)
GET/api/server/admin/concurrencySession + gateway:readPer-model concurrency: current, historical peak, target

Admin surface: Capability Hub and approvals

Section titled “Admin surface: Capability Hub and approvals”
MethodPathAuthenticationPurpose and key fields
GET/api/server/admin/capabilities/approvalsSession + capability:readUnified Capability Hub approval queue (read-only; actions go through each domain’s own endpoints)
GET/api/server/admin/skillsSession + market:readMarketplace skill list
POST/api/server/admin/skillsSession + market:writeCreate a marketplace skill
POST/api/server/admin/skills/:name/archiveSession + market:writeUpload a skill archive (new version)
GET/api/server/admin/skills/:name/archiveSession + market:readDownload a skill archive
PUT / DELETE/api/server/admin/skills/:nameSession + market:writeUpdate / delete a marketplace skill
POST/api/server/admin/skills/:name/enableSession + market:writeList / unlist
POST/api/server/admin/skills/:name/normalizeSession + market:writeNormalize a skill archive
GET/api/server/admin/skills/:name/preview, /skills/:name/fileSession + market:readPreview / read one file’s content
GET/api/server/admin/skills/builtinSession + capability:readBuilt-in platform skills (read-only diagnostics; the path sits beside /skills/:name and the static segment wins)
GET / PUT/api/server/admin/skills/:name/grantsSession + market:read / market:writeList / replace all grants
PUT / DELETE/api/server/admin/skills/:name/grantSession + market:writeAdd / remove one grant
GET/api/server/admin/agentsSession + market:readMarketplace agent list
POST/api/server/admin/agentsSession + market:writeCreate a marketplace agent
POST/api/server/admin/agents/:name/archiveSession + market:writeUpload an agent archive
GET/api/server/admin/agents/:name/archiveSession + market:readDownload an agent archive
PUT / DELETE/api/server/admin/agents/:nameSession + market:writeUpdate / delete
POST/api/server/admin/agents/:name/enableSession + market:writeList / unlist
GET/api/server/admin/agents/:name/preview, /agents/:name/fileSession + market:readPreview / read file content
GET / PUT/api/server/admin/agents/:name/grantsSession + market:read / market:writeList / replace all grants
PUT / DELETE/api/server/admin/agents/:name/grantSession + market:writeAdd / remove one grant
GET/api/server/admin/shared-skillsSession + capability:readAll organization shared skills (including pending)
GET/api/server/admin/shared-skills/:name/:version/archive, /preview, /fileSession + capability:readDownload / preview / read file
POST/api/server/admin/shared-skills/:name/:version/approve, /rejectSession + capability:writeApprove / reject (rejection requires a reason)
DELETE/api/server/admin/shared-skills/:name/:versionSession + capability:writeDelete one version
PUT/api/server/admin/shared-skills/:name/:version/qualitySession + capability:writeSet the quality badge (official / featured)
PUT/api/server/admin/shared-skills/:name/enabledSession + capability:writeList / unlist an organization shared skill
GET / PUT/api/server/admin/shared-skills/:name/grantsSession + capability:read / capability:writeList / replace all grants
PUT / DELETE/api/server/admin/shared-skills/:name/grantSession + capability:writeAdd / remove one grant
GET/api/server/admin/agent-presetsSession + capability:readAll organization shared agents
GET/api/server/admin/agent-presets/:name/archive, /:name/preview, /:name/:version/archive, /:name/:version/preview, /:name/:version/fileSession + capability:readDownload / preview / read file
POST/api/server/admin/agent-presets/:name/approve, /reject, /:name/:version/approve, /:name/:version/rejectSession + capability:writeApprove / reject
DELETE/api/server/admin/agent-presets/:name, /:name/:versionSession + capability:writeDelete an agent / one version
PUT/api/server/admin/agent-presets/:name/:version/qualitySession + capability:writeSet the quality badge
PUT/api/server/admin/agent-presets/:name/enabledSession + capability:writeList / unlist an organization shared agent
GET / PUT/api/server/admin/agent-presets/:name/grantsSession + capability:read / capability:writeList / replace all grants
PUT / DELETE/api/server/admin/agent-presets/:name/grantSession + capability:writeAdd / remove one grant
GET/api/server/admin/capability-locksSession + capability:readCapability lock list (names only administrators may publish; names that do not exist yet can be pre-locked)
PUT / DELETE/api/server/admin/capability-locks/:kind/:nameSession + capability:writeAdd / remove a lock
PUT/api/server/admin/apps/:kind/:app_id/ownerSession + capability:writeTransfer capability ownership. Ownership is app-level and version-independent, hence the apps base path

Admin surface: connectors, portal and server information

Section titled “Admin surface: connectors, portal and server information”
MethodPathAuthenticationPurpose and key fields
GET/api/server/admin/connectorsSession + connector:readConnector catalogue (definition, auth mode, enabled state)
GET/api/server/admin/connectors/:idSession + connector:readA single connector
POST/api/server/admin/connectorsSession + connector:writeCreate. The server normalizes input into a canonical definition on the write path (including credential-field shape validation)
PUT / DELETE/api/server/admin/connectors/:idSession + connector:writeUpdate / delete
PUT/api/server/admin/connectors/:id/enabledSession + connector:writeDelivery switch
GET/api/server/admin/portalSession + portal:readPortal configuration (public or not, download-URL overrides, note text). Brand names and copy are not here — they come from channel content
PUT/api/server/admin/portalSession + portal:writeUpdate portal configuration
GET/api/server/admin/server-infoSession + server-info:readServer information: version and update hints, database and migrations, model concurrency, error-monitoring configuration
MethodPathAuthenticationPurpose and key fields
GET/api/server/admin/auditSession + audit:readAudit log (hash chain, tamper-evident)
GET/api/server/admin/audit/settingsSession + audit:readAudit retention policy
PUT/api/server/admin/audit/settingsSession + audit:retention:writeChange the retention policy (super admin only)

Mounted under /api/server/admin/wasm-apps. Read endpoints use capability:read, write endpoints use capability:write.

MethodPathAuthenticationPurpose and key fields
GET/api/server/admin/wasm-appsSession + capability:readApp list
POST/api/server/admin/wasm-apps/:app_id/publish, /unpublishSession + capability:writeList / unlist as an administrator (symmetric with the publisher’s own listing)
POST/api/server/admin/wasm-apps/:app_id/freezeSession + capability:writeFreeze
PUT/api/server/admin/wasm-apps/:app_id/ownerSession + capability:writeTransfer ownership
GET/api/server/admin/wasm-apps/:app_id/releasesSession + capability:readThat app’s versions and review queue
POST/api/server/admin/wasm-apps/:app_id/releases/:version/approve, /rejectSession + capability:writeApprove or reject a version
PUT/api/server/admin/wasm-apps/reviewSession + capability:writeMaster switch for publish review
GET / PUT/api/server/admin/wasm-apps/limitsSession + capability:read / capability:writePlatform limits (concurrency, instance memory, time budgets). Most take effect immediately; instance memory needs a restart
GET/api/server/admin/wasm-apps/runtimeSession + capability:readPlatform-wide runtime watermarks: compile queue and cache, execution slots, dropped call-event counters, free disk
GET/api/server/admin/wasm-apps/:app_id/diagnosticsSession + capability:readApp diagnostics (an administrator troubleshooting exit)
GET/api/server/admin/wasm-apps/:app_id/schema, /rowsSession + capability:readApp database schema and row browsing (same implementation as the employee surface; the differences are authentication and whose account lands in the audit log)
GET/api/server/admin/wasm-apps/:app_id/opensSession + capability:readApp open counts (long-lived daily rollups plus detail)
GET/api/server/admin/wasm-apps/opens/summarySession + capability:readOperations dashboard summary (a static segment, more specific than /:app_id/opens, so it matches first)
GET/api/server/admin/wasm-apps/:app_id/ai-usageSession + capability:readPer-app AI usage
MethodPathAuthenticationPurpose and key fields
POST/v1/chat/completionsBearer + in-flight gateOpenAI-compatible chat (stream optional)
POST/v1/embeddingsBearer + in-flight gateEmbeddings
POST/v1/completionsBearer + in-flight gateCompletions
POST/v1/responsesBearer + in-flight gateCompatible form (usage parsing accepts both field namings)
POST/v1/messagesBearer + in-flight gateAnthropic Messages compatible
GET/v1/modelsBearer + in-flight gateAvailable models (only enabled providers, catalogue entries not missing, with input modalities)
POST/v1/filesBearer + in-flight gateUpload a file, returns a file_id
GET/v1/filesBearer + in-flight gateList files
GET/v1/files/:file_idBearer + in-flight gateRetrieve file metadata
DELETE/v1/files/:file_idBearer + in-flight gateDelete a file

Authorization: Bearer is the only authentication method. The native variants without the /v1 prefix (/chat/completions, /completions, /responses, /messages, /embeddings, /models, /files*) are mounted as well and behave identically.

MethodPathAuthenticationPurpose
GET/, /portalPublicPortal home: channel branding plus download entries for the three platforms (plain HTML, no scripts)
GET/admin/Public (the page itself then requires sign-in)Admin Console SPA (build output embedded in the server binary)
GET/healthzPublicHealth probe: JSON with database connectivity; 503 when the database is unavailable
GET/readyzPublicReadiness probe: beyond health it reports free disk, execution and compile queue watermarks, and the retention-cleanup facts. Because the endpoint is unauthenticated it returns short phrases only; detail goes to the server log

Stable contract (safe to depend on):

  • The namespace split: /api/client/v2/* is the employee surface, /api/server/admin/* is the admin surface, /v1/* is the model gateway;
  • Authentication mechanics and token semantics (where Bearer goes, the admin CSRF header name X-CSRF-Token);
  • The error envelope {"error":{"code","message"}} and the code set in the table above;
  • The update manifest’s schema / channel_id / assets[].url|sha256|size shape — it is the upgrade contract between the client and the update server;
  • The OpenAI / Anthropic compatible forms under /v1/*.

May change:

  • Request and response fields of admin endpoints. The Admin Console ships in the same version as the server and evolves with it; third parties integrating directly with the admin surface must align by version;
  • Added fields are backward compatible (clients ignore unknown fields); changing the meaning of an existing field is a behaviour change and is recorded in the release notes;
  • bootstrap.server_version is a diagnostic/provenance field with no client consumer today — it is not the source of any version-mismatch prompt (version checks use the update manifest).

Retired — do not use:

  • The old namespaces /api/* (historical admin and employee routes), /v2/api/* and /v2/v1/*. Today’s /v1/* is the model gateway, not the old admin surface;
  • The employee browser session and one-time ticket exchange: /login, /logout and /app-ticket were removed wholesale together with “apps open only inside the desktop client”;
  • The old branding and portal endpoints /api/client/v2/brand and /api/client/v2/portal: branding and portal content now come from /api/client/v2/channel and the portal HTML;
  • Employee-side token quota, money quota and department budget request fields: the balance is the single billing gate, and those fields in a request body are ignored.

Known not implemented (differences from the vendor’s model API documentation; integrating per that documentation will fail):

  • The /beta prefix (prefix continuation and FIM) is not implemented;
  • Anthropic-compatible /anthropic/v1/* and x-api-key authentication are not implemented (/v1/messages uses Bearer);
  • GET /user/balance (key holder’s view) is not implemented; only the admin providers/:id/balance exists;
  • A vendor 429 means “account-level concurrency cap”, while this product’s 429 means insufficient balance or a local rate limit — different semantics.

API requests with a trailing slash return 404 JSON rather than a 307 redirect: predictable semantics, consistent with how the body limit is applied.