HTTP API
This reference is generated at build time from FastAPI's OpenAPI document. Its
endpoint inventory, parameters, request and response types, validation
constraints, status codes, and component schemas come directly from route
metadata, docstrings, and type hints.
Bearer authentication is required unless an operation is marked public.
Write-scoped routes are also marked 🔒. See
Authentication for token configuration and scope
semantics. The server binds to 127.0.0.1:8000 by default.
The ingest workflow also has a task-oriented contract in the
Upstream ingest API ; that guide adds retry,
idempotency, and integration advice around the generated wire reference below.
Endpoint map
POST /v1/pages Ingest a page 🔒
POST /v1/pages/batch Ingest up to 100 pages 🔒
POST /v1/pages/status/batch Fetch status for up to 500 pages
GET /v1/pages/{page_id} Fetch a page
GET /v1/pages/{page_id}/chunks List a page's indexed chunks
GET /v1/pages/{page_id}/status Page indexing status
GET /v1/jobs List jobs
POST /v1/jobs/retry Retry dead jobs in bulk 🔒
POST /v1/jobs/{job_id}/retry Retry a dead job 🔒
POST /v1/search Search the reading history
POST /v1/search/batch Search many queries in one call
GET /v1/pages/{page_id}/similar Pages similar to a page
POST /v1/feedback Record relevance feedback
POST /v1/forget Purge and blacklist a URL or domain 🔒
GET /v1/blacklist List blacklist rules
DELETE /v1/blacklist/{blacklist_id} Remove a blacklist rule 🔒
GET /v1/clusters List reading-topic clusters
GET /v1/clusters/runs List clustering runs
GET /v1/clusters/projection Read a run's two-dimensional page projection
GET /v1/clusters/{cluster_id} A cluster's label, keywords, and member pages
POST /v1/clusters/recompute Trigger a cluster run 🔒
GET /v1/entities/{ref} Look up an entity
GET /v1/pages/{page_id}/entities Entities mentioned on a page
POST /v1/entities/merges/{merge_id}/undo Undo an entity merge (LIFO only) 🔒
GET /v1/models/{model_id}/backfill Read model backfill progress
POST /v1/models/{model_id}/backfill Estimate or start a backfill 🔒
GET /v1/models List embedding models
POST /v1/models Register an embedding model 🔒
POST /v1/models/{model_id}/activate Make this the active search model 🔒
DELETE /v1/models/{model_id} Retire a model and drop its vector space 🔒
POST /v1/compare Compare embedding models on one query
GET /v1/watches List watches
POST /v1/watches Create a watch 🔒
GET /v1/watches/{watch_id} Get a watch
PATCH /v1/watches/{watch_id} Update a watch 🔒
DELETE /v1/watches/{watch_id} Delete a watch 🔒
POST /v1/watches/{watch_id}/run Poll a watch now 🔒
GET /v1/events Stream job status changes (SSE)
GET /v1/admin/metrics/timeseries Read metric history
GET /v1/admin/metrics/summary Typed operational canaries
GET /v1/admin/query-log List query-log runs
GET /v1/admin/query-log/{query_id} Read one query-log run
POST /v1/admin/eval/score Score logged runs
POST /v1/admin/eval/replay Enqueue a live eval replay 🔒
GET /v1/admin/eval/replay/{job_id} Poll a live eval replay
GET /v1/admin/config Read effective configuration
GET /v1/admin/mcp Inspect mounted MCP tools
GET /v1/whoami Identify caller
GET /metrics Read Prometheus metrics
GET /healthz Check process liveness
GET /readyz Check service readiness
Endpoint details
Pages
POST /v1/pages — Ingest a page 🔒
Add a page the user read to the index. body_extracted and body_html are mutually exclusive; when neither is given the URL is fetched asynchronously. Known canonical URLs record a revisit instead.
Operation ID: add_page · Required scope: write
Request body
Required.
Responses
POST /v1/pages/batch — Ingest up to 100 pages 🔒
Validate and ingest each page independently. Results preserve input order; malformed or blacklisted items do not prevent other items.
Operation ID: add_pages_batch · Required scope: write
Request body
Required.
Responses
POST /v1/pages/status/batch — Fetch status for up to 500 pages
Return one status per distinct requested page id. Unknown ids are reported with found=false instead of failing the batch.
Operation ID: page_status_batch · Required scope: read
Request body
Required.
Responses
GET /v1/pages/{page_id} — Fetch a page
Return the full stored body text and metadata of one page from the user's reading history.
Operation ID: get_page · Required scope: read
Parameters
Name
In
Type
Required
Description and constraints
page_id
path
string
yes
—
Responses
GET /v1/pages/{page_id}/chunks — List a page's indexed chunks
Return chunk text and body offsets in ordinal order.
Operation ID: get_page_chunks · Required scope: read
Parameters
Name
In
Type
Required
Description and constraints
page_id
path
string
yes
—
Responses
GET /v1/pages/{page_id}/status — Page indexing status
Return the indexing lifecycle status of a page.
Operation ID: page_status · Required scope: read
Parameters
Name
In
Type
Required
Description and constraints
page_id
path
string
yes
—
Responses
Jobs
GET /v1/jobs — List jobs
List jobs newest first, optionally filtered by status and kind.
status_filter is a deprecated compatibility alias for status; a
request that supplies both is rejected.
Operation ID: list_jobs · Required scope: read
Parameters
Name
In
Type
Required
Description and constraints
status
query
JobStatus | null
no
—
status_filter
query
JobStatus | null
no
Deprecated
kind
query
JobKind | null
no
—
limit
query
integer
no
Default: 100; Minimum: 1; Maximum: 1000
Responses
POST /v1/jobs/retry — Retry dead jobs in bulk 🔒
Retry dead jobs either by explicit job_ids (up to 500, deduped, results in input order) or by selector (all dead jobs, optionally filtered by kind, up to limit). Non-dead jobs are reported as skipped and unknown ids as not_found; the call is idempotent — a second selector call finds nothing left to retry. Always returns 200.
Operation ID: retry_jobs_batch · Required scope: write
Request body
Required.
Responses
POST /v1/jobs/{job_id}/retry — Retry a dead job 🔒
Reset a dead job to pending and re-enqueue it; other states return 409.
Retrying an index job also resets its page from dead back to
queued, so page status tracks the re-enqueued work.
Operation ID: retry_job · Required scope: write
Parameters
Name
In
Type
Required
Description and constraints
job_id
path
string
yes
—
Responses
Search
POST /v1/search — Search the reading history
Hybrid semantic + keyword search over pages the user has read. Returns grounded passages from the user's own reading history. Contains no information the user has not read. Returns an empty result when nothing matches. An entity filter that resolves to no known entity returns 404 so a bad reference is distinguishable from a genuine zero.
Operation ID: search · Required scope: read
Request body
Required.
Responses
POST /v1/search/batch — Search many queries in one call
Run up to 20 queries sequentially with shared parameters (sequential on purpose: it respects embedding provider rate limits, like model comparison does). Each item gets its own query_id and query-log row, so feedback and evaluation join per query. Per-item failures are reported inline as outcome='error' items; the call itself stays 200.
Operation ID: search_batch · Required scope: read
Request body
Required.
Responses
GET /v1/pages/{page_id}/similar — Pages similar to a page
Rank other pages from the user's reading history by similarity to this one. Returns grounded results from the user's own reading history only.
Operation ID: similar_to · Required scope: read
Parameters
Name
In
Type
Required
Description and constraints
page_id
path
string
yes
—
mediation
query
Mediation
no
Default: "vector"
k
query
integer
no
Default: 10; Minimum: 1; Maximum: 50
Responses
POST /v1/feedback — Record relevance feedback
Append feedback; unknown query_ids are accepted (eval join drops them).
Operation ID: record_feedback · Required scope: read
Request body
Required.
Responses
Status
Description
Body
202
Successful Response
application/json: object[string, string]
422
Validation Error
application/json: HTTPValidationError
Forget
POST /v1/forget — Purge and blacklist a URL or domain 🔒
Permanently remove matching pages from the index and blacklist the pattern so future ingests are rejected. This deletes user data; removal of the blacklist rule later does not restore content.
Operation ID: forget · Required scope: write
Request body
Required.
Responses
GET /v1/blacklist — List blacklist rules
All rules, newest first.
Operation ID: list_blacklist · Required scope: read
Responses
DELETE /v1/blacklist/{blacklist_id} — Remove a blacklist rule 🔒
Future ingests are allowed again; purged content stays purged.
Operation ID: unblacklist · Required scope: write
Parameters
Name
In
Type
Required
Description and constraints
blacklist_id
path
string
yes
—
Responses
Status
Description
Body
204
Successful Response
—
422
Validation Error
application/json: HTTPValidationError
Clusters
GET /v1/clusters — List reading-topic clusters
Topic clusters discovered over the user's reading history. Returns grounded results derived only from pages the user has read.
Operation ID: list_clusters · Required scope: read
Parameters
Name
In
Type
Required
Description and constraints
include_tombstoned
query
boolean
no
Default: false
Responses
GET /v1/clusters/runs — List clustering runs
Return persisted clustering history newest first.
Operation ID: list_cluster_runs · Required scope: read
Parameters
Name
In
Type
Required
Description and constraints
limit
query
integer
no
Default: 100; Minimum: 1; Maximum: 1000
Responses
GET /v1/clusters/projection — Read a run's two-dimensional page projection
Return page coordinates for a persisted clustering run.
Operation ID: cluster_projection · Required scope: read
Parameters
Name
In
Type
Required
Description and constraints
run_id
query
string
yes
Minimum Length: 1
Responses
GET /v1/clusters/{cluster_id} — A cluster's label, keywords, and member pages
Member pages of one topic cluster from the user's reading history. Tombstoned clusters remain resolvable by id.
Operation ID: cluster_pages · Required scope: read
Parameters
Name
In
Type
Required
Description and constraints
cluster_id
path
string
yes
—
Responses
POST /v1/clusters/recompute — Trigger a cluster run 🔒
Enqueue a manual run; 409 when one is already in flight.
Operation ID: recompute_clusters · Required scope: write
Responses
Entities
GET /v1/entities/{ref} — Look up an entity
Resolve an entity by id, canonical form, or alias (references survive merges). Returns aliases and the user's pages mentioning it — grounded in the reading history only.
Operation ID: entities · Required scope: read
Parameters
Name
In
Type
Required
Description and constraints
ref
path
string
yes
—
Responses
GET /v1/pages/{page_id}/entities — Entities mentioned on a page
Entities linked to one page.
Operation ID: page_entities · Required scope: read
Parameters
Name
In
Type
Required
Description and constraints
page_id
path
string
yes
—
Responses
POST /v1/entities/merges/{merge_id}/undo — Undo an entity merge (LIFO only) 🔒
Restore a merged entity from its snapshot.
Operation ID: undo_entity_merge · Required scope: write
Parameters
Name
In
Type
Required
Description and constraints
merge_id
path
string
yes
—
Responses
Models
GET /v1/models/{model_id}/backfill — Read model backfill progress
Return durable progress for a model's corpus backfill.
Operation ID: get_model_backfill · Required scope: read
Parameters
Name
In
Type
Required
Description and constraints
model_id
path
string
yes
—
Responses
POST /v1/models/{model_id}/backfill — Estimate or start a backfill 🔒
confirm=false returns an exact dry-run estimate (chunk token counts are stored); confirm=true starts the durable, resumable backfill.
Operation ID: backfill_model · Required scope: write
Parameters
Name
In
Type
Required
Description and constraints
model_id
path
string
yes
—
Request body
Required.
Responses
GET /v1/models — List embedding models
All registered models.
Operation ID: list_models_api · Required scope: read
Responses
POST /v1/models — Register an embedding model 🔒
Register (not active, no vectors yet). Rejected below the chunk budget.
Operation ID: register_model · Required scope: write
Request body
Required.
Responses
POST /v1/models/{model_id}/activate — Make this the active search model 🔒
Atomic flip; only ready models can be activated.
Operation ID: activate_model · Required scope: write
Parameters
Name
In
Type
Required
Description and constraints
model_id
path
string
yes
—
Responses
DELETE /v1/models/{model_id} — Retire a model and drop its vector space 🔒
409 when active; drops the vector space and page vectors.
Operation ID: retire_model · Required scope: write
Parameters
Name
In
Type
Required
Description and constraints
model_id
path
string
yes
—
Responses
Status
Description
Body
204
Successful Response
—
422
Validation Error
application/json: HTTPValidationError
Compare
POST /v1/compare — Compare embedding models on one query
Runs the full retrieval pipeline once per model; the sparse arm and reranker are identical across arms, so the delta isolates the embedder. Returns per-model rankings over the user's reading history plus agreement statistics (Jaccard@k, RBO, Kendall's tau).
Operation ID: compare · Required scope: read
Request body
Required.
Responses
Watches
GET /v1/watches — List watches
All watches with their schedules and last-poll health (status, error, item count).
Operation ID: list_watches · Required scope: read
Responses
POST /v1/watches — Create a watch 🔒
Register a URL to poll on a schedule (default every 24 hours). Each poll discovers the source's current item URLs and ingests the new ones, so they become searchable. Kind 'rss' polls an RSS/Atom feed; kind 'youtube' polls a YouTube playlist or channel and ingests each video's transcript (single videos go to add_page instead); kind 'podcast' polls a podcast RSS feed and ingests each episode's audio enclosure as a local Whisper transcript (requires a transcription extra). Already-indexed and blacklisted items are skipped automatically. The first poll runs within a minute of creation.
Operation ID: create_watch · Required scope: write
Request body
Required.
Responses
GET /v1/watches/{watch_id} — Get a watch
One watch with its schedule and last-poll health.
Operation ID: get_watch · Required scope: read
Parameters
Name
In
Type
Required
Description and constraints
watch_id
path
string
yes
—
Responses
PATCH /v1/watches/{watch_id} — Update a watch 🔒
Partially update a watch: pause/resume with 'enabled', change the poll interval, title, or per-kind config. Omitted fields are left unchanged; the URL is immutable (delete and recreate instead). Changing the interval reschedules the next poll from the last run.
Operation ID: update_watch · Required scope: write
Parameters
Name
In
Type
Required
Description and constraints
watch_id
path
string
yes
—
Request body
Required.
Responses
DELETE /v1/watches/{watch_id} — Delete a watch 🔒
Stop polling this source. Pages already ingested by the watch stay indexed; use forget to remove content.
Operation ID: delete_watch · Required scope: write
Parameters
Name
In
Type
Required
Description and constraints
watch_id
path
string
yes
—
Responses
Status
Description
Body
204
Successful Response
—
422
Validation Error
application/json: HTTPValidationError
POST /v1/watches/{watch_id}/run — Poll a watch now 🔒
Enqueue an immediate poll instead of waiting for the schedule; the next scheduled poll moves to one interval from now. Returns the poll job id; track it via the jobs API.
Operation ID: run_watch · Required scope: write
Parameters
Name
In
Type
Required
Description and constraints
watch_id
path
string
yes
—
Responses
Events
GET /v1/events — Stream job status changes (SSE)
A text/event-stream of job ledger transitions. Opens with a snapshot event carrying the current job list (same shape as GET /v1/jobs), then one job event per status change (pending, running, done, failed, dead), with : keep-alive comments between events. Returns 503 when the subscriber limit is reached. Authenticate with the normal bearer header (fetch-based SSE); query-string tokens are not supported.
Operation ID: stream_events · Required scope: read
Responses
Status
Description
Body
200
Successful Response
application/json: object
Admin
GET /v1/admin/metrics/timeseries — Read metric history
Read historical rollups plus current gauge values for one metric.
Operation ID: admin_metrics_timeseries · Required scope: read
Parameters
Name
In
Type
Required
Description and constraints
metric
query
string
yes
Minimum Length: 1
since
query
string (date-time) | null
no
—
step
query
number
no
Default: 60.0; Exclusive Minimum: 0
Responses
GET /v1/admin/metrics/summary — Typed operational canaries
One JSON snapshot of operational health: job-ledger counts, vector tombstone backlog, dropped observability rows, provider error counters, search latency quantiles, and circuit breaker states. Counter-derived fields are process-lifetime totals that reset on restart; since bounds the latency window only.
Operation ID: admin_metrics_summary · Required scope: read
Parameters
Name
In
Type
Required
Description and constraints
since
query
string (date-time) | null
no
—
Responses
GET /v1/admin/query-log — List query-log runs
List retrieval traces newest first, optionally filtered by time and kind.
Each trace includes candidate, dense, sparse, and final hit sets, per-stage
timing, and the latest relevance feedback. The default limit is 100 and the
maximum is 1,000.
Operation ID: admin_query_log · Required scope: read
Parameters
Name
In
Type
Required
Description and constraints
since
query
string (date-time) | null
no
—
limit
query
integer
no
Default: 100; Minimum: 1; Maximum: 1000
kind
query
"search" | "compare_arm" | null
no
—
Responses
GET /v1/admin/query-log/{query_id} — Read one query-log run
Return one full retrieval trace with rankings, timing, and feedback.
Operation ID: admin_query_log_detail · Required scope: read
Parameters
Name
In
Type
Required
Description and constraints
query_id
path
string
yes
—
Responses
POST /v1/admin/eval/score — Score logged runs
Score logged rankings synchronously without calling external providers.
Operation ID: admin_eval_score · Required scope: read
Request body
Required.
Responses
POST /v1/admin/eval/replay — Enqueue a live eval replay 🔒
Enqueue a durable two-arm replay that may call paid model providers.
The response is a 202 with a job ID and result URL. Polling the result needs
only read scope; the report or failure survives process restarts.
Operation ID: admin_eval_replay · Required scope: write
Request body
Required.
Responses
GET /v1/admin/eval/replay/{job_id} — Poll a live eval replay
Read durable replay status, its completed report, or terminal failure.
Operation ID: admin_eval_replay_result · Required scope: read
Parameters
Name
In
Type
Required
Description and constraints
job_id
path
string
yes
—
Responses
GET /v1/admin/config — Read effective configuration
Return effective settings with secrets redacted recursively.
Every setting is marked boot_only because runtime mutation is not
supported.
Operation ID: admin_config · Required scope: read
Responses
Return actual mounted tool metadata and mutating-tool visibility.
Operation ID: admin_mcp · Required scope: read
Responses
Status
Description
Body
200
Successful Response
application/json: McpAdminResponse
Auth
GET /v1/whoami — Identify caller
Return the authenticated token name and its effective scopes.
Operation ID: whoami · Required scope: read
Responses
Status
Description
Body
200
Successful Response
application/json: WhoAmIResponse
Health
GET /metrics — Read Prometheus metrics
Return the Prometheus text exposition for authenticated scrapers.
Operation ID: metrics · Required scope: read
Responses
Status
Description
Body
200
Prometheus text exposition.
text/plain: string
GET /healthz — Check process liveness
Return success when the API process is running. No authentication.
Operation ID: healthz · Required scope: public
Responses
Status
Description
Body
200
Successful Response
application/json: object[string, string]
GET /readyz — Check service readiness
Check that the metadata store is reachable and an embedding model is active. Returns 503 until both conditions hold. No authentication.
Operation ID: readyz · Required scope: public
Responses
Status
Description
Body
200
Successful Response
application/json: object
503
A required dependency is unavailable.
—
Schemas
AdminConfigResponse
Field
Type
Required
Description and constraints
settings
object
yes
—
mutability
object[string, "boot_only"]
yes
—
BackfillEstimateResponse
Dry-run estimate (confirm=false).
Field
Type
Required
Description and constraints
model_id
string
yes
—
n_chunks
integer
yes
—
total_tokens
integer
yes
—
est_cost_usd
number | null
yes
—
est_duration_s
number | null
yes
—
confirm_required
true
no
Default: true
BackfillRequest
POST /v1/models/{id}/backfill body.
Field
Type
Required
Description and constraints
confirm
boolean
no
Default: false
BackfillStartedResponse
202-style acknowledgement (confirm=true).
Field
Type
Required
Description and constraints
model_id
string
yes
—
status
"backfilling"
no
Default: "backfilling"
BlacklistEntry
One blacklist rule.
Field
Type
Required
Description and constraints
id
string
yes
—
pattern
string
yes
—
kind
BlacklistKind
yes
—
reason
string | null
yes
—
created_at
string (date-time)
yes
—
BlacklistKind
Whether a blacklist rule matches a URL exactly or a domain suffix.
Type: "url" | "domain"
BlacklistResponse
GET /v1/blacklist response.
Field
Type
Required
Description and constraints
entries
array<BlacklistEntry >
yes
—
BlacklistedResponse
403: URL matches a blacklist rule.
Field
Type
Required
Description and constraints
error
"blacklisted"
no
Default: "blacklisted"
pattern
string
yes
—
BreakerStateSummary
Field
Type
Required
Description and constraints
name
string
yes
—
state
"closed" | "half_open" | "open"
yes
—
ChunkResult
One matched chunk, whole text.
Field
Type
Required
Description and constraints
chunk_id
string
yes
—
ordinal
integer
yes
—
text
string
yes
—
score
number
yes
—
ClusterDetailResponse
GET /v1/clusters/{id} response.
ClusterListResponse
GET /v1/clusters response.
Field
Type
Required
Description and constraints
clusters
array<ClusterSummary >
yes
—
ClusterMemberPage
A page inside a cluster.
Field
Type
Required
Description and constraints
page_id
string
yes
—
canonical_url
string
yes
—
title
string | null
yes
—
probability
number | null
yes
—
ClusterProjectionPointResponse
A page point in a clustering run's display projection.
Field
Type
Required
Description and constraints
page_id
string
yes
—
x
number
yes
—
y
number
yes
—
cluster_id
string | null
yes
—
ClusterProjectionResponse
GET /v1/clusters/projection.
ClusterRef
Cluster membership shown on a result (populated from M4).
Field
Type
Required
Description and constraints
id
string
yes
—
label
string | null
yes
—
ClusterRunResponse
One persisted clustering run.
Field
Type
Required
Description and constraints
id
string
yes
—
trigger
string
yes
—
algorithm
string
yes
—
params
object[string, JsonValue ]
yes
—
started_at
string (date-time)
yes
—
finished_at
string (date-time) | null
yes
—
duration_ms
integer | null
yes
—
n_pages
integer | null
yes
—
n_clusters
integer | null
yes
—
n_noise
integer | null
yes
—
ClusterRunsResponse
GET /v1/clusters/runs.
ClusterSummary
One cluster.
Field
Type
Required
Description and constraints
id
string
yes
—
label
string | null
yes
—
keywords
array<string>
yes
—
size
integer
yes
—
tombstoned
boolean
no
Default: false
projection_x
number | null
no
—
projection_y
number | null
no
—
CompareAgreement
Agreement stats for one model pair.
Field
Type
Required
Description and constraints
model_a
string
yes
—
model_b
string
yes
—
jaccard_at_k
number
yes
—
rbo
number
yes
—
kendall_tau
number | null
yes
—
intersection_size
integer
yes
—
CompareModelRun
One model's ranking.
Field
Type
Required
Description and constraints
model
string
yes
—
results
array<ComparedPage >
yes
—
CompareRequest
POST /v1/compare body.
Field
Type
Required
Description and constraints
query
string
yes
Minimum Length: 1; Maximum Length: 4000
models
array<string>
yes
Minimum Items: 2; Maximum Items: 5
k
integer
no
Default: 10; Minimum: 1.0; Maximum: 100.0
candidates
integer
no
Default: 100; Minimum: 1.0; Maximum: 1000.0
rerank
boolean
no
Default: true
CompareResponse
POST /v1/compare response.
Field
Type
Required
Description and constraints
compare_id
string
yes
—
query
string
yes
—
runs
array<CompareModelRun >
yes
—
agreement
array<CompareAgreement >
yes
—
ComparedPage
One ranked page in a compare arm.
Field
Type
Required
Description and constraints
page_id
string
yes
—
canonical_url
string
yes
—
title
string | null
yes
—
score
number
yes
—
CreateWatchRequest
POST /v1/watches body.
Field
Type
Required
Description and constraints
url
string
yes
—
kind
WatchKind
no
Default: "rss"
title
string | null
no
—
interval_hours
integer | null
no
—
enabled
boolean
no
Default: true
config
object[string, string] | null
no
—
EntityDetailResponse
GET /v1/entities/{ref} response.
Field
Type
Required
Description and constraints
entity
EntitySummary
yes
—
aliases
array<string>
yes
—
page_ids
array<string>
yes
—
EntitySummary
One canonical entity.
Field
Type
Required
Description and constraints
id
string
yes
—
canonical_form
string
yes
—
type
string
yes
—
mention_count
integer
yes
—
page_count
integer
yes
—
idf
number | null
yes
—
EvalReplayAcceptedResponse
Field
Type
Required
Description and constraints
job_id
string
yes
—
result_url
string
yes
—
EvalReplayRequest
Field
Type
Required
Description and constraints
model_a
string | null
no
—
model_b
string | null
no
—
rerank_a
boolean
no
Default: true
rerank_b
boolean
no
Default: true
k
integer
no
Default: 10; Minimum: 1.0; Maximum: 1000.0
candidates
integer
no
Default: 100; Minimum: 1.0; Maximum: 10000.0
limit
integer | null
no
—
EvalReplayResultResponse
Field
Type
Required
Description and constraints
job_id
string
yes
—
status
JobStatus
yes
—
report
object | null
no
—
error
string | null
no
—
EvalScoreRequest
Field
Type
Required
Description and constraints
k
integer
no
Default: 10; Minimum: 1.0; Maximum: 1000.0
since
string (date-time) | null
no
—
model
string | null
no
—
FeatureStatus
Status of an asynchronous enrichment feature for a page.
Field
Type
Required
Description and constraints
status
JobStatus | "not_queued" | null
no
—
last_error
string | null
no
—
FeedbackRequest
POST /v1/feedback body.
Field
Type
Required
Description and constraints
query_id
string
yes
—
page_id
string
yes
—
relevant
boolean
yes
—
ForgetRequest
POST /v1/forget body: exactly one of url/domain.
Field
Type
Required
Description and constraints
url
string | null
no
—
domain
string | null
no
—
reason
string | null
no
—
ForgetResponse
POST /v1/forget response.
Field
Type
Required
Description and constraints
blacklist_id
string
yes
—
pattern
string
yes
—
kind
BlacklistKind
yes
—
pages_purged
integer
yes
—
vector_deletes_queued
integer
yes
—
HTTPValidationError
Field
Type
Required
Description and constraints
detail
array<ValidationError >
no
—
IngestAcceptedResponse
202: new page queued.
Field
Type
Required
Description and constraints
page_id
string
yes
—
status
"queued"
no
Default: "queued"
IngestBatchAcceptedResult
A newly queued item in an ingest batch.
Field
Type
Required
Description and constraints
page_id
string
yes
—
status
"queued"
no
Default: "queued"
index
integer
yes
—
outcome
"accepted"
no
Default: "accepted"
IngestBatchBlacklistedResult
A blacklisted item in an ingest batch.
Field
Type
Required
Description and constraints
error
"blacklisted"
no
Default: "blacklisted"
pattern
string
yes
—
index
integer
yes
—
outcome
"blacklisted"
no
Default: "blacklisted"
IngestBatchRejectedResult
An independently invalid item in an ingest batch.
Field
Type
Required
Description and constraints
index
integer
yes
—
outcome
"rejected"
no
Default: "rejected"
detail
string
yes
—
IngestBatchRequest
POST /v1/pages/batch envelope.
Items remain unvalidated here so one malformed page does not reject the
otherwise valid envelope. The route validates each item independently.
Field
Type
Required
Description and constraints
pages
array<object>
yes
Minimum Items: 1; Maximum Items: 100
IngestBatchResponse
POST /v1/pages/batch response in input order.
IngestBatchRevisitResult
A revisit item in an ingest batch.
Field
Type
Required
Description and constraints
page_id
string
yes
—
status
PageStatus
yes
—
revisit
true
no
Default: true
content_hash_differs
boolean
no
Default: false
index
integer
yes
—
outcome
"revisit"
no
Default: "revisit"
POST /v1/pages body.
Field
Type
Required
Description and constraints
url
string
yes
—
title
string | null
no
—
body_extracted
string | null
no
—
body_html
string | null
no
—
fetched_at
string (date-time) | null
no
—
source
string | null
no
—
metadata
object[string, JsonValue ] | null
no
—
IngestRevisitResponse
200: canonical URL already known.
Field
Type
Required
Description and constraints
page_id
string
yes
—
status
PageStatus
yes
—
revisit
true
no
Default: true
content_hash_differs
boolean
no
Default: false
JobKind
Kinds of durable jobs the queue executes.
Type: "index_page" | "fetch_and_index" | "extract_entities" | "backfill_model" | "cluster" | "label_clusters" | "canonicalize_entities" | "purge_vectors" | "eval_replay" | "poll_watch"
JobListResponse
GET /v1/jobs.
Field
Type
Required
Description and constraints
jobs
array<JobResponse >
yes
—
JobResponse
Job ledger row (admin surface).
Field
Type
Required
Description and constraints
job_id
string
yes
—
kind
string
yes
—
status
JobStatus
yes
—
attempts
integer
yes
—
max_attempts
integer
yes
—
last_error
string | null
yes
—
created_at
string (date-time)
yes
—
updated_at
string (date-time)
yes
—
JobRetryBatchMissingResult
An unknown job id.
Field
Type
Required
Description and constraints
job_id
string
yes
—
outcome
"not_found"
no
Default: "not_found"
JobRetryBatchRequest
POST /v1/jobs/retry body: explicit ids or a dead-job selector.
Field
Type
Required
Description and constraints
status
"dead"
no
Default: "dead"
job_ids
array<string> | null
no
—
kind
JobKind | null
no
—
limit
integer
no
Default: 100; Minimum: 1.0; Maximum: 500.0
JobRetryBatchResponse
POST /v1/jobs/retry response in input/selection order.
JobRetryBatchRetriedResult
A job that was reset to pending and re-enqueued.
Field
Type
Required
Description and constraints
job_id
string
yes
—
kind
string
yes
—
status
JobStatus
yes
—
attempts
integer
yes
—
max_attempts
integer
yes
—
last_error
string | null
yes
—
created_at
string (date-time)
yes
—
updated_at
string (date-time)
yes
—
outcome
"retried"
no
Default: "retried"
JobRetryBatchSkippedResult
A job skipped because it is not dead.
Field
Type
Required
Description and constraints
job_id
string
yes
—
status
JobStatus
yes
—
outcome
"skipped"
no
Default: "skipped"
detail
string
yes
—
JobStatus
Ledger status of a durable job.
Type: "pending" | "running" | "done" | "failed" | "dead"
JobsSummary
Field
Type
Required
Description and constraints
by_status
object[string, integer]
yes
—
queue_depth
integer
yes
—
dead
integer
yes
—
failures_by_kind
object[string, integer]
yes
—
JsonValue
Type: object
LoggedHitResponse
Field
Type
Required
Description and constraints
chunk_id
string
yes
—
page_id
string
yes
—
score
number
yes
—
Field
Type
Required
Description and constraints
page_id
string
yes
—
score
number
yes
—
rank
integer
yes
—
McpAdminResponse
Field
Type
Required
Description and constraints
tools
array<McpToolResponse >
yes
—
enable_mutating_tools
boolean
yes
—
Field
Type
Required
Description and constraints
name
string
yes
—
description
string | null
no
—
inputSchema
object
no
—
What mediates 'similar': vectors, cluster co-membership, or entities.
Type: "vector" | "cluster" | "entity"
MetricPointResponse
Field
Type
Required
Description and constraints
ts
string (date-time)
yes
—
value
number
yes
—
MetricSeriesResponse
Field
Type
Required
Description and constraints
sample
string
yes
—
labels
object[string, string]
yes
—
metric_type
string
yes
—
points
array<MetricPointResponse >
yes
—
MetricsSummaryResponse
Field
Type
Required
Description and constraints
generated_at
string (date-time)
yes
—
tombstones
TombstoneBacklogSummary
yes
—
jobs
JobsSummary
yes
—
query_log_dropped_rows
integer
yes
—
embedding_errors_by_provider
object[string, integer]
yes
—
rerank_degraded_total
integer
yes
—
search_latency
SearchLatencySummary | null
yes
—
breakers
array<BreakerStateSummary >
yes
—
MetricsTimeseriesResponse
ModelBackfillResponse
GET /v1/models/{id}/backfill.
Field
Type
Required
Description and constraints
model_id
string
yes
—
status
"not_started" | "running" | "complete" | "failed"
yes
—
total_chunks
integer
yes
—
embedded_chunks
integer
yes
—
total_tokens
integer
yes
—
cursor_page_id
string | null
yes
—
started_at
string (date-time) | null
yes
—
updated_at
string (date-time) | null
yes
—
finished_at
string (date-time) | null
yes
—
last_error
string | null
yes
—
ModelInfo
One registered embedding model.
Field
Type
Required
Description and constraints
id
string
yes
—
provider
string
yes
—
model_name
string
yes
—
dim
integer
yes
—
max_input_tokens
integer
yes
—
is_active
boolean
yes
—
status
string
yes
—
ModelListResponse
GET /v1/models response.
Field
Type
Required
Description and constraints
models
array<ModelInfo >
yes
—
ModelReport
Mean metrics over one model's scored runs.
Field
Type
Required
Description and constraints
model
string
yes
—
queries
integer
yes
—
ndcg
number
yes
—
reciprocal_rank
number
yes
—
recall
number
yes
—
recall_candidates
number
yes
—
rerank_lift
number | null
yes
—
PageChunkResponse
One stored chunk with its position in the page body.
Field
Type
Required
Description and constraints
chunk_id
string
yes
—
ordinal
integer
yes
—
text
string
yes
—
token_count
integer
yes
—
char_start
integer
yes
—
char_end
integer
yes
—
section_title
string | null
no
—
section_start_s
number | null
no
—
PageChunksResponse
GET /v1/pages/{id}/chunks.
Field
Type
Required
Description and constraints
page_id
string
yes
—
chunks
array<PageChunkResponse >
yes
—
PageEntitiesResponse
GET /v1/pages/{id}/entities response.
Field
Type
Required
Description and constraints
page_id
string
yes
—
entities
array<EntitySummary >
yes
—
GET /v1/pages/{id}.
Field
Type
Required
Description and constraints
page_id
string
yes
—
canonical_url
string
yes
—
original_url
string
yes
—
domain
string
yes
—
title
string | null
yes
—
body_text
string | null
yes
—
source
string | null
yes
—
metadata
object[string, JsonValue ] | null
yes
—
first_seen_at
string (date-time)
yes
—
last_seen_at
string (date-time)
yes
—
visit_count
integer
yes
—
indexed_at
string (date-time) | null
yes
—
status
PageStatus
yes
—
One ranked page.
Field
Type
Required
Description and constraints
page_id
string
yes
—
canonical_url
string
yes
—
title
string | null
yes
—
domain
string
yes
—
first_seen_at
string (date-time)
yes
—
visit_count
integer
yes
—
score
number
yes
—
cluster
ClusterRef | null
no
—
chunks
array<ChunkResult >
yes
—
exact_match
boolean
no
Default: false
PageStatus
Lifecycle of a page through the indexing pipeline.
Type: "queued" | "indexing" | "indexed" | "failed" | "dead"
PageStatusBatchFoundResult
Status for a page known to the server.
Field
Type
Required
Description and constraints
page_id
string
yes
—
status
PageStatus
yes
—
last_error
string | null
no
—
features
PageStatusFeatures | null
no
—
found
true
no
Default: true
PageStatusBatchMissingResult
Status result for an unknown or expired page id.
Field
Type
Required
Description and constraints
page_id
string
yes
—
found
false
no
Default: false
PageStatusBatchRequest
POST /v1/pages/status/batch envelope.
Field
Type
Required
Description and constraints
page_ids
array<string>
yes
Minimum Items: 1; Maximum Items: 500
PageStatusBatchResponse
POST /v1/pages/status/batch response.
PageStatusFeatures
Nested enrichment feature state.
Field
Type
Required
Description and constraints
entities
FeatureStatus | null
no
—
PageStatusResponse
GET /v1/pages/{id}/status.
Field
Type
Required
Description and constraints
page_id
string
yes
—
status
PageStatus
yes
—
last_error
string | null
no
—
features
PageStatusFeatures | null
no
—
QueryLogListResponse
QueryLogRunResponse
Field
Type
Required
Description and constraints
query_id
string
yes
—
ts
string (date-time)
yes
—
kind
string
yes
—
compare_id
string | null
yes
—
query_text
string
yes
—
params
object
yes
—
active_model
string
yes
—
reranker_model
string | null
yes
—
candidate_set
array<LoggedHitResponse >
yes
—
dense_hits
array<LoggedHitResponse >
yes
—
sparse_hits
array<LoggedHitResponse >
yes
—
final_pages
array<LoggedPageResponse >
yes
—
timing_ms
object[string, number]
yes
—
feedback
object[string, boolean]
yes
—
QueryScore
Metrics for one logged run.
Field
Type
Required
Description and constraints
query_id
string
yes
—
query_text
string
yes
—
model
string
yes
—
ndcg
number
yes
—
reciprocal_rank
number
yes
—
recall
number
yes
—
recall_candidates
number
yes
—
rerank_lift
number | null
yes
—
RecomputeResponse
POST /v1/clusters/recompute response.
Field
Type
Required
Description and constraints
accepted
boolean
yes
—
detail
string | null
no
—
RegisterModelRequest
POST /v1/models body.
Field
Type
Required
Description and constraints
provider
string
yes
—
model_name
string
yes
—
dim
integer
yes
Minimum: 1.0; Maximum: 8192.0
max_input_tokens
integer
yes
Minimum: 1.0
id
string | null
no
—
RollupStrategy
How chunk scores pool into a page score.
No magic-number bonuses in v1: rerankers are calibrated, and arbitrary
boosts would destroy their ranking. A bonus variant may be added later
only if eval proves lift.
Type: "max" | "mean_top_m" | "sum_rrf"
ScoreReport
Everything eval score emits.
Field
Type
Required
Description and constraints
k
integer
yes
—
logged
integer
yes
—
labeled
integer
yes
—
scored
integer
yes
—
skipped_no_positive
integer
yes
—
models
array<ModelReport >
yes
—
queries
array<QueryScore >
yes
—
SearchBatchErrorResult
One batch query that failed with a per-item (non-fatal) error.
Field
Type
Required
Description and constraints
index
integer
yes
—
query
string
yes
—
outcome
"error"
no
Default: "error"
error
"feature_unavailable" | "no_active_model"
yes
—
detail
string
yes
—
SearchBatchOkResult
One successful batch query with its full search response.
Field
Type
Required
Description and constraints
query_id
string
yes
—
results
array<PageResult >
yes
—
offset
integer
yes
—
has_more
boolean
yes
—
suggestions
array<Suggestion >
yes
—
timing_ms
object[string, number]
yes
—
index
integer
yes
—
query
string
yes
—
outcome
"ok"
no
Default: "ok"
SearchBatchRequest
POST /v1/search/batch body: shared params + up to 20 query strings.
Field
Type
Required
Description and constraints
k
integer
no
Default: 10; Minimum: 1.0; Maximum: 100.0
offset
integer
no
Default: 0; Minimum: 0.0
candidates
integer
no
Default: 100; Minimum: 1.0; Maximum: 1000.0
rerank
boolean
no
Default: true
chunks_per_page
integer
no
Default: 2; Minimum: 0.0; Maximum: 10.0
rollup
RollupStrategy
no
Default: "max"
rollup_m
integer
no
Default: 3; Minimum: 1.0; Maximum: 20.0
rrf_k
integer
no
Default: 60; Minimum: 1.0
suggest
integer
no
Default: 3; Minimum: 0.0; Maximum: 10.0
mediation
Mediation
no
Default: "vector"
recency_half_life_days
number | null
no
—
filters
SearchFiltersBody | null
no
—
queries
array<string>
yes
Minimum Items: 1; Maximum Items: 20
SearchBatchResponse
POST /v1/search/batch response in input order.
SearchFiltersBody
First-class search filters.
Field
Type
Required
Description and constraints
domain
string | null
no
—
after
string (date-time) | null
no
—
before
string (date-time) | null
no
—
cluster_id
string | null
no
—
entity
string | null
no
—
SearchLatencySummary
Field
Type
Required
Description and constraints
since
string (date-time) | null
yes
—
runs
integer
yes
—
p50_ms
number
yes
—
p95_ms
number
yes
—
SearchRequest
POST /v1/search body.
Field
Type
Required
Description and constraints
k
integer
no
Default: 10; Minimum: 1.0; Maximum: 100.0
offset
integer
no
Default: 0; Minimum: 0.0
candidates
integer
no
Default: 100; Minimum: 1.0; Maximum: 1000.0
rerank
boolean
no
Default: true
chunks_per_page
integer
no
Default: 2; Minimum: 0.0; Maximum: 10.0
rollup
RollupStrategy
no
Default: "max"
rollup_m
integer
no
Default: 3; Minimum: 1.0; Maximum: 20.0
rrf_k
integer
no
Default: 60; Minimum: 1.0
suggest
integer
no
Default: 3; Minimum: 0.0; Maximum: 10.0
mediation
Mediation
no
Default: "vector"
recency_half_life_days
number | null
no
—
filters
SearchFiltersBody | null
no
—
query
string
yes
Minimum Length: 1; Maximum Length: 4000
SearchResponse
POST /v1/search response.
Field
Type
Required
Description and constraints
query_id
string
yes
—
results
array<PageResult >
yes
—
offset
integer
yes
—
has_more
boolean
yes
—
suggestions
array<Suggestion >
yes
—
timing_ms
object[string, number]
yes
—
SimilarResponse
GET /v1/pages/{id}/similar response.
Field
Type
Required
Description and constraints
page_id
string
yes
—
mediation
Mediation
yes
—
results
array<SimilarResult >
yes
—
SimilarResult
One similar page.
Field
Type
Required
Description and constraints
page_id
string
yes
—
canonical_url
string
yes
—
title
string | null
yes
—
score
number
yes
—
reason
string
yes
—
Suggestion
A related page appended to the response.
Field
Type
Required
Description and constraints
page_id
string
yes
—
title
string | null
yes
—
reason
string
yes
—
TombstoneBacklogSummary
Field
Type
Required
Description and constraints
pending
integer
yes
—
deleted
integer
yes
—
verified
integer
yes
—
UndoMergeResponse
POST /v1/entities/merges/{id}/undo response.
Field
Type
Required
Description and constraints
restored_entity_id
string
yes
—
UpdateWatchRequest
PATCH /v1/watches/{watch_id} body; omitted fields stay unchanged.
url is immutable: it is the watch's dedup identity — delete and
recreate to point a watch elsewhere.
Field
Type
Required
Description and constraints
enabled
boolean | null
no
—
interval_hours
integer | null
no
—
title
string | null
no
—
config
object[string, string] | null
no
—
ValidationError
Field
Type
Required
Description and constraints
loc
array<string | integer>
yes
—
msg
string
yes
—
type
string
yes
—
input
object
no
—
ctx
object
no
—
WatchKind
Kinds of pull sources a watch can poll.
Type: "rss" | "youtube" | "podcast"
WatchListResponse
GET /v1/watches response.
Field
Type
Required
Description and constraints
watches
array<WatchResponse >
yes
—
WatchResponse
One watch with its schedule and last-poll health.
Field
Type
Required
Description and constraints
id
string
yes
—
kind
WatchKind
yes
—
url
string
yes
—
title
string | null
yes
—
enabled
boolean
yes
—
interval_hours
integer
yes
—
config
object[string, string] | null
yes
—
next_run_at
string (date-time)
yes
—
last_run_at
string (date-time) | null
yes
—
last_status
WatchStatus
yes
—
last_error
string | null
yes
—
last_item_count
integer | null
yes
—
created_at
string (date-time)
yes
—
WatchRunAcceptedResponse
POST /v1/watches/{watch_id}/run response (202).
Field
Type
Required
Description and constraints
watch_id
string
yes
—
job_id
string | null
yes
—
WatchStatus
Outcome of a watch's most recent poll.
Type: "pending" | "ok" | "error"
WhoAmIResponse
Authenticated token identity and effective scopes.
Field
Type
Required
Description and constraints
name
string
yes
—
scopes
array<string>
yes
—