# Oomira /demo — build a structured record of a person or company (no account) WHAT THIS IS Supply the facts you already know and choose the task. Oomira returns typed, dated OCF (Oomira Context Format) plus the facts still needed. Use /demo for a new record. Use the MCP server at https://oomira.com/mcp when the person or company already has a saved Oomira account. PROGRAMMATIC (keyless — no account, no key, the clean way, no browser) POST https://oomira.com/api/v1/scaffold (NO Authorization header — it is free and keyless) body: { "profile": { ...what you know... }, "birthday": "YYYY-MM-DD", "objective": "buy_home" } -> { "ok": true, "ocf": "", "facts_count": N, "situation": "mortgage_application", "blocking_remaining": 4, "completeness": { score, needed, met }, "recognized": N, "gaps": [ { input, ask, shape, none_ok, blocking }, ... ], "questions": [...], "targets": [...], "continuation": {...}, "next": { how_to_fill } } Nothing is fetched and nothing is written — profile in, entailed/dated/gap-aware OCF out. The same engine the demo runs. To PERSIST the result into a world, use POST /api/v1/map-seed/start. WHEN YOU'RE MISSING INFO (the interview loop) The "gaps" array IS your interview script — do NOT invent your own questions. Each gap gives you the question to ask ("ask") and the answer shape ("shape": year|date|percent|money|count|text). A gap does NOT tell you why it matters: we hold the facts, YOU do the reasoning — explain the reason in your own words. If "none_ok": true, "I don't have one" is a valid answer — record it, don't leave it open. Declare an "objective" (e.g. buy_home) and the gaps BLOCKING that objective sort first, with "blocking_remaining" as your progress bar. Loop: relay 2-4 asks to your user in your own voice -> add their answers to `answers` AND send the previous reply's `continuation` back as `continue_from` -> re-POST -> gaps shrink. Exit when blocking_remaining is 0, OR the user can't/won't answer — then the OCF honestly names the remaining ?gaps, which is the point. DON'T OMIT `continue_from`: this API is stateless and cannot recover facts from an earlier request, so without it every answer you already collected is silently dropped and the loop never converges. Objectives that bind a situation (all 19, live from the ontology): buy_home -> mortgage_application get_visa -> visa_application file_taxes -> tax_filing build_resume -> resume prepare_fundraising_due_diligence -> fundraising_due_diligence get_life_insurance -> life_insurance_application medical_history -> medical_history estate_plan -> estate_planning retire -> retirement_planning financial_plan -> financial_planning personal_record -> personal company_record -> company file_business_taxes -> business_tax_filing board_update -> board_update sell_business -> business_sale build_fundraising_deck -> fundraising_deck prepare_investor_memo -> investor_memo sell_house -> property_sale organize_documents -> documents HAND THE INTERVIEW TO A HUMAN INSTEAD (also keyless — no account, no key) If your user would rather fill a form than answer you in chat, POST https://oomira.com/api/v1/interview-sessions -> { "interview_url": "https://oomira.com/i/", "app": {...}, "questions": [...], "targets": [...], "ocf": "..." }. Real hosted link, expires in 24h, and you can PREPOPULATE it with everything you already know so they only fill the gaps: curl -sX POST https://oomira.com/api/v1/interview-sessions -H 'content-type: application/json' \ -d '{"situation":"mortgage_application","profile":{"name":{"first":"Jane","last":"Doe"},"residency":["CA-ON"]}}' NOTE THE VOCABULARY: /scaffold speaks `objective` ("buy_home"); this endpoint speaks `situation` ("mortgage_application"), the schema that objective binds to (see the table above). Sending an `objective` here returns 400 unknown_situation. /scaffold's reply carries the `situation` it resolved — pass that straight through. ONCE YOU HAVE THE LINK, you have TWO ways to get it completed (do either, or both): (a) HAND IT TO THE USER — send them the interview_url; they open it in their own browser and answer. (b) DRIVE IT YOURSELF — open the same link in the user's browser and complete it FOR them (you can read a company's site, tap the gates, fill what you know). Same session either way. Each answer PATCHes back server-side, so you poll GET /api/v1/interview-sessions/ to read the answers + the re-planned OCF, no key. (A key is only needed to bind the session to a stored world.) Secure fields (SIN, income, account numbers) are collected ON THE USER'S DEVICE and are never returned to you — you get the structure, they keep the secret. WHY USE THE BROWSER LINK, not just loop /scaffold: it is the ONLY path that can ENRICH. /scaffold spends nothing — no fetch, no research — so it can only ASK a fact, never look one UP. The interview link runs in the USER'S session with THEIR credits (every user starts with $2.00, and can buy more), so its ✦ enrich actions can fill gaps the keyless API structurally cannot: "fill from public sources" (research, keyless — needs a NAME on the record to look someone up), or "connect an account" / "upload a document" (Stripe, Plaid, GitHub, Drive — these need the user to save an account). The ENRICH panel shows the estimated cost against the balance before it runs. Reach for it when a fact is DISCOVERABLE (a company's details, a LinkedIn bio) rather than something only the user knows. IN-BROWSER, no link (https://oomira.com/demo — the try-it-yourself surface) The SAME keyless engine as /scaffold, running on-device. A person taps situations + gates and the "Your context · OCF" panel assembles live; answers PERSIST in that browser (localStorage — they survive a reload, and clear only on "Clear all entered context"). But it is CLIENT-ONLY: there is no server session and no token, so an agent cannot read it back over the API — you'd have to scrape the rendered OCF off the page. For an agent handoff you can actually read back (and enrich), mint an interview link above; /demo is where a human tries it themselves. PROFILE JSON SHAPE (the `profile` you POST above; the same facts the browser demo assembles) Check `recognized` in the response: it counts how many of your profile facts we understood. If it comes back 0, we ignored your whole profile — you used keys we don't read. Fix the keys, don't retry. { "residency": ["CA-ON"], // or ["US-CA"] — these two are validated; others are ignored "birth_date": "1988-05-20", // resolves age-triggered rules (else they stay ?gaps) "name": { "first": "Sam", "last": "Rowan" }, "partner": { "first": "Alex" }, // or just true if you only know they have one "marital_status": "married", // married | separated | divorced | widowed "children": [{ "age": 7 }, { "age": 4 }], // or a plain count: "children": 2 "expecting": true, // boolean only — "expecting": 1 is silently ignored "homes": [{ "tenure": "own", "mortgage": true, "value": 800000, "bought": "2019" }], // tenure: own | rent "vehicles": [{ "ownership": "own" }], // ownership: own | lease — anything else (incl. "finance") reads as own "companies":[{ "name": "Rowan Studio", "structure": "sole_prop", "employees": "1-4", "revenue": "100k-500k", "employs_me": true, "raised": false }], // structure: sole_prop | incorporated | mixed "income": 130000, // annual, plain number "employment": ["employed"], // employed | self_employed | founder | unemployed | retired | student "citizenships": ["CA"], // CA | US | other "education": [{ "institution": "McGill", "credential": "BSc", "year": "2010" }], "drives": true, "gender": "female" // female | male | nonbinary | undisclosed } All amounts are plain numbers (not strings). Anything you don't know: leave it out. WORKING EXAMPLE (Ontario, married, 2 kids, sole company) {"residency":["CA-ON"],"birth_date":"1988-05-20", "partner":{"first":"Alex"},"marital_status":"married","children":[{"age":7},{"age":4}], "companies":[{"name":"Rowan Studio","structure":"sole_prop","employees":"1-4","employs_me":true}], "income":130000,"employment":["founder"],"education":[{"institution":"McGill","credential":"BSc"}]} → POST it (keyless), literal and runnable as-is: curl -sX POST https://oomira.com/api/v1/scaffold -H 'content-type: application/json' \ -d '{"profile":{"residency":["CA-ON"],"birth_date":"1988-05-20","partner":{"first":"Alex"},"marital_status":"married","children":[{"age":7},{"age":4}],"companies":[{"name":"Rowan Studio","structure":"sole_prop","employees":"1-4","employs_me":true}],"income":130000,"employment":["founder"],"education":[{"institution":"McGill","credential":"BSc"}]},"objective":"buy_home"}' → That example returns recognized: 6 (56 facts). If yours returns 0, you are sending keys we do not read. FURTHER - OCF spec: https://oomira.com/docs#ocf (grammar: path: value [tier] @as-of, gaps ?x, absence none) - Full docs: https://oomira.com/docs.txt - Persistent (authenticated) version: the MCP server, https://oomira.com/mcp