Search
Run a web search via Brave and optionally fetch each result page as markdown in the same call. The discovery primitive in the Gyrence pipeline — Search finds, Fetch reads one, Gyre walks many.
Use this when
- You need discovery → cleaned markdown in a single call (RAG, agent tool, research pipeline).
- You're running site-scoped queries (
site:sec.gov 8-K,site:fda.gov recall) and want the bodies, not just the SERP. - You want recency control beyond Brave's defaults (
tbs: "y2","y3","y5"). - You need per-URL credit attribution —
results[].fetch.viatells you which result paid HTTP vs browser tier.
| Method | POST |
| Path | /api/v1/search |
| Auth | Bearer |
| Credits | 2 base + (1 per http sub-fetch, 3 per browser sub-fetch) when fetch: true |
Request
| Parameter | Type | Description |
|---|---|---|
queryrequired | string | Search query. Min length 1. |
limit | numberdefault: 10 | Max results. Range 1..20. |
fetch | booleandefault: false | Fetch each result URL inline and attach a fetch field to each result. |
fetchFormats | ("markdown" | "links" | "html")[]default: ["markdown"] | Which fields to populate on each inline fetch. html is accepted but not currently emitted. |
tbs | "d" | "w" | "m" | "y" | "y2" | "y3" | "y5" | Time window: past day / week / month / 1–5 years. y2/y3/y5 post-filter Brave's 1-year cap. |
Example body
{
"query": "site:sec.gov 8-K corporate action",
"limit": 10,
"fetch": true,
"fetchFormats": ["markdown"],
"tbs": "m"
}Response
| Field | Type | Description |
|---|---|---|
query | string | Echo of the input query. |
totalResults | number | Count of returned results. |
via | "http" | "browser" | "n/a" | Dominant sub-fetch tier across results, or the literal "n/a" when fetch: false. |
results[] | SearchResult[] | Ordered results, rank 1..N. |
results[].rank | number | 1-based rank after filtering. |
results[].title | string | Page title from Brave. |
results[].url | string | Result URL. |
results[].snippet | string | Brave-provided snippet. |
results[].description | string | Alias of snippet. |
results[].age | string? | Relative age (e.g. "3 months ago") when Brave provides it. |
results[].page_age | string? | ISO timestamp when Brave provides it. |
results[].fetch | object? | Present only when fetch: true. See below. |
results[].fetch on success
| Field | Type | Description |
|---|---|---|
ok | true | |
markdown | string | Empty string when "markdown" not in fetchFormats. |
links | string[] | Empty array when "links" not in fetchFormats. |
statusCode | number | Origin HTTP status. |
via | "http" | "browser" | Tier that produced this sub-fetch. Drives credit cost (1 vs 3). |
results[].fetch on failure
| Field | Type | Description |
|---|---|---|
ok | false | |
error | string | Failure reason (timeout, SSRF block, upstream error). |
via | "http" | "browser" | Always "http" on failure. |
Example response
{
"ok": true,
"data": {
"query": "site:sec.gov 8-K corporate action",
"totalResults": 2,
"via": "http",
"results": [
{
"rank": 1,
"title": "Form 8-K — Example Corp",
"url": "https://www.sec.gov/...",
"snippet": "Item 8.01 Other Events...",
"description": "Item 8.01 Other Events...",
"page_age": "2026-05-12T14:00:00Z",
"fetch": {
"ok": true,
"markdown": "# Form 8-K\n\n...",
"links": [],
"statusCode": 200,
"via": "http"
}
}
]
}
}Example
curl -X POST https://www.gyrence.com/api/v1/search \
-H "Authorization: Bearer $GYRENCE_API_KEY" \
-H "Content-Type: application/json" \
-d '{"query":"site:sec.gov 8-K","limit":10,"fetch":true,"tbs":"m"}'Errors
| Code | HTTP | Meaning |
|---|---|---|
bad_request | 400 | query missing/empty, or any field fails validation. |
unauthorized | 401 | Missing, malformed, or revoked Authorization header. |
credits_exhausted | 402 | Workspace balance below request cost. |
timeout | 408 | Request exceeded the 25-second hard deadline. |
rate_limited | 429 | Per-workspace rate limit, or Brave returned 429. |
upstream_error | 502 | Brave returned 5xx or unparseable response. |
{ "ok": false, "error": "brave returned 503", "code": "upstream_error" }Credits
Total = 2 base + Σ sub-fetches, where each sub-fetch is 1 (HTTP tier) or 3 (browser tier). With fetch: false, it's a flat 2. Read results[].fetch.via to attribute cost per URL. Failed sub-fetches are not charged.
Coverage & known limits
- Max 20 results per call. For deeper coverage, paginate by refining
queryortbs. - Sub-fetches are capped at 10s each (independent of the 25s request deadline). Slow origins surface as
{ ok: false, error: "timeout" }on that result; the envelope still succeeds. - SSRF sub-fetches to private / loopback / link-local hosts return
{ ok: false }per result — they don't fail the whole call. tbs ≥ y2uses Brave'sfreshness=pyand post-filters by parsed date. Results without a parseablepage_age/ageare kept (not dropped).htmlinfetchFormatsis accepted today but not emitted. Use/fetchdirectly when you need the cleaned HTML field.
Notes
- Inline-fetch concurrency. Up to 5 sub-fetches run in parallel; each capped at 10s independent of the 25s request deadline.
- Result ordering. Results are returned in Brave's relevance order, then filtered (e.g. by
tbs), then re-numbered withrank: 1..N. - Per-URL fetcher. Each sub-fetch uses the same two-tier pipeline as
/fetch(HTTP → browser escalation, SEC.gov fast path, block-page detection).
Try it
Run Search from the console at /app/search — toggle fetch, set a tbs window, and inspect per-result tier.
