{
  "name": "unlob API endpoints",
  "description": "Every HTTP endpoint, with parameters and return shapes.",
  "baseUrl": "https://api.unlob.com",
  "openapi": "https://www.unlob.com/openapi.json",
  "documentation": "https://www.unlob.com/docs/api",
  "dateModified": "2026-08-05",
  "authentication": {
    "header": "x-api-key",
    "alternative": "Authorization: Bearer",
    "keyFormat": "ulb_ followed by 48 hexadecimal characters",
    "note": "Keys are stored as hashes and shown once. /healthz, /readyz, /metrics and /describe need no authentication."
  },
  "groups": [
    {
      "id": "search",
      "label": "Search & retrieval",
      "blurb": "Find passages, widen a result set, and fetch the one document you actually decided to read."
    },
    {
      "id": "graph",
      "label": "Coverage graph",
      "blurb": "Traverse the relationships the index already computed: corroboration, authority, entity briefs, connecting paths and packed context."
    },
    {
      "id": "ops",
      "label": "Discovery & operations",
      "blurb": "Capability discovery, coverage transparency, account state and the probes your infrastructure expects."
    }
  ],
  "endpoints": [
    {
      "slug": "search",
      "method": "GET",
      "path": "/search",
      "name": "Search",
      "group": "search",
      "summary": "The main query surface: returns metadata-only passage hits — url, host, title, snippet, score and world-model signals — but never the page body.",
      "requiresAuth": true,
      "mcpTool": "web_search",
      "parameters": [
        {
          "name": "q",
          "type": "string",
          "required": true,
          "default": null,
          "description": "The query. Supports AND / OR, `-` negation and \"quoted phrases\"."
        },
        {
          "name": "mode",
          "type": "keyword | semantic | hybrid",
          "required": false,
          "default": "hybrid",
          "description": "Retrieval strategy."
        },
        {
          "name": "limit",
          "type": "integer",
          "required": false,
          "default": "10",
          "description": "Number of hits. `0` returns the count only."
        },
        {
          "name": "vertical",
          "type": "string",
          "required": false,
          "default": null,
          "description": "Restrict to one vertical core. Omit to auto-route."
        },
        {
          "name": "site",
          "type": "string",
          "required": false,
          "default": null,
          "description": "Restrict to a single host."
        },
        {
          "name": "exclude_site",
          "type": "string[]",
          "required": false,
          "default": null,
          "description": "Hosts to drop from results."
        },
        {
          "name": "lang",
          "type": "string",
          "required": false,
          "default": null,
          "description": "ISO language code. Also accepts `langs[]` for several."
        },
        {
          "name": "from / to",
          "type": "unix timestamp",
          "required": false,
          "default": null,
          "description": "Crawl-time window (`fetched_at`)."
        },
        {
          "name": "published_from / published_to",
          "type": "unix timestamp",
          "required": false,
          "default": null,
          "description": "Content-date window — usually the recency you actually mean."
        },
        {
          "name": "term",
          "type": "string",
          "required": false,
          "default": null,
          "description": "An exact salient-term needle that must be present."
        },
        {
          "name": "source",
          "type": "cc | delta",
          "required": false,
          "default": null,
          "description": "Crawl provenance: the batch corpus or the delta crawler."
        },
        {
          "name": "min_host_rank",
          "type": "float",
          "required": false,
          "default": null,
          "description": "Floor on host authority."
        },
        {
          "name": "min_quality",
          "type": "integer",
          "required": false,
          "default": null,
          "description": "Floor on passage quality score."
        },
        {
          "name": "min_centrality",
          "type": "float",
          "required": false,
          "default": null,
          "description": "Floor on graph centrality."
        },
        {
          "name": "min_independent_sources",
          "type": "integer",
          "required": false,
          "default": null,
          "description": "Require corroboration by N distinct hosts."
        },
        {
          "name": "content_type",
          "type": "string[]",
          "required": false,
          "default": null,
          "description": "article, news, docs, code, academic, forum, and more."
        },
        {
          "name": "authority",
          "type": "string[]",
          "required": false,
          "default": null,
          "description": "edu, gov, org, com, other."
        },
        {
          "name": "topic",
          "type": "string[]",
          "required": false,
          "default": null,
          "description": "Topic tags assigned at index time."
        },
        {
          "name": "tld",
          "type": "string[]",
          "required": false,
          "default": null,
          "description": "Top-level domains to include."
        },
        {
          "name": "safe",
          "type": "boolean",
          "required": false,
          "default": "true",
          "description": "Drops explicit content."
        },
        {
          "name": "min_words / max_words",
          "type": "integer",
          "required": false,
          "default": null,
          "description": "Passage length bounds."
        },
        {
          "name": "sort",
          "type": "string",
          "required": false,
          "default": "relevance",
          "description": "relevance, recency, host_rank, quality, published, words or centrality."
        },
        {
          "name": "collapse",
          "type": "none | host | page | story",
          "required": false,
          "default": null,
          "description": "Deduplicate results by host, page or story cluster."
        },
        {
          "name": "facets",
          "type": "boolean",
          "required": false,
          "default": "false",
          "description": "Return facet counts alongside results."
        },
        {
          "name": "fields",
          "type": "string[]",
          "required": false,
          "default": null,
          "description": "Project only the fields you need."
        },
        {
          "name": "prefer_recent / prefer_authority",
          "type": "boolean",
          "required": false,
          "default": null,
          "description": "Soft ranking preferences rather than hard filters."
        }
      ],
      "returns": "`{ vertical, routed, mode, total, results: WebHit[], facets? }`, where each `WebHit` carries url, host, title, snippet, score, published_at, content_type, authority, word_count, host_rank, quality, centrality, community_id, independent_sources and in_degree.",
      "example": "curl -H \"x-api-key: $UNLOB_API_KEY\" \\\n  \"https://api.unlob.com/search?q=rust+AND+async+-python&vertical=code&mode=hybrid&limit=5\"",
      "documentation": "https://www.unlob.com/docs/api/search"
    },
    {
      "slug": "similar",
      "method": "GET",
      "path": "/similar",
      "name": "Similar",
      "group": "search",
      "summary": "More-like-this: given a passage id, returns its semantic neighbours from the same embedding space the index was built in.",
      "requiresAuth": true,
      "mcpTool": "similar",
      "parameters": [
        {
          "name": "id",
          "type": "string",
          "required": true,
          "default": null,
          "description": "A passage id from a previous search hit."
        },
        {
          "name": "limit",
          "type": "integer",
          "required": false,
          "default": "10",
          "description": "Number of neighbours."
        },
        {
          "name": "lang",
          "type": "string",
          "required": false,
          "default": null,
          "description": "Restrict neighbours to one language."
        }
      ],
      "returns": "The same `WebHit[]` shape as `/search`.",
      "example": "curl -H \"x-api-key: $UNLOB_API_KEY\" \\\n  \"https://api.unlob.com/similar?id=p:8f2c9a&limit=10\"",
      "documentation": "https://www.unlob.com/docs/api/similar"
    },
    {
      "slug": "browse",
      "method": "GET",
      "path": "/browse",
      "name": "Browse",
      "group": "search",
      "summary": "Query-free browsing: the most recent or highest-ranked passages, optionally within a single vertical.",
      "requiresAuth": true,
      "mcpTool": "browse",
      "parameters": [
        {
          "name": "vertical",
          "type": "string",
          "required": false,
          "default": null,
          "description": "Restrict to one vertical."
        },
        {
          "name": "sort",
          "type": "recency | host_rank",
          "required": false,
          "default": "recency",
          "description": "Ordering."
        },
        {
          "name": "limit",
          "type": "integer",
          "required": false,
          "default": "10",
          "description": "Number of passages."
        },
        {
          "name": "lang",
          "type": "string",
          "required": false,
          "default": null,
          "description": "Language filter."
        }
      ],
      "returns": "The same `WebHit[]` shape as `/search`.",
      "example": "curl -H \"x-api-key: $UNLOB_API_KEY\" \\\n  \"https://api.unlob.com/browse?vertical=code&sort=recency&limit=20\"",
      "documentation": "https://www.unlob.com/docs/api/browse"
    },
    {
      "slug": "doc",
      "method": "GET",
      "path": "/doc/:id",
      "name": "Get document",
      "group": "search",
      "summary": "Fetches the full cleaned text of one passage by id — the only endpoint that returns page content.",
      "requiresAuth": true,
      "mcpTool": "get_document",
      "parameters": [
        {
          "name": "id",
          "type": "string",
          "required": true,
          "default": null,
          "description": "Passage id, as a path segment."
        }
      ],
      "returns": "`{ id, url, host, title, text, published_at, fetched_at, word_count }`",
      "example": "curl -H \"x-api-key: $UNLOB_API_KEY\" \\\n  \"https://api.unlob.com/doc/p:8f2c9a\"",
      "documentation": "https://www.unlob.com/docs/api/doc"
    },
    {
      "slug": "why-not",
      "method": "GET",
      "path": "/why_not",
      "name": "Why not",
      "group": "ops",
      "summary": "Coverage transparency: explains whether a URL is present in the index, was removed and why, or was never admitted.",
      "requiresAuth": true,
      "mcpTool": "why_not",
      "parameters": [
        {
          "name": "url",
          "type": "string",
          "required": true,
          "default": null,
          "description": "The absolute URL to explain."
        }
      ],
      "returns": "A tagged union: `present`, `removed { reason, superseded_by?, removed_at }`, or `unknown`.",
      "example": "curl -H \"x-api-key: $UNLOB_API_KEY\" \\\n  \"https://api.unlob.com/why_not?url=https://docs.rs/tokio\"",
      "documentation": "https://www.unlob.com/docs/api/why-not"
    },
    {
      "slug": "related",
      "method": "GET",
      "path": "/related",
      "name": "Related",
      "group": "graph",
      "summary": "Coverage graph traversal: the connected neighbourhood of a passage, up to k hops — the edges are what to read next.",
      "requiresAuth": true,
      "mcpTool": "related",
      "parameters": [
        {
          "name": "id",
          "type": "string",
          "required": true,
          "default": null,
          "description": "Seed passage id."
        },
        {
          "name": "hops",
          "type": "integer",
          "required": false,
          "default": "1",
          "description": "Traversal depth. Bounded breadth-first."
        },
        {
          "name": "limit",
          "type": "integer",
          "required": false,
          "default": "10",
          "description": "Maximum neighbours returned."
        }
      ],
      "returns": "Connected passages with the edge type that linked them.",
      "example": "curl -H \"x-api-key: $UNLOB_API_KEY\" \\\n  \"https://api.unlob.com/related?id=p:8f2c9a&hops=2&limit=15\"",
      "documentation": "https://www.unlob.com/docs/api/related"
    },
    {
      "slug": "corroborate",
      "method": "GET",
      "path": "/corroborate",
      "name": "Corroborate",
      "group": "graph",
      "summary": "The anti-hallucination check: how many distinct hosts independently carry a story, and which ones.",
      "requiresAuth": true,
      "mcpTool": "corroborate",
      "parameters": [
        {
          "name": "id",
          "type": "string",
          "required": true,
          "default": null,
          "description": "A passage id belonging to the story."
        },
        {
          "name": "limit",
          "type": "integer",
          "required": false,
          "default": "10",
          "description": "Maximum source groups."
        }
      ],
      "returns": "`{ story_id?, independent_sources, merged_duplicates, sources: [{ host, host_rank, passages }] }`",
      "example": "curl -H \"x-api-key: $UNLOB_API_KEY\" \\\n  \"https://api.unlob.com/corroborate?id=p:8f2c9a\"",
      "documentation": "https://www.unlob.com/docs/api/corroborate"
    },
    {
      "slug": "authorities",
      "method": "GET",
      "path": "/authorities",
      "name": "Authorities",
      "group": "graph",
      "summary": "The top passages on a topic ranked by graph centrality, so an agent can triage a field before reading into it.",
      "requiresAuth": true,
      "mcpTool": "authorities",
      "parameters": [
        {
          "name": "topic",
          "type": "string",
          "required": true,
          "default": null,
          "description": "A topic tag or entity name."
        },
        {
          "name": "limit",
          "type": "integer",
          "required": false,
          "default": "10",
          "description": "Number of passages."
        }
      ],
      "returns": "The same `WebHit[]` shape as `/search`, ordered by centrality.",
      "example": "curl -H \"x-api-key: $UNLOB_API_KEY\" \\\n  \"https://api.unlob.com/authorities?topic=technology&limit=10\"",
      "documentation": "https://www.unlob.com/docs/api/authorities"
    },
    {
      "slug": "dossier",
      "method": "GET",
      "path": "/dossier",
      "name": "Dossier",
      "group": "graph",
      "summary": "A one-hop brief on an entity: where it is mentioned, which hosts cover it, and which entities co-occur with it.",
      "requiresAuth": true,
      "mcpTool": "dossier",
      "parameters": [
        {
          "name": "entity",
          "type": "string",
          "required": true,
          "default": null,
          "description": "The entity name."
        },
        {
          "name": "limit",
          "type": "integer",
          "required": false,
          "default": "10",
          "description": "Maximum mentions, sources and related entities."
        }
      ],
      "returns": "`{ entity, mentions, top_sources: [host, count][], related_entities: [entity, count][] }`",
      "example": "curl -H \"x-api-key: $UNLOB_API_KEY\" \\\n  \"https://api.unlob.com/dossier?entity=Common+Crawl\"",
      "documentation": "https://www.unlob.com/docs/api/dossier"
    },
    {
      "slug": "path",
      "method": "GET",
      "path": "/path",
      "name": "Path",
      "group": "graph",
      "summary": "The shortest chain of edges linking two passages — reasoning-path retrieval, or connect-the-dots.",
      "requiresAuth": true,
      "mcpTool": "path",
      "parameters": [
        {
          "name": "from",
          "type": "string",
          "required": true,
          "default": null,
          "description": "Start passage id."
        },
        {
          "name": "to",
          "type": "string",
          "required": true,
          "default": null,
          "description": "End passage id."
        },
        {
          "name": "max_hops",
          "type": "integer",
          "required": false,
          "default": "4",
          "description": "Search depth ceiling."
        }
      ],
      "returns": "`{ found, hops, nodes: [{ key, kind: passage | host | story | topic | entity, hit? }] }`",
      "example": "curl -H \"x-api-key: $UNLOB_API_KEY\" \\\n  \"https://api.unlob.com/path?from=p:8f2c9a&to=p:41ab7c\"",
      "documentation": "https://www.unlob.com/docs/api/path"
    },
    {
      "slug": "assemble-context",
      "method": "GET",
      "path": "/assemble_context",
      "name": "Assemble context",
      "group": "graph",
      "summary": "GraphRAG as a single call: a corroborated, story-deduplicated, trust-ranked context pack fitted to a token budget, with a reason attached to every passage.",
      "requiresAuth": true,
      "mcpTool": "assemble_context",
      "parameters": [
        {
          "name": "q",
          "type": "string",
          "required": true,
          "default": null,
          "description": "The question to assemble context for."
        },
        {
          "name": "budget",
          "type": "integer",
          "required": false,
          "default": "4000",
          "description": "Token budget for the pack."
        },
        {
          "name": "lang",
          "type": "string",
          "required": false,
          "default": null,
          "description": "Language restriction."
        },
        {
          "name": "min_independent_sources",
          "type": "integer",
          "required": false,
          "default": null,
          "description": "Require corroboration before inclusion."
        }
      ],
      "returns": "`{ query, token_budget, estimated_tokens, items: [{ hit, reason }] }`",
      "example": "curl -H \"x-api-key: $UNLOB_API_KEY\" \\\n  \"https://api.unlob.com/assemble_context?q=who+funds+independent+web+indexes&budget=4000\"",
      "documentation": "https://www.unlob.com/docs/api/assemble-context"
    },
    {
      "slug": "describe",
      "method": "GET",
      "path": "/describe",
      "name": "Describe",
      "group": "ops",
      "summary": "A self-describing capability catalog: the filter grammar and every controlled vocabulary, so an agent can discover the query surface instead of guessing it.",
      "requiresAuth": false,
      "mcpTool": null,
      "parameters": [],
      "returns": "The filter grammar plus every controlled vocabulary as JSON.",
      "example": "curl \"https://api.unlob.com/describe\"",
      "documentation": "https://www.unlob.com/docs/api/describe"
    },
    {
      "slug": "account",
      "method": "GET",
      "path": "/account",
      "name": "Account",
      "group": "ops",
      "summary": "Your tenant’s current plan, usage against quota and remaining allowance for this billing period.",
      "requiresAuth": true,
      "mcpTool": null,
      "parameters": [],
      "returns": "`{ plan, monthly_quota, usage_this_period, quota_remaining, rate_per_min, period_start_unix }`",
      "example": "curl -H \"x-api-key: $UNLOB_API_KEY\" \"https://api.unlob.com/account\"",
      "documentation": "https://www.unlob.com/docs/api/account"
    },
    {
      "slug": "healthz",
      "method": "GET",
      "path": "/healthz",
      "name": "Health",
      "group": "ops",
      "summary": "Unauthenticated liveness probe. Returns 200 while the process is up.",
      "requiresAuth": false,
      "mcpTool": null,
      "parameters": [],
      "returns": "`ok`",
      "example": "curl \"https://api.unlob.com/healthz\"",
      "documentation": "https://www.unlob.com/docs/api/healthz"
    },
    {
      "slug": "readyz",
      "method": "GET",
      "path": "/readyz",
      "name": "Readiness",
      "group": "ops",
      "summary": "Unauthenticated readiness probe: 200 once the index is loaded and non-empty, 503 while it is not.",
      "requiresAuth": false,
      "mcpTool": null,
      "parameters": [],
      "returns": "200 when ready, 503 with a reason when not.",
      "example": "curl -i \"https://api.unlob.com/readyz\"",
      "documentation": "https://www.unlob.com/docs/api/readyz"
    },
    {
      "slug": "metrics",
      "method": "GET",
      "path": "/metrics",
      "name": "Metrics",
      "group": "ops",
      "summary": "Prometheus metrics: per-status request counters, a latency histogram and an in-flight gauge.",
      "requiresAuth": false,
      "mcpTool": null,
      "parameters": [],
      "returns": "Prometheus text format.",
      "example": "curl \"https://api.unlob.com/metrics\"",
      "documentation": "https://www.unlob.com/docs/api/metrics"
    }
  ]
}