Sources and ingestion

Every input is kept as a source package first, then classified, split into chunks, indexed, and mined for claims. The original is never rewritten, so every fact can point back to the source it came from.

Ways in

InputRoute or command
TextPOST /api/ingest, optimal capture, mix optimal.ingest
A filePOST /api/assets with the bytes as base64
A folder of filesmix optimal.ingest_workspace
A finished chatPOST /api/sessions/commit, optimal session commit
A durable memoryPOST /api/memory, POST /api/memory/remember, optimal remember
A Notion exportPOST /api/import/notion, mix optimal.import_notion
Many records at oncePOST /api/batch/import/signals, POST /api/batch/import/memories
An appConnectors, below
Another Engine’s workspaceA workspace bundle; see Operations

Text

curl -s -X POST http://127.0.0.1:4200/api/ingest 
  -H "Authorization: Bearer $OPTIMAL_ENGINE_API_KEY" 
  -H "Content-Type: application/json" 
  -d '{
    "workspace": "default:notes",
    "title": "Pricing decision",
    "text": "Decided: annual plans get two months free from March.",
    "node": "pricing",
    "extract_claims": true
  }'
FieldRequiredMeaning
textyesThe content
workspacenoWorkspace id; default when left out
titlenoTitle shown in results
genrenoOverride the genre the Engine would pick
nodenoNode slug the source belongs to
extract_claimsnotrue by default

The response is {"ok": true, "signal_id", "genre", "type", "entities", "source_package_id"}. A missing text answers 400; a source the pipeline cannot take answers 422 with ok: false and an error.

Files

POST /api/assets takes a file as content_base64 with its filename. The Engine stores the bytes, hashed, under the workspace’s assets/ folder, or in S3-compatible storage when OPTIMAL_ASSET_STORAGE=s3.

KindExtensionsText comes from
Markdown and text.md .txt .rst .adoc .logthe file
Data.yaml .yml .toml .json .csv .tsvthe file
Web.html .htm .xhtmlthe file
Codeabout 37 languages, such as .ex .py .js .ts .go .rs .java .sqlthe file
Office.docx .pptx .xlsxthe file
PDF.pdfpdftotext
Images.png .jpg .jpeg .gif .webp .svgtesseract, plus a description from the vision model
Audio.mp3 .wav .m4a .ogg .flaca whisper.cpp server
Video.mp4 .mov .webm .mkvffmpeg keyframes and audio

An unknown extension is read as plain text. When a tool is missing, the file is kept with its metadata and a warning such as ffmpeg not on PATH, and you can parse it again later.

Chat sessions

Commit a finished conversation so its lessons become memory:

curl -s -X POST http://127.0.0.1:4200/api/sessions/commit 
  -H "Authorization: Bearer $OPTIMAL_ENGINE_API_KEY" 
  -H "Content-Type: application/json" 
  -d '{
    "workspace": "default:notes",
    "correlation_id": "chat-2026-10-23-01",
    "title": "Renewal planning",
    "messages": [
      {"role": "user", "content": "When is the supplier renewal?"},
      {"role": "assistant", "content": "The call moved to the 14th."}
    ],
    "learned": ["The supplier renewal call is on the 14th."]
  }'

The chat is stored as an episode. Each learned item, up to 50, becomes a proposed claim in the review queue. The response (201) has the session_id, its uri, the summary, and the message_count. Read sessions back with GET /api/sessions and GET /api/sessions/:id.

Notion exports

Export a Notion workspace as Markdown & CSV, then send the zip:

mix optimal.import_notion ./notion-export.zip --workspace default:notes

Over HTTP, POST /api/import/notion takes the zip as the request body and starts a job; follow it with GET /api/import/notion/:job_id. Each page, database, and row becomes its own item with an optimal://<workspace>/notion/<id> URI, and page hierarchy and links become graph edges. The importer checks sizes before it unpacks anything, refuses ZIP64 archives, and never turns an entry name into a path on disk.

Apps (connectors)

A connector pulls records from an app on a schedule and stores them as sources. It only reads; nothing is written back to the app.

GroupApps
Mail, files, and docsGmail, Google Drive, Notion, Dropbox, OneDrive, Confluence, a local sources folder
Chat and meetingsSlack, Microsoft Teams, Zoom, Fathom
Work tracking and codeGitHub, Linear, Jira
CRM and businessHubSpot, Salesforce, HighLevel, Stripe
Publishing and formsbeehiiv, Jotform

Set CONNECTOR_KEY before you add one: it encrypts the app keys the Engine stores.

mix optimal.connector list
mix optimal.pull

Over HTTP, GET and POST /api/connectors list and add connectors, and POST /api/connectors/:id/run runs one now. docs/guides/connectors.md in the repository lists what each one pulls and how it signs in. Pulled records are stored as database rows with optimal://connectors/<kind>/<id> URIs, not as files, unless the connector is set to write files.

Limits

LimitValue
JSON request body8 MB
Import file1 GiB (OPTIMAL_IMPORT_MAX_BYTES)
Workspace bundle5 GiB (OPTIMAL_BUNDLE_MAX_BYTES)
Text sent to the embedding model6,000 characters per chunk
Learned items per chat session50
Was this page helpful?