Miriel Docs

REST API

The whole platform is plain HTTPS and JSON. This is the curated reference for the endpoints most integrations need; every example runs as written once MIRIEL_API and MIRIEL_API_KEY are exported (see Get started).

Basics

Base URL and conventions

Base URLhttps://api.miriel.ai — every path below is under /api/v2
BodiesJSON, except uploads, which are multipart/form-data
HealthGET /api/v2/health — no auth
Trailing slashesNamespace roots accept both: /api/v2/query and /api/v2/query/
ExplorerSwagger UI at /api/v2/docs, spec at /api/v2/swagger.json (a few routes, learn among them, are documented here but missing from the generated spec)

Authentication

Send your credential on every request in the `x-access-token` header. There is no Authorization: Bearer scheme on Miriel's own endpoints.

bash
curl -s -X POST "$MIRIEL_API/api/v2/get_projects" \
  -H "x-access-token: $MIRIEL_API_KEY"
CredentialShapeUse
API keyUUIDServers, scripts, integrations. From Settings → Developers.
Session JWTJWTInteractive clients. POST /api/dashboard/v1/login with HTTP Basic (email / password) returns a two-week token.
Browser apps
The API only allows the dashboard's own origins. A web app on your domain should call Miriel from its backend and keep the key there.

Errors and limits

StatusBodyMeaning
401{"message": "Api key / token is missing!"}No x-access-token header
401{"message": "Token is invalid!"}Wrong key, or an expired JWT
403{"error": "…"}The credential cannot use this endpoint
4xxan explanatory messageAn account limit was hit (resources, daily/monthly queries, monthly tokens)

Current usage is on the workspace's Usage & billing page; GET /api/v2/limits/ reports the configured limits.

Learn

POST /api/v2/learn

The primary ingest endpoint. input is a list of items; each value is inline text, a URL, or the name of a file uploaded in the same request.

curl -s -X POST "$MIRIEL_API/api/v2/learn" \
  -H "x-access-token: $MIRIEL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "project": ["default"],
    "input": [
      {"value": "Our pricing decision: usage-based, with a free tier up to 1,000 queries a month."},
      {"value": "https://miriel.ai/docs"}
    ]
  }'

Request fields

FieldTypeRequiredDescription
inputarrayYesItems to learn — see item fields below.
projectstring[]NoProjects (workspace tags) to file the items under. Default ["default"].
metadataobjectNoKey/values stored on every resource; filter on them with metadata_query.
priorityint | "pin" | "norank"NoRanking weight, default 100. "pin" (-2) always ranks above unpinned results; "norank" (-1) keeps a resource out of ranked results.
grant_idsstring[]NoAccess grants for the new resources (["*"] = everyone in the account).
discoverablebooleanNoWhether the resources appear in cross-project discovery.
recursion_depthintegerNoFor URLs: how many links deep to crawl. 0 = just the page.
chunk_sizeintegerNoOverride chunking for embedding.
streams / streaming_optionsobjectNoFor RTSP and video-stream ingestion.

Item fields

FieldTypeRequiredDescription
valuestringYesText, a URL, or an uploaded filename.
upsert_idstringNoA stable id you choose. Learning again with the same id replaces the resource instead of adding a duplicate.
command"add" | "upsert" | "append"Noupsert and append require upsert_id.
expiration_secondsintegerNoTime to live; expired items are swept automatically.

The response carries job_ids. POST /api/v2/upload_files is a multipart-oriented alias of the same handler; GET /api/v2/get_supported_types lists accepted file types.

Jobs

POST/api/v2/get_job_status{"job_ids": [...]} → {"jobs": {"<id>": "completed"}}
GET/api/v2/jobs/<job_id>/timelinestage-by-stage timeline for one job
POST/api/v2/kill_jobcancel a running job

Query

POST /api/v2/query/

bash
curl -s -X POST "$MIRIEL_API/api/v2/query/" \
  -H "x-access-token: $MIRIEL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "query": "What did we decide about pricing?",
    "project": ["default"],
    "num_results": 5
  }'
FieldTypeRequiredDescription
querystringYesThe question.
projectstring | string[]NoScope. Omit (or "*") to search every project.
num_resultsintegerNoPassages to retrieve, default 10. Pinned resources count toward it.
metadata_querystringNoFilter on metadata: key=value, >, <, >=, <=, combined with AND / OR (spaces required, case-sensitive).
want_llm / want_vector / want_graphbooleanNoToggle answer synthesis and each retrieval leg. All default true — set want_llm false for retrieval only.
modelstringNoOverride the answering model for this query.
response_formatobjectNoStructured output schema, e.g. {"founders": ["string"], "count": "integer"}. llm_result comes back as a JSON string.
input_imagesstring | string[]NoImage URLs to ask about alongside your data.
conversation_mode / conversation_historyboolean / arrayNoMulti-turn — see Conversations.
streamingbooleanNoStream the answer as server-sent events — see Streaming.
query_type"search" | "auto" | "exhaustive"Nosearch (default) answers from the best passages. exhaustive reads every matching document — for "how many contracts mention sales tax?" — and returns a query_id to poll.
publish_optionsarrayNoDeliver the result somewhere when done, e.g. [{"type": "email", "to_addresses": ["you@example.com"]}].

