API reference
Base URL https://oort.is-a-good.dev. Every endpoint takes and returns JSON, and every one needs a bearer token.
POST /v1/search
Query in, ranked and extracted content out.
| Field | Type | Default | Notes |
|---|---|---|---|
query | string | — | Required, 1–2000 chars |
max_results | int | 5 | 1–50 |
max_tokens | int | 2500 | Budget for the returned content |
depth | enum | fast | fast or deep |
deadline_ms | int | server default | Partial results rather than an error on expiry |
include_domains | string[] | [] | Restrict to these hosts |
exclude_domains | string[] | [] | Never return these hosts |
freshness_days | int | — | Only content newer than this |
include_raw_content | bool | false | Full document alongside the passage |
include_images | bool | false | Top-level images[] |
include_favicon | bool | false | Per-result favicon |
include_follow_up_questions | bool | false | Derived from retrieved section headings |
extract_fields | string[] | [] | e.g. ["version","timeout"] |
extract_mode | enum | deterministic | auto adds a verified LLM pass for unfilled fields |
stream | bool | false | SSE; results arrive as they clear ranking |
Result object
| Field | Notes |
|---|---|
content | The passage, wrapped in untrusted-content delimiters |
provenance | char_start, char_end, heading_path — offsets into that document's extracted markdown |
score | Relative rank score; comparable within one response only |
injection_risk | 0–1 signal score, with injection_signals naming what fired |
tokens | Counted, not estimated |
providers | Which lanes surfaced this URL |
POST /v1/extract
URLs to clean markdown. Up to 20 per call, fetched concurrently.
| Field | Type | Notes |
|---|---|---|
urls | string[] | Required, 1–20 |
max_tokens | int | Truncates each document |
extract_fields | string[] | Adds structured[] with offsets |
screenshot | bool | Forces the browser tier |
full_page_screenshot | bool | Whole scroll height |
actions | object[] | See below |
include_images, include_favicon | bool | Per document |
Per-document error is set rather than failing the whole request, so one dead URL never costs you the other nineteen.
Browser actions
{
"urls": ["https://example.com/app"],
"actions": [
{"type": "click", "selector": "#accept-cookies"},
{"type": "type", "selector": "#search", "text": "liveness probe"},
{"type": "press", "key": "Enter"},
{"type": "wait", "selector": ".results", "ms": 5000},
{"type": "screenshot", "full_page": true}
]
}Vocabulary: click, type, press, scroll, select, wait, screenshot. Each requires its own arguments — a click without a selector is a 422, not a silent no-op.
executeJavascript action, and there will not be. Accepting a caller-supplied snippet and evaluating it in the page is one line of code and turns this endpoint into remote code execution against arbitrary origins from the host's network. Every action compiles to a fixed driver call.POST /v1/map
Enumerate a site's URLs without fetching page bodies.
| Field | Type | Notes |
|---|---|---|
url | string | Site root |
limit | int | 1–5000, default 500 |
search | string | Substring filter, applied while collecting |
include_subdomains | bool | Default false |
source reports where the list came from: sitemap, index (the site has no usable sitemap, so this is what we have crawled), or none.
POST /v1/answer
Search, stream results, then stream a synthesised answer over SSE. Results are emitted before synthesis begins — an answer is never a blocking prerequisite for getting content back.
GET /v1/replay/{request_id}
Reconstruct a past request: the same corpus, the same ranking inputs. Deterministic extraction is what makes this reproduce rather than approximate.
POST /tavily/search
A compatibility shim for clients written against Tavily's request shape. Maps the common subset — search_depth, days, include_answer, include_images, include_favicon, include_follow_up_questions — and adds an oort object with request id, degraded reasons and injection scores. It is a subset, not parity; verify against their current reference before assuming a field exists.
Errors
| Status | Meaning |
|---|---|
401 | Missing or unknown key |
422 | Request failed validation; the body names the field |
429 | Rate limited; retry-after is set |
5xx | Unexpected. request_id is in the response and the audit log |
200 with partial: true and whatever was ready.