Skip to main content
Before copying a curl example, choose your Cloud region. For authenticated calls, it must be the same region as your key. The examples below use MIROBODY_API_BASE:
For SDK examples with a literal Global URL, use the matching China URL when your account is in China. See Regions. Upload a health document to the Subject’s store. Mirobody saves the original first, then in the background extracts its readable text — OCR for PDFs and images, a straight conversion for spreadsheets and text files — and runs the same standardization pipeline as POST /v1/standardize over it, so an uploaded lab report also lands as standardized records. The agent reads both when it answers.
Uploads are capped at 100 MB per file — larger requests return 413. For big exports or realtime streams, use the WebSocket upload path.

Upload a file

Response:
The file’s identifier is id (a slash-containing key) — use it as {file_key} in the fetch and delete calls below. created_at is epoch seconds.
status: "processed" confirms the original was accepted and stored — its text may still be processing. A GET /v1/files/{file_key} immediately after upload can return an empty extracted_text; retry after a short delay.
An upload makes the document’s text readable by the agent, and Mirobody also pulls the report’s readings out of it — standardized exactly like a POST /v1/data write — and stores them as records. Query them from GET /v1/data without re-entering anything; re-uploading the same file creates no duplicates. Prefer POST /v1/standardize when you’d rather run that extraction yourself and check the readings first. Already have structured records? Send them to POST /v1/data.

List files

data holds the files; subject echoes the Subject. Each item exposes both id and file_key (identical values). created_at is epoch seconds, matching the upload response.

Fetch parsed text

Returns the extracted text for one file — the same content the agent reads:
extracted_text can be empty while the file’s text is still being processed. abstract may also be empty; it isn’t generated for every file type.

WebSocket upload

For large exports or realtime capture, wss://…/v1/files/stream uploads over one socket with chunking and progress. Auth rides the query string (browsers can’t set WebSocket headers):
Frame sequence (all JSON text frames):
  1. Server → you: {"type": "connection_established"} — send nothing before this.
  2. You → server: {"type": "upload_start", "messageId": "<batch-id>", "files": [{"filename", "contentType", "size"}]} — one messageId for the whole batch.
  3. You → server, per 256 KB chunk: {"type": "upload_chunk", "messageId", "filename", "chunk": "<base64>", "chunkIndex", "totalChunks"}.
  4. You → server: {"type": "upload_end", "messageId"} → server replies upload_end_response when every original file has been stored. Its text may still be processing.
Same 100 MB per-file cap, same Subject isolation, and the stored files are identical to a POST /v1/files upload — list them with GET /v1/files.

Delete a file

Removes the file from the API surface immediately (404 if it isn’t the Subject’s file or is already deleted):
Deleting a file removes the file but not the records auto-extracted from it. To remove those, delete them from the data plane with DELETE /v1/data (by indicator or id), or erase the whole Subject with DELETE /v1/subjects/{user}. (Session-scoped uploads are erased together with their session-scoped records by DELETE /v1/sessions/{id}.)
Time-bounded uploads are also removed automatically at retention expiry — an expired file disappears from every GET /v1/files* read immediately and is then permanently deleted. To erase everything about a Subject at once, use DELETE /v1/subjects/{user} — see Compliance.

See also