Developers

Everything the dashboard does, your code can do.

A REST API and an MCP server over the same workspace: send data, ask with citations, run procedures, read cameras.

Quick start

Three calls

Create a key in the dashboard under Settings → Developers. Then send something and ask about it.

# 1. send a reading (IRF)
curl https://YOUR-IRRIS/api/v1/ingest \
  -H "Authorization: Bearer $IRRIS_KEY" -H "Content-Type: application/json" \
  -d '{"type":"reading","source":"line-3/plc","subject":"asset:press-7",
       "data":{"value":182.4,"unit":"C"}}'

# 2. send a manual
curl https://YOUR-IRRIS/api/v1/ingest/file -H "Authorization: Bearer $IRRIS_KEY" -F file=@press7-manual.pdf

# 3. ask
curl https://YOUR-IRRIS/api/v1/ask \
  -H "Authorization: Bearer $IRRIS_KEY" -H "Content-Type: application/json" \
  -d '{"message":"Is press 7 within its platen limits?"}'
→ {"reply": "No. It read 182.4 C [1], above the 180 C hold limit on p. 14 of the manual [2].",
   "sources": [{"n":1,"title":"…"},{"n":2,"title":"press7-manual.pdf","page":14}], "conversation_id": "…"}

Authentication

One key per integration

Keys start with irr_ and belong to one workspace. Send Authorization: Bearer irr_… or X-API-Key: irr_…. Clients that can only take a URL may add ?key=irr_…, but a key in a URL can end up in logs. Keys are shown once; delete one to revoke it.

Send data

Any data, one standard

Records follow the Irris Record Format. Send IRF when you can, and anything else as it is.

CallWhat it takes
POST /api/v1/ingestOne IRF record, a list, or {"records": [...]}. Up to 10,000 per call. Same source + id updates.
POST /api/v1/ingest?type=work_order&source=erpAny other JSON. Each object becomes one record of that type.
Content-Type: application/x-ndjsonOne record per line, for streams and big batches.
POST /api/v1/ingest/filePDF, Word, Excel, CSV, JSON, Markdown, text, images (multipart file). PDFs keep page numbers for citations.
POST /api/v1/hooks/{secret}A webhook made in Data → Webhooks, for systems that can only POST. No key needed: the secret is in the URL.
PostgresConnect in Data → Databases. Irris syncs the tables you pick and runs read-only queries live. Use a read-only database user.

Ask

Questions in, cited answers out

POST /api/v1/ask with {"message", "conversation_id"?, "camera_id"?, "run_id"?, "stream"?}. Irris searches your records and documents, queries connected databases, looks through cameras and starts procedures on her own. Every fact in the reply carries a [n] that matches sources. With "stream": true the reply is Server-Sent Events: tool for each step, then done.

Procedures

SOPs that check themselves

A procedure is a list of steps. A step can say what correct looks like on camera (check) and the range a reading must fall in. A run walks through it: each step is checked through the camera or marked by hand, out-of-range readings fail, and the finished run writes a batch_record.

Calls

POST /api/v1/proceduresCreate
POST /api/v1/runs{"procedure_id", "camera_id"?, "label"?}
POST /api/v1/runs/{id}/check{} checks through the camera; {"result": "pass", "reading": {"value": 180, "unit": "C"}} marks it by hand
POST /api/v1/runs/{id}/back · /stopMove back a step, or stop
{
  "name": "Mould change, tool T-12",
  "steps": [
    { "instruction": "Lock out the press",
      "check": "red LOTO tag on the main isolator" },
    { "instruction": "Check the platen temperature",
      "check": "the controller display is readable",
      "reading": { "label": "platen", "min": 175,
                   "max": 185, "unit": "C" } },
    { "instruction": "Fit the mould",
      "check": "all four clamps closed",
      "caution": "two people to lift" }
  ]
}

Cameras

A phone, or the cameras you have

POST /api/v1/cameras {"kind": "phone"}Returns a pairing link. Open it on any phone: it streams its back camera to Irris. No account on the phone.
POST /api/v1/cameras {"kind": "url", "url"}An HTTP snapshot URL, an MJPEG stream, or RTSP (with OpenCV on the server). Irris grabs a frame when it needs one.
POST /api/v1/cam/frame?t={token}Push your own JPEG frames for a paired camera, from any device or script.
GET /api/v1/cameras/{id}/frame.jpgThe latest frame.
POST /api/v1/cameras/{id}/look{"question"} → {"say", "status", "reading"}

MCP

Give your AI agents your operation

Streamable HTTP at /mcp, stateless, JSON responses. Tools: ask, ingest, search, records, databases, sql, look, cameras, procedures, start_run, run_status, check_step, remember. Resources: irris://irf (the standard) and irris://workspace.

// Claude Desktop, Cursor, any MCP client
{
  "mcpServers": {
    "irris": {
      "type": "http",
      "url": "https://YOUR-IRRIS/mcp",
      "headers": { "Authorization": "Bearer irr_…" }
    }
  }
}
# Claude Code
claude mcp add --transport http irris \
  https://YOUR-IRRIS/mcp \
  --header "Authorization: Bearer $IRRIS_KEY"

# clients that only take a URL
https://YOUR-IRRIS/mcp?key=irr_…

Models

Bring your own models

Irris reasons with any OpenAI-compatible chat API that supports tool calling, and sees with any OpenAI-compatible API that takes images: Ollama or vLLM on your own GPU, or a hosted provider. Set them per workspace in Settings → Models. Keys are stored encrypted and never returned. Irris never pools workspaces or trains anything shared on your data. What reaches a hosted model follows that provider's terms, so run both models on your own GPU to keep everything in-house.

Reference

Every endpoint

The full OpenAPI reference, with every field, is at /api/docs (spec: /api/v1/openapi.json). A guide for LLMs is at /llms.txt.

Building an agent? Give it /api/v1/openapi.json and /llms.txt, not this page. Every error carries a code and a next_action; creates take an Idempotency-Key; GET /api/v1/changes?cursor= is a feed of everything that changed; GET /api/v1/status/{kind}/{id} says why anything is stuck and what unblocks it; webhooks are signed with HMAC-SHA256.