Skip to main content
Mirobody’s hosted API is OpenAI-compatible. Point any OpenAI SDK at the base URL below, pass an mb_live_* key, and call /v1/chat/completions — the agent answers from each end-user’s real, structured health data, with traceable citations. The same engine also runs self-hosted — build the open-source C++ engine with ./build.sh and run it yourself; the hosted API adds managed storage, keys, and billing on top. You create keys, watch usage, and try an interactive Playground in the developer console. These docs are the API reference.

Base URL

Mirobody is global-first. The live integration environment today is the global test cluster — point your SDK here:
https://test-mirobody-api.thetahealth.ai/v1
Its data is non-production and may be reset at any time, so never put real end-user data there. The global production API (https://mirobody-api.thetahealth.ai/v1) and the China production API (https://mirobody-api.thetahealth.cn/v1) are still provisioning — though the China test environment (consumer app + developer console) is now live. See Regions for the full host matrix and live status. Authenticate every call with an mb_live_* key — see Authentication.

Authentication

SurfaceSchemeHow to get it
/v1/* (the API)Authorization: Bearer mb_live_*Create a key in the consoleAPI Keys. The secret is shown once.
/api/console/* (console)Session JWT (login)Email-code or WeChat login in the console.
/v1 keys are not JWTs — they’re long-lived API keys scoped to your account. Never ship them in client-side code.

OpenAI compatibility

Standard OpenAI fields work as-is; Mirobody extensions ride along in extra_body (Python SDK) or as plain top-level JSON (curl/fetch).
Fields
Standardmodel, messages, stream, user
Mirobody extensionsretention, session_id, health_context, mcp_servers, include_tool_steps
Responsechoices[0].message.content (+ reasoning_content, tool_steps), usage, plus top-level health_records / citations
Sampling parameters are accepted for compatibility, but the agent runs its own generation. max_tokens is accepted but not enforced — the agent controls output length. temperature, top_p, stop, and seed are accepted but ignored. n other than 1 is also not enforced — the response still returns a single choice.

Multi-tenancy: the user field

Every request carries a user string — the tenant-isolation key. The backend maps (your account, user) to an internal Subject; each user you pass is fully isolated from the others. Pass each end-user’s stable id as user and their data never crosses over. Omit it and the call falls back to your account’s default Subject. Subjects are not consumer accounts — they’re invisible to the Mirobody app and to other developers.

Data retention

Anything you supply (structured records, uploaded files, inline health_context) carries a retention that decides how long it’s kept:
retentionMeaningLifetime
permanentKept until explicitly deleted (default for inline health_context)Permanent
sessionBound to session_id, dropped when the session ends≤ 24h, or DELETE /v1/sessions/{id}
1dAuto-deleted within a day≤ 24h
6hAuto-deleted 6 hours after write≤ 6h
2hAuto-deleted 2 hours after write≤ 2h
1hAuto-deleted 1 hour after write≤ 1h
noneUsed for this request only, never persistedDeleted in finally
Accepted values are permanent (a.k.a. persistent) | 1h | 2h | 6h | 1d | session | none. Any time-bounded grain is hard-capped at ≤ 24h. On POST /v1/data the retention field is required — there is no default; omitting it returns 400 (code: invalid_retention). For inline health_context on POST /v1/chat/completions, it defaults to permanent. none is meant for inline health_context (use-and-forget). On POST /v1/data it is rejected with HTTP 400 (writing to the store but asking not to store is contradictory) — to use-and-forget structured data, attach it as health_context with retention=none on POST /v1/chat/completions instead. The agent only ever reads the Subject’s currently-unexpired data.

Citations

Answers are explainable and checkable — not “sounds plausible,” but “this conclusion came from that record of yours.” Today the traceability is carried by health_records (a top-level array of {tool, data} pairs — the actual tool outputs the answer relied on). The citations array is reserved for record:N-style refs and is currently returned empty, so read health_records.

Error format

Errors use the OpenAI-style envelope:
{
  "error": {
    "message": "`retention` is required (days int or 'persistent').",
    "type": "invalid_request_error",
    "code": "invalid_retention",
    "param": "retention"
  }
}
type is consistently invalid_request_error; code and param identify the specific problem. Observed (status, code) pairs:
HTTPcodeWhen
400invalid_retention (field-specific)Malformed request / missing required field — param names the field
401nullMissing or malformed Authorization header
401invalid_api_keyBad or revoked mb_live_* key
404Unknown resource (e.g. file_key / session_id)
429Rate limit — see Rate Limits
500internal_errorUnexpected server-side failure
502Upstream agent error — transient; retry with backoff
In streaming, an upstream failure arrives as an SSE error frame before the stream ends.

Endpoints at a glance

MethodPathPurpose
GET/v1/modelsList capability tiers (mirobody-flash / mirobody-expert)
POST/v1/chat/completionsOpenAI-compatible health chat (stream, health_context, mcp_servers)
POST · GET/v1/dataWrite / read structured records
POST · GET/v1/filesUpload & parse files (OCR / Excel), list, fetch parsed text
DELETE/v1/sessions/{id}End a session (see caveats — session-record purge is not yet effective)
GET·POST·DELETE/api/console/keysManage API keys (JWT)
GET/api/console/usageUsage: requests / tokens / cost (JWT)