Quickstart
From zero to a first search and fetch in two minutes.
1. Get a key#
Ask the Cormorant operator for a project API key (cmr_…). Keep it out of
source control and pass it through an environment variable:
Shell
export CORMORANT_API_KEY=cmr_...
2. Search#
curl
curl -sS https://api.cormorant.ch/v1/search \
-H "Authorization: Bearer $CORMORANT_API_KEY" \
-H "Content-Type: application/json" \
-d '{"query": "Holcim annual report 2025", "max_results": 5}'
Python
import os
import httpx
client = httpx.Client(
base_url="https://api.cormorant.ch",
headers={"Authorization": f"Bearer {os.environ['CORMORANT_API_KEY']}"},
timeout=180, # sync calls can take up to 150 s
)
found = client.post("/v1/search", json={"query": "Holcim annual report 2025", "max_results": 5})
found.raise_for_status()
for hit in found.json()["results"]:
print(hit["rank"], hit["title"], hit["url"])
TypeScript
const BASE = "https://api.cormorant.ch";
const headers = {
Authorization: `Bearer ${process.env.CORMORANT_API_KEY}`,
"Content-Type": "application/json",
};
const res = await fetch(`${BASE}/v1/search`, {
method: "POST",
headers,
body: JSON.stringify({ query: "Holcim annual report 2025", max_results: 5 }),
});
if (!res.ok) throw new Error(`${res.status}: ${await res.text()}`);
const { results } = await res.json();
for (const hit of results) console.log(hit.rank, hit.title, hit.url);
Each result has url, title, every distinct snippets entry and the
engines that found it. The response also tells you the provider
(searxng or brave), whether it was cached, and its cost_usd.
3. Fetch a page#
curl
curl -sS https://api.cormorant.ch/v1/fetch \
-H "Authorization: Bearer $CORMORANT_API_KEY" \
-H "Content-Type: application/json" \
-d '{"url": "https://www.holcim.com/investors", "include_html": false}'
Python
page = client.post(
"/v1/fetch", json={"url": "https://www.holcim.com/investors", "include_html": False}
).json()
if page["error"] is None:
print(page["title"], page["tier"], len(page["text"]), "characters")
else:
print("could not fetch:", page["error"], page["request_id"])
TypeScript
const page = await (
await fetch(`${BASE}/v1/fetch`, {
method: "POST",
headers,
body: JSON.stringify({ url: "https://www.holcim.com/investors", include_html: false }),
})
).json();
if (page.error === null) console.log(page.title, page.tier, page.text.length);
else console.log("could not fetch:", page.error, page.request_id);
Always check error: /v1/fetch answers HTTP 200 for unsuccessful fetches
too (a 404 on the site is error: "http_404"). On success you get:
text— the main text, ready for an LLM or an index;title,content_kind(html,pdf,json, …),final_url,status;tier— which tier got it, andattempts— everything that was tried;body_url— the exact bytes, if you need them later.
4. Many URLs? Use a batch#
curl
curl -sS https://api.cormorant.ch/v1/batch/fetch \
-H "Authorization: Bearer $CORMORANT_API_KEY" \
-H "Content-Type: application/json" \
-d '{"idempotency_key": "quickstart-1", "items": [{"url": "https://example.com"}, {"url": "https://example.org"}]}'
# → {"job_id": "…", "created": true}
curl -sS "https://api.cormorant.ch/v1/jobs/$JOB_ID?include=items" \
-H "Authorization: Bearer $CORMORANT_API_KEY"
See Sync vs batch for polling, paging and callbacks.
Next steps#
- Fetching in depth — tiers, cost controls, PDFs, exact bytes.
- Errors & retries — what to retry and how.
- Using Cormorant from AI agents.