# Add context to an AI task Start with the row that matches the context you have: | What you have | Use | First action | | --- | --- | --- | | A few known facts, no Oomira account | Keyless HTTP | Call `scaffold` | | A saved Oomira account | MCP | Connect with OAuth and call `whoami` | | Another person must answer | Interview link | Create an interview session | All three paths return Oomira Context Format (OCF): sourced, dated facts plus explicit gaps. ## Generate context without an account List the supported task schemas: ```bash curl -s https://oomira.com/api/v1/schemas ``` Choose a returned `name`, then send the facts you already know: ```bash curl -sX POST https://oomira.com/api/v1/scaffold \ -H 'content-type: application/json' \ -d '{ "profile": { "name": { "first": "Jane", "last": "Doe" }, "residency": ["CA-ON"] }, "schema": "mortgage_application" }' ``` Use `ocf` as the task context. Ask the first blocking item in `questions`. For the next call, send the response's complete `continuation` object as `continue_from` with the new answer: ```json { "continue_from": { "schema": "mortgage_application", "profile": { "name": { "first": "Jane", "last": "Doe" }, "residency": ["CA-ON"] }, "answers": {} }, "answers": { "property_target_value": 750000 } } ``` Don't reconstruct or omit `continue_from`. The API is stateless. ## Read saved context Connect `https://oomira.com/mcp` with OAuth. Call `whoami`, then call `about_me` or `about_world`. If the saved context is incomplete, call `list_schemas`, then `plan_interview`. To collect missing facts from the subject, call `create_interview_session`. Ask its returned `questions` in the conversation, render its MCP App, or send its `interview_url`. # How Oomira works Oomira builds a sourced, dated record of a person or company, then returns the facts needed for a specific task. Known facts stay distinct from missing facts, so an AI can continue the work without guessing. ## Choose the context source | Available context | First action | Result | | --- | --- | --- | | Connected Oomira account | Call `whoami`, then read the relevant world | Current, sourced context | | No saved context | Discover a schema, then call `scaffold` | Generated context and the next questions | | Another person must answer | Create an interview session | Expiring browser or MCP interview | Each path returns Oomira Context Format (OCF). An AI can use OCF directly without understanding Oomira's storage model. ## Complete the task 1. Receive the user's task 2. Load saved context when available 3. Otherwise, discover a schema and generate context 4. Ask the next blocking question 5. Continue with the returned state and new answer 6. Complete the original task with the resulting OCF Use research only when the task requires new evidence. Save the result only when later tasks should reuse it. ## The gaps are an acquisition plan, not a form A generated context does not just list what a task needs — it says *how to get each piece*, so an agent gathers automatically and asks the person only for the irreducible set. The path nests into the same sections the subject is interviewed in (`.
..`), every gap carries its acquisition route, and the context leads with a header that names the schema, names the subject, and tallies the lines below it: ``` # schema: Fundraising deck # acme_robotics = Acme Robotics # 123 fields tracked, one line each = 114 open (63 public record · 31 searchable · 5 connectable · 15 to ask Acme Robotics) + 9 present + 0 on record · a plain ? = ask acme_robotics.identity.logo_url: ? ← fetch [1] acme_robotics.identity.company_brand.brand_primary_color: ? ← fetch [2] acme_robotics.team.person.linkedin_url: ? ← search [3] acme_robotics.team.company_team.employee_count: ? ← fetch [1] acme_robotics.money.company_financials.annual_revenue: ? ← connect [4] # sources [1] official home about or team page [2] own site style [3] public search [4] stripe ``` Every number in that header is a count of lines below it, so a reader can check it by counting: `fields tracked` is the number of rows, and `open + present + on record` partitions them. When several schemas are compiled into one record the first line reads `# schemas (N, compiled as ONE record): …` and names each one. The `# = ` line declares who the relationship-anchored path prefix refers to; the prefix itself stays stable (`you.`, or a subject slug) because the name is a fact, not part of the path. The source names are written once, in a numbered `# sources` legend at the end, and referenced inline — so a long source slug never repeats. A document gap reads `? ← upload`; which document proves a fact is an ontology property (`accepted_evidence`), derived at the schema level, not enumerated in the OCF. | Route | Meaning | Agent action | | --- | --- | --- | | `← fetch ` | A public source that *has* this fact — a registry, API, or authored page (OpenCorporates, Wikidata, RDAP, the official site) | Retrieve directly — reliable, no permission | | `← search ` | A public candidate that *might* surface it (a person's spouse or citizenship via biography/news) | Try it — a lead, not a guarantee | | `← connect ` | The subject's own connected account (Stripe, Plaid, payroll, GitHub) | Pull over the user's OAuth connector | | `← upload ` | An issuer document (T4, pay record, cap table) | Read the document once provided | | a bare `?` | Only the subject knows (a preference, a decision) | Ask the person — the minimal set | The `fetch` vs `search` split is the source's declared yield — an authored fact mapping (`evidence_ceiling` verified/cited) versus a schema-driven candidate — so an agent knows what it will get versus what it can only try for. A bare `?` (no route) is the default: ask the subject. Read the routes top to bottom: fetch and connect first, search and ask last. That turns intake into orchestration — the same requirements engine an agent can call before it plans, so it knows exactly what it can gather versus what genuinely needs the human. The routes are declared per fact in the ontology; the OCF header documents the notation for any reader. # Collect missing context with an interview Use an interview session when an AI or application needs another person to supply missing facts. The session stores answers, then regenerates questions from the ontology planner after every answer. The API never stores a separate questionnaire. ## Choose keyless or authenticated storage | Session | Create with | Default expiry | Sensitive facts | | --- | --- | --- | --- | | Keyless | No authorization header | 24 hours | Removed before storage and never returned | | Authenticated | Bearer credential | 7 days | Available to the secure planner | Both session types return an opaque bearer link. Treat `interview_url` like a password-reset link. The database stores only the token's SHA-256 hash. An authenticated session persists answers inside the session. It does not silently write those answers into a durable world. Use an explicit world write or save action when later tasks should reuse them. ## Create a browser interview This request creates a keyless session: ```bash 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"] }, "answers": {} }' ``` The response includes: - `interview_url`: browser handoff at `/i/{token}` - `app.resource_uri`: Model Context Protocol (MCP) App resource for supporting hosts - `questions`: current ontology-planned actions - `targets`: every required fact and its current state - `ocf`: current Oomira Context Format (OCF) - `session.answers`: accumulated typed answers ## Submit typed answers and re-plan Read each question's `writes[].input` and `shape`. Send values under those input keys. Preserve booleans, arrays, numbers, and objects as JSON values. ```bash curl -sX PATCH \ https://oomira.com/api/v1/interview-sessions/oom_iv_your_token_here/answers \ -H 'content-type: application/json' \ -d '{ "answers": { "gross_annual_income": 125000, "income_type": "salary", "co_borrower": false } }' ``` The response contains the merged answers and the new `questions` array. Known, inferred, inapplicable, and explicitly absent facts disappear from the remaining interview automatically. ## Ask questions through MCP Connect `https://oomira.com/mcp` with OAuth, then: 1. Call `list_schemas` 2. Call `create_interview_session` with a returned schema name 3. Ask the first blocking question from `questions` 4. Call `submit_interview_answers` with the user's typed answer 5. Repeat until no blocking question remains An MCP host can render `ui://oomira/interview/{token}` when it supports MCP Apps. Otherwise, the AI can ask questions in the conversation or present `interview_url`. ## Read or revoke a session Call `GET /api/v1/interview-sessions/{token}` to retrieve current state. Call `DELETE /api/v1/interview-sessions/{token}` to revoke the bearer link immediately. The concise machine contract is also available at `/interviews.txt`. # Use saved context Saved context prevents an AI from asking for facts the user already supplied. A world stores typed facts, dates, sources, relationships, and history for a person, company, or project. ## Personal and company worlds A founder's personal world and company world remain separate records. The founder relationship bridges them, so a task can use the relevant facts without copying private personal context into the company. Create or select the task's world first; use cross-world context only when the caller is authorized for both. ## Use MCP from an AI client Connect `https://oomira.com/mcp` with OAuth, then: 1. Call `whoami` 2. Select the relevant world 3. Call `about_me` or `about_world` 4. Use narrower tools only when the task needs more detail ## Use HTTP from an application Call `GET /api/v1/worlds/:id/ocf` with an `oom_live_` bearer key when your application already knows the world. It reads the world's current facts and renders them through the same serializer the generated path uses, so cold and saved context cannot drift. | Parameter | Effect | | --- | --- | | `entity_uuid` | Scope the context to one entity | | `scope=all` | Serialize every entity; the default is the world's subject | | `provenance=none\|tier\|full` | Drop, collapse (default), or expand the source behind each line | | `include=inbound,history` | Add inbound edges and superseded history | | `as_of=YYYY-MM-DD` | The world as it was known and valid on that date | | `format=json\|tree` | A JSON envelope, or the context as a navigable file tree instead of one document | Generated context is stateless. Persist it only when another task should reuse it. # Read Oomira Context Format Oomira Context Format (OCF) is the compact output shared by saved and generated context. One fact per line, as `path: value [tier] @as-of`, optionally followed by trailing clauses. ```text you.identity.legal_name: Jane Doe [stated: user] you.work.employment.compensation: 185000 CAD [doc ✓] @2026-07-13 you.identity.industry: robotics [stated: agent] you.living.citizenship: present [inferred: existence] you.people.spouse: ? you.assets.real_estate: ? ← connect [1] ``` | Part | Meaning | | --- | --- | | `subject.section.field` | The path nests: subject, its life section, then the typed fact (a record adds a segment, `you.work.employment.compensation`) | | Value | Resolved value; `present` = exists but not captured yet; `none` = confirmed absent; `~x` = an approximation, never quote it as exact | | `[tier]` | WHO asserted it + how — `[stated: user]` (a human), `[stated: agent]` (an AI, verify it), `[doc ✓]`, `[sourced ✓]`, `[cited]`, `[rule]`, `[inferred: …]`. A tier can name its source: `[cited: acme.example]` | | `@date` | The as-of clock: when it was asserted or last known true. A date inside the *value* (`due 2027-04-30`) is the effective clock; the two never share a slot | | `?` / `? ← route` | A gap and how to fill it — a bare `?` = ask the subject; a route points into the numbered `# sources` legend | ## Trailing clauses A line can carry more than a value. These clauses exist because dropping them would make the document read as more certain than the record is. | Clause | Where | Meaning | | --- | --- | --- | | `· unconfirmed` | inside the tier bracket | It is in the record with that provenance, but no human has affirmed it. Nothing is held back outside the record — an absent line means we do not have it | | `· stand-in: ` | inside the tier bracket | The value is the wrong *kind* of thing for the field and is standing in because nothing better was published (a browser tab icon in `logo_url`). Real URL, usable as a placeholder; never present it as the thing the field names, and treat the real one as still missing | | `· prior: [tier] until ` | after the value | What the field held **before**, with its own source and the date it stopped being true. An arc, not an erasure: the line's own value is the current one. Cite a prior only as history, always with its date | | `· disputed: [tier]` | after the value | Another source asserts a different value for the **same** period and a human pinned the one on the line. Never quote a disputed value as current; if it matters, say the sources disagree | | `↳ implied by …` | after the value | The subject's own facts that imply this line — a grounded projection, not a guess | | `+N` / `(N prior)` | after the tier | N corroborating sources folded behind the one shown / N superseded older values folded out | `prior` and `disputed` are different on purpose, because the storage model treats them differently: a prior is **valid time** (true, then ended — nothing is superseded, the date decides which point is current), while a disputed reading is the undatable case where one of two sources is simply wrong. A line can be written with these clauses through `answers` sidecar keys on `POST /api/v1/scaffold`: `~source`, `~via`, `~unconfirmed`, `~standin`, `~since`, and `~prior` / `~disputed` (each a JSON list of `{ value, source, via, until }`). ## Records nest; nothing is folded away A record — a job, an account, an incorporation — is a **parent line with its own fields nested beneath it** at the record path (`you.work.employment`, then `you.work.employment.employer`). Every field the schema tracks gets its own line whatever its state, which is why the header's count is exactly the number of rows below it. The one exception: a record line whose value is `none` **closes** that record. Its fields do not apply to this subject, so they are neither listed nor counted. That is the only case where the document is smaller than the schema. ## The legend ships with the document Every OCF document is self-describing: it is preceded by `#` comment lines explaining the notation, and the legend is **adaptive** — it emits only the notation that document actually uses, and nothing it does not. A reader needs no system prompt and no external doc to interpret a line. `GET /api/v1/worlds/:id/ocf` accepts `?provenance=none|tier|full` to drop, collapse, or expand the source behind each line. OCF is a task projection, not a database export. It preserves the details that can change an AI's reasoning: type, date, evidence, currency, explicit absence, drift, and unresolved facts. # Find fields in the ontology The ontology defines every entity, fact, value shape, evidence rule, and temporal rule that Oomira can represent. Generated context, saved worlds, OCF, and the API share this contract. A schema is a named subset of the ontology for one task. The planner compares that schema with known facts and returns only the questions that can advance the task. The registry below and `GET /api/v1/ontology` are generated from the shipping library, so a type that exists is a type you can see. Pass `?entity_type=` to get that type's fact types with their acquisition routes, accepted evidence, system of record, coverage, and resolved retrieval routes; pass `?kind=` to filter entity types by kind. **A quantity that changes is an entity plus a series, not a field.** A `metric` entity holds *what* is measured — its name, unit, and cadence — and each reading is a separate `metric_value` fact on it, dated by the period it covers (`effective_date` opens the window, `end_date` closes it). So a year of monthly readings is twelve dated facts, not one number overwritten twelve times, and the whole curve is readable at any past date. A company points at its metrics through `tracked_metrics`; the metric points back through `tracked_by`. Search the registry below when you need an exact field, value shape, or evidence rule. # Create a schema from a representative source Use this workflow when a form, directory, checklist, or document already expresses the context your task needs. Oomira extracts its reusable field contract, maps each requirement to the ontology, and leaves the draft editable. Extraction never saves facts or starts enrichment. 1. Call `POST /api/v1/schemas/preview` with `url` or `source_text` 2. Review `requirements`, remove unwanted fields, and map every item in `unmapped` 3. Call `POST /api/v1/schemas` with the approved `fields` 4. Apply the saved schema to a world, then enrich its missing facts `POST /api/v1/schemas/preview` uses AI when it reads a link. The response reports `writes: false`. A source label is not an ontology fact until the response includes a `fact_type` and you approve it. ```typescript const draft = await oomira.post('/api/v1/schemas/preview', { url: 'https://example.com/representative-application', entity_type: 'company', }) await oomira.post('/api/v1/schemas', { name: 'accelerator_application', display_name: 'Accelerator application', entity_type: 'company', fields: draft.fields.map((field) => field.fact_type), }) ``` The same flow appears in `/demo` under **Generate from a source**. Paste a link, edit the required facts, then select **Save schema**. # See how Oomira completes missing facts Oomira plans fact completion from the ontology. Each fact type records how Oomira can obtain it: public search, an application programming interface (API), a private connection, a document, or a question for the subject. The planner follows four steps: 1. Compare the task schema with known facts 2. Read each missing fact’s ontology source and evidence rules 3. Present eligible search, API, connection, document, and question routes with their cost and authorization gates 4. Execute only the routes the caller requests, preserving source evidence on every candidate or write ## Plan before you spend `GET` or `POST /api/v1/enrichment/plan` answers "what would be enriched, and by which method" **without a key and without spending** — it is pure computation over the ontology's enrichment catalog: no stored user data, no model call, no provider call. Post `fact_types` to scope the plan to a record's in-scope facts, and `entity_type` to plan for a person or a company. Every capability comes back with the `likely_fact_types` it can satisfy, the specific `sources` and `source_tools` behind it, its `access` tier, and `document_types` where it is a document store. The four access tiers are a real fork you opt into knowingly: | `access` | Meaning | | --- | --- | | `public` | Free public web — an official site fetch, Wikidata, RDAP, feeds, Wayback, public GitHub. Costs nothing | | `paid_public` | Public data behind a metered pull (a corporate registry, X). Its own tier so the estimate is honest | | `oauth` | Connect an account (Stripe, Plaid, GitHub). Needs a saved account | | `document` | Upload a document, or connect a document store. Needs a saved account | The two open-web tiers ride `managed_enrichment`; the two account-gated tiers ride `private_connections`. Send `stated_accounts` — what the subject has said about named platforms, as `{ "x": "does_not_use" }` or `{ "x": { "status": "uses", "handle": "@acme" } }` — and the plan reshapes accordingly. Each affected lane gains `account_gating`, one row per platform and source: a **social** platform stated absent downgrades to `mentions_only` (the source can still surface mentions *of* the subject, never a profile pull), a confirmed handle upgrades to `profile_lookup` where a real profile lookup exists, and a **non-social** source stated absent is removed outright — there is no "mentions of your accounting account" fallback. A lane whose every platform-mapped source was stated unused comes back `dropped: true`. `POST /api/v1/research` reads `stated_accounts` with the same parser, so the plan you show and the run you fire cannot disagree. ## Enrichment is a graph, not a flat sweep The response also carries `unlock_lanes`, and each capability that owns one carries `unlock`. Some lookups need an input the record may not hold yet — a corporate registry indexes legal names, a profile API needs a handle. The lane says whether it is waiting on **us** or on the **person**: | `status` | Meaning | | --- | --- | | `ready` | The key is in hand; it fires | | `run_can_unlock` | The key is not in hand, but a run discovers it from the open web. Do **not** ask the person for it | | `needs_user` | The key has no open-web route at all. This is the only case where asking is honest | | `not_requested` | This run's target fields ask for nothing this lane fills — reported, never silently dropped | During a run the same lane list comes back on the result with the outcomes: `fired`, `no_match` (it ran and the source had nothing), `identity_blocked` (the discovered key could not be tied to this subject, so the lookup was refused), or `budget_blocked` (the key was held and the run cap stopped it, with the note saying how much was needed and how much was left). ## Run: `POST /api/v1/research` Billed, and never keyless. Bounded by three things before a cent moves: available credits (402 when empty), the account's research spending limit for the period (409 `budget_exceeded`, with the limit and its reset time), and the per-run cap. Omit `budget_cents` and the run's cap becomes the remaining room under that spending limit; supply it and the run is capped smaller. Research can also be switched off per world or account-wide (409 `research_disabled`). | `mode` | What it does | | --- | --- | | `full` (default) | Orient on the subject, sweep, read, extract, and write into the selected world | | `discover` | Producer only: register every discovered URL as an unread source and return the queue. No reading, no extraction | | `deepen` | Read the unread sources already queued against one entity. Needs `entity_uuid` + `world_id` | | `seed` | Register one `seed_url` (or structure one `seed_text`) and read it. Needs `entity_uuid` + `world_id` | | `read_sources` | World-level: read every unread source in the world, including its files. No subject required | | `registry` | Fire the corporate-registry pull directly on a legal name, optionally narrowed by `jurisdiction` | Useful inputs: `name` **or** `website` (a domain alone is a complete research identity — the site names its own subject); `entity_type`; `target_fields` (the contract — the run hunts exactly those and returns exactly those); `exclude_angles` (subtractive, so omitting it never narrows a run by accident); `stated_accounts`; `max_sources`; `progress: true` to stream the run as NDJSON progress lines with a final result line; and `background: true` to get a session id immediately and let the run finish detached. `known_facts` is what the record **already holds** — `[{ fact_type, value, entity_type? }]`, up to 60. They are not facts to write and not facts to bill. They are offered only as inputs to the dependency graph, so a run does not have to pay to rediscover a legal name it was just handed in order to chain off it. Chaining is the point: a fact one lane discovers unlocks a later lane inside the same run. A website yields the legal name, which unlocks the corporate registry (incorporation date, jurisdiction, company type, officers, filings). A founder name resolves to a confirmed person, whose own pages yield education, awards, prior ventures, and a real headshot. Every chained lookup is gated on identity — a discovered value used as the input to the next lookup is exactly how a namesake contaminates a record — and facts from an unlocked lane carry **their own** source and path, never the parent lane's. Each returned fact says which path produced it in `via`: `own_pages`, `web_search`, `web_search_deep`, `structured_api`, `registry`, `profile_pull`, `document`, `own_site_style` (the subject's own HTML and CSS, read deterministically for brand colours and type), or `ip_geolocation`. The response also carries `identity` — who the run decided the subject is. If it reports `needs_disambiguation`, supply a website or profile rather than trusting a name-only match. ## Read a document that has no text `POST /api/v1/structure` turns supplied content into typed facts. A file the subject handed you goes in document mode: send `subject` plus a document `source_kind` and the record extractor runs — a résumé becomes one employment record per role and one credential per qualification; a deck or investor update becomes one funding-round record per round, a product per named product, and a person plus employment per team member. When the file has no text layer at all — which is what a deck exported from a design tool always is — send `document_base64` (plus `document_pages` when you know it) instead of `text`. The pages go to the model as a document block and the same extraction contract reads them. Bounds: 3MB of file, at most 40 pages, and document pages require a subject and a document `source_kind`. It is one metered model call, billed like every other. Send the run's `budget_cents` and the cost of the exact request is priced **before** the call using a free token count; over the cap the request is refused with the estimate rather than quietly eating a balance. ## Review before you write `POST /api/v1/sources/preview` never writes and is the review-first path — dry-run one URL, or a named provider with `?source=`. Commit only the cited candidates you approve with `POST /api/v1/sources/commit`. Use `GET /api/v1/ontology?entity_type=company` to inspect this contract. The response includes acquisition routes, accepted evidence, systems of record, field coverage, and document-type coverage. Use `GET /api/v1/pricing` to map every API or connection to its `likely_fact_types`. File connections also return `document_types`; each document type lists the ontology facts it can verify, issuer requirements, and freshness limits. # Choose an API endpoint Use a keyless endpoint for generated context. Use an API key for saved worlds, writes, or paid enrichment. ## Create an API key API keys belong to a business. Sign in to Oomira, open **Account**, expand **Businesses**, select your business, then find **API keys**. Only a business owner can create or revoke a key. If you don't have a business yet, create one in the same section. Copy a new key when it appears. Oomira shows it once. Keep the `oom_live_` value on your server and verify it before building further: ```bash curl -s https://oomira.com/api/v1/me \ -H 'authorization: Bearer oom_live_your_access_token_here' ``` MCP does not use API keys. Connect `https://oomira.com/mcp` with OAuth instead. ## Context | Method | Endpoint | Use | Auth | | --- | --- | --- | --- | | GET | `/api/v1/schemas` | Discover supported task schemas | None (custom schemas need a key) | | POST | `/api/v1/scaffold` | Generate OCF and planner questions | None | | POST | `/api/v1/interview-sessions` | Create an expiring interview handoff | Optional key | | GET, DELETE | `/api/v1/interview-sessions/:token` | Read or revoke an interview | Bearer link | | POST, PATCH | `/api/v1/interview-sessions/:token/answers` | Save answers and re-plan questions | Bearer link | | GET | `/api/v1/worlds/:id/ocf` | Read saved context | Key | | POST | `/api/v1/research` | Discover or verify facts (billed) | Key | | GET, POST | `/api/v1/enrichment/plan` | What would be enriched, by which method | None | | POST | `/api/v1/sources/preview` | Preview one URL or named provider | Key | | POST | `/api/v1/sources/commit` | Save approved preview facts | Key | ## Artifacts | Method | Endpoint | Use | Auth | | --- | --- | --- | --- | | POST | `/api/v1/decks` | Generate a sourced fundraising deck from OCF (billed SSE stream) | Key | Generate the record first with `scaffold`, finish its blocking questions, then send the returned `ocf`. The deck writer may arrange and rephrase held facts, but it cannot invent missing claims. Slides without enough evidence return as `unwritten` with the exact interview fields they need. ```bash curl -N https://oomira.com/api/v1/decks \ -H 'authorization: Bearer oom_live_your_access_token_here' \ -H 'content-type: application/json' \ -d '{ "company": "Acme Robotics", "website": "https://acme.example", "ocf": "# schema: Fundraising deck\nacme.identity.company_name: Acme Robotics [stated: user]" }' ``` The response is `text/event-stream`. Handle `start`, `stage`, `slide`, and `heartbeat` as progress. The terminal event is either `done` (with `deck`, `costCents`, and `balanceCents`) or `error`. Do not treat the stream as successful until `done` arrives. ## Ontology and schemas | Method | Endpoint | Use | Auth | | --- | --- | --- | --- | | GET | `/api/v1/ontology` | List types, evidence rules, source coverage, and completion routes | None | | GET | `/api/v1/schemas/:name` | Read a built-in or custom schema | Built-in: none; custom: key | | POST | `/api/v1/schemas/preview` | Compile a representative URL or document into an editable schema draft | Key | | POST | `/api/v1/schemas` | Save a custom schema | Key | | GET, POST | `/api/v1/worlds/:id/ontology` | Read or extend what one world tracks | Key | | POST | `/api/v1/worlds/:id/apply-schema` | Apply a schema to a world | Key | ## Saved worlds | Method | Endpoint | Use | Auth | | --- | --- | --- | --- | | GET, POST | `/api/v1/worlds` | List or create worlds | Key | | GET | `/api/v1/worlds/:id` | Read a world | Key | | GET, POST | `/api/v1/worlds/:id/entities` | Read or write facts | Key | | GET | `/api/v1/worlds/:id/graph` | Read relationships | Key | | GET | `/api/v1/worlds/:id/timeline` | Read dated changes | Key | | GET | `/api/v1/public/worlds/:id` | Read a public world | Key with the `public:read` scope | ## Extraction, files, and export | Method | Endpoint | Use | Auth | | --- | --- | --- | --- | | POST | `/api/v1/structure` | Extract typed facts from supplied text, citations, or document pages (billed) | Key | | POST | `/api/v1/orient` | Resolve a seed to an entity and source plan | Key | | GET | `/api/v1/sources/corporate` | Look up a corporate registry record | Key | | GET | `/api/v1/sources/:id/snapshots` | Read the captured snapshots behind a source | Key | | POST | `/api/v1/map-seed/start` | Persist a generated scaffold into a world | Key | | GET | `/api/v1/integrations/:provider` | Inspect a connected provider | Key | | GET | `/api/v1/files/list`, `/read`, `/glob` | Discover and read world files | Key | | POST | `/api/v1/files/write`, `/edit`, `/grep`, `/delete` | Write, patch, search, or remove world files | Key | | POST | `/api/v1/files/import/presign`, `/commit` | Upload a file into a world | Key | | POST | `/api/v1/takeout/generate` | Build a sourced world export | Key | | GET | `/api/v1/takeout/download` | Download the generated export | Key | ## Account, spend, and run control | Method | Endpoint | Use | Auth | | --- | --- | --- | --- | | GET | `/api/v1/me` | Who the credential belongs to, and the current balance | Key | | GET | `/api/v1/pricing` | The public rate card | None | | GET | `/api/v1/billing/balance` | Current credit balance, in cents | Key | | GET | `/api/v1/usage` | Itemized spend over time | Key | | GET | `/api/v1/research/spend` | Research spend over a window | Key | | GET | `/api/v1/research/delegation-events` | Live run progress as a server-sent event stream | Key | | POST | `/api/v1/research/control` | Pause, resume, or cancel a run | Key | | GET, POST, DELETE | `/api/v1/keys` | List, mint, or revoke API keys | Browser session or existing key | | POST, GET | `/api/v1/auth/cli-session` | Register and poll a command-line device authorization | None | Send `Authorization: Bearer oom_live_your_access_token_here` to endpoints marked **Key**. Creating an interview session accepts optional authentication: without a key it creates a restricted keyless session. Reading, answering, and revoking a session use the opaque token in the session URL. API keys are server-side secrets. Scopes narrow a key: `world:` and `business:` bound it to specific data, and `public:read` — which is **not** granted by default — is what lets a key read a public world. # Connect an AI with MCP The Model Context Protocol (MCP) gives an AI direct access to saved Oomira context and ontology-planned interview sessions. Connect `https://oomira.com/mcp` with OAuth. Call `whoami` first. Then call `about_me` for cross-world context or `about_world` for one world. Prefer saved facts over public or model-generated guesses. If a required fact is missing, call `list_schemas`, then plan or create an interview. The world graph remains read-only through MCP. `create_interview_session` and `submit_interview_answers` write only to an isolated, expiring session. They never silently change durable world facts. ## Available tools | Tool | Inputs | Description | | --- | --- | --- | | `list_schemas` | — | List built-in and custom schemas that define the facts a task can require. | | `plan_interview` | `situation, answers?, stage?, subject?` | Plan the next questions for a task from the facts already known. Re-call with answers to shrink the gaps. | | `create_interview_session` | `situation, world_id?, profile?, answers?, subject?` | Create an authenticated interview with structured questions, an MCP App resource, and a browser link. | | `submit_interview_answers` | `token, answers, complete?` | Save a typed answer patch in an interview session and return the re-planned remaining questions. | | `whoami` | — | Who you are, your businesses, and the worlds you own. Nothing about a world’s contents. | | `about_me` | `compact?` | You across all your worlds: a cross-world projection of the owner (the “self” entity everywhere it appears). | | `about_world` | `world?, compact?` | Deep orient on one world: its lead/self entity, facts, neighborhood, timeline, and files. | | `get_entity` | `query, world?, include?, expand?` | Fetch an entity by slug or name. Pass "self" for the workspace owner. include=minimal|facts|full trades detail for size. | | `search_facts` | `query, world?` | Keyword search across entity names and fact values — the “what do you know about X” tool. Searches a world’s materialized entity records, so a world not yet materialized (e.g. a frozen snapshot) returns nothing. | | `get_ontology` | `world?, entity_type?` | What this world tracks: its per-world entity + fact types and metadata (the schema, not the data). | | `get_graph` | `world?, include_superseded?` | The whole entity-relationship graph: entities + edges, in one call. Inverse edges are derived, never stored twice. | | `get_timeline` | `world?, category?, from?, to?, limit?` | The world’s history as a dated event stream, with provenance behind each event. | | `list_directory` | `path?, recursive?, max_depth?` | List files in a world, like `ls`. Each world has a writable file tree and Scout’s read-only derived graph. | | `read_file` | `path, offset?, limit?` | Read a file, like `cat` / `sed -n`. Large files auto-slice; page with offset/limit. | | `glob` | `pattern` | Find files by glob pattern, like `find`. A world-slug prefix scopes to one world; without it, fans out across all. | | `grep` | `pattern, path?, glob?, case_insensitive?` | Regex search of file contents, like `grep -rn`. Returns path + line number to feed straight into read_file. | Use `create_interview_session` when the AI should ask questions in the conversation, display an MCP App, or provide a browser handoff. Write durable facts through the HTTP worlds API. # Understand pricing Reading and generating context is free. Verification and persistent hosting are paid. | Activity | Price model | | --- | --- | | Read context, call `scaffold`, or use `@oomira/world` | Free | | Search providers or run models for research | Provider cost plus the displayed markup | | Keep a persistent, maintained world | Monthly plan | The interactive table below reads the same pricing store used by billing. Applications can read those rows from public `GET /api/v1/pricing`. This text doesn't copy rates, so it can't drift from billing. An AI accesses enrichment through one Oomira API, but upstream execution varies. Oomira uses its provider account for services such as Brave, Exa, Perplexity, OpenCorporates, X, Reddit, and Anthropic. It reads Wikidata, Wikipedia, RDAP, public GitHub data, websites, RSS, Atom, Substack, YouTube feeds, Medium feeds, and Wayback through direct public endpoints. Connected GitHub, Google, Dropbox, Stripe, and Plaid data requires user authorization. No source runs automatically. Provider-backed research, models, and image generation are charged only when invoked.