---
title: "Stories Search"
method: GET
path: "/v1/stories/search"
---

# Stories Search

`GET /v1/stories/search`

## Request

- Base URL: `https://api.storyflo.com` (the document declares no server; this is the origin it was published from)
- URL: `https://api.storyflo.com/v1/stories/search`
- Auth: none declared

Search Storyflo's audio archive.

When ``expand=True`` (default) and local results are thin (< 5),
we also race a Hacker News + Brave Search News + GNews fan-out
and surface the top external hits as 'suggestions' the listener
can forward to story@storyflo.com to ingest. External results are
NOT in our DB until the listener forwards — they're discovery
nudges, not silently-ingested content.

Hot-query speedup: responses are wrapped by a 60s in-process
LRU+TTL cache keyed by ``(query, vertical, limit, offset)``. The
watchdog smoke-tests ``?q=tech`` every minute and the frontend
hero suggests a small fixed set of common terms, so a tiny per-
worker cache collapses >90% of that load to one warm response
per minute. ``degraded=True`` responses are NOT cached by default
(don't lock in an empty result on a statement_timeout blip).
Operator can bypass per-request with
``X-Storyflo-Search-Cache: bypass`` (used by smoke probes that
want to measure cold-pass latency) or globally via env
``SEARCH_CACHE_TTL_SEC=0``.

Pool-exhaustion fix (mirrors PR #657 for /v1/search/hybrid):
deliberately no ``db: AsyncSession = Depends(get_db_replica)``
parameter. With basic-plan PG sized at ``DB_POOL_SIZE=5 +
MAX_OVERFLOW=3`` (total 8 conns, see
``[[storyflo-prod-deploy-discipline-2026-06-19]]``), a request-
scoped Depends session would be held for the full duration of
``cache.get_or_compute`` — including for non-owners merely
awaiting another coroutine's Future inside ``search_cache.py``.
The owner opens a short-lived replica session inside ``_compute``
and releases it before the external fan-out + Future resolution;
non-owners hold zero connections while waiting.

## Query parameters

- `q` string, required
- `vertical` string, nullable
- `limit` integer
- `offset` integer
- `expand` boolean

## Response `200`

Successful Response

- object

## Other responses

- `422`: Validation Error

---

[API](https://skmtc.dev/storyflo/apis/storyflo-inference-router.md) · [All operations](https://skmtc.dev/storyflo/apis/storyflo-inference-router/llms.txt) · [OpenAPI document](https://skmtc.dev/storyflo/apis/storyflo-inference-router/revisions/c3a1a735ac7a?raw)