Response

jsonc
{
  "results": {
    "query_id": "…",
    "status": "complete",           // an exhaustive query returns early — poll until complete
    "llm_result": "…",              // the answer (a JSON string when response_format is set)
    "vector_db_results": [ … ],     // ranked passages, each with its source and metadata
    "timings": { … },
    "conversation_history": [ … ]   // when conversation_mode is on
  }
}

Every query is stored. GET /api/v2/query/<query_id> returns the stored result with status at the top level (not wrapped in results).

GET/api/v2/query/query history — page_size, page_offset, statuses, created_before/after
GET/api/v2/query/<query_id>one stored result
GET/api/v2/query/<query_id>/downloadpresigned URL for the full result
POST/api/v2/query/timedthe same query with a stage-by-stage timing breakdown
POST/api/v2/format_query_resultre-format a stored result

Conversations

Queries are independent by default. With conversation_mode: true the response includes results.conversation_history; send it back as conversation_history on the next query. The server keeps no conversation state — persist the history yourself to resume later.

json
{
  "query": "And what did we charge before that?",
  "conversation_mode": true,
  "conversation_history": [ /* results.conversation_history from the previous response */ ]
}

Streaming

With "streaming": true the answer arrives as server-sent events: metadata, start, then chunk events carrying content, and finally done (or error). With voice_mode an audio event carries base64 audio near the end.

bash
curl -N -X POST "$MIRIEL_API/api/v2/query/" \
  -H "x-access-token: $MIRIEL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"query": "Summarize the Q3 report", "streaming": true}'
# data: {"type": "chunk", "content": "Revenue grew …"}

Resources and projects

POST/api/v2/get_all_documentslist resources (filter by project, metadata_query)
POST/api/v2/get_resourcefetch one resource (stream_resource to stream it)
POST/api/v2/get_resource_chunksevery chunk of one resource
POST/api/v2/remove_resourceforget a resource
POST/api/v2/resource_versionsversion history (restore_resource_version, delete_resource_version)
POST/api/v2/edit_contentedit in place (also edit_csv, edit_docx_content, edit_file_metadata …)
POST/api/v2/set_resource_accesschange who can read a resource
POST/api/v2/get_projectslist projects (create_project, delete_project)
Keeping a local folder in sync
Tools that mirror a directory can use the change feed: GET /api/v2/project/<project>/resources?modified_since=, GET /api/v2/project/<project>/changes?since=, and PUT / DELETE /api/v2/project/<project>/resource. Content still goes in through learn.

Knowledge graph

Entities and relationships are extracted during ingest and feed every answer (want_graph). Explore or curate the graph directly:

POST/api/v2/graph/relationshipsrelationships for an entity
POST/api/v2/graph/traversewalk the knowledge graph
POST/api/v2/graph/statsgraph size and coverage
POST/api/v2/graph/mergemerge duplicate entities (/graph/delete removes one)

Integrations and sources

Rather than calling learn for every change, connect a provider once and let a source backfill its history and keep syncing. The workspace's Connect page is a UI over these endpoints; GET /api/v2/providers/ is the manifest of what can be connected.

OAuth connections

GET/api/v2/oauth/<provider>/authorizestart the flow — returns the consent URL
GET/api/v2/oauth/<provider>/statusis this provider connected?
POST/api/v2/oauth/<provider>/disconnectremove the connection
GET/api/v2/oauth/connectionsall connections

Providers include google, microsoft, slack, discord, dropbox, github, notion, salesforce and zoom. Once connected, browse before choosing what to sync — e.g. /oauth/google/drives, /oauth/slack/channels, /oauth/github/repos.

Sources

POST/api/v2/sources/create — provider, scope (folder, channel, repo…), target project
GET/api/v2/sources/list (GET/PATCH/DELETE /sources/<id> for one)
POST/api/v2/sources/<id>/backfillpull historical items
POST/api/v2/sources/<id>/pausepause live sync (/resume restarts it)
GET/api/v2/sources/<id>/statusbackfill and sync progress

Push from your own systems

POST/api/v2/webhooks/ingest/<watcher_id>generic inbound webhook — the id in the URL authorizes it
POST/api/v2/git_repos/sync_git_repoingest a git repo and keep it synced

Apps

Describe an application in plain language and Miriel compiles it into a typed, reviewable manifest — its workflows, the data it needs and the grants it may use — then runs it on the platform. See Workflow optimization for what that looks like in practice.

POST/api/v2/workflow-apps/compile{"description": "…"} → a draft manifest
POST/api/v2/workflow-apps/create the app from a manifest
POST/api/v2/workflow-apps/<app_id>/activateprovision data, register workflows, start
POST/api/v2/workflow-apps/<app_id>/amendchange it in plain language (/rollback undoes a version)
GET/api/v2/workflow-apps/<app_id>/runsruns (/records, /interactions for its data and questions for you)
REST API — Miriel Docs