Search
Rank fresh pages from the Blopus index for a query. 1 credit per block of 10 results β see Credits.
Parameters#
| Field | Type | Description |
|---|---|---|
queryrequired | string | The search query. 1β500 characters. |
countopt | int | Number of results, up to 50. Default 10. Rounded up to a block of 10, because that is the unit you are billed β ask for 4 and you get 10, ask for 15 and you get 20. See Credits. |
freshnessopt | enum | pd Β· pw Β· pm Β· p3m Β· p1y Β· all. Default all. Past day / week / month / 3 months / year. |
recencyopt | enum | normal Β· relaxed Β· off. Default normal. This changes ranking, not what is returned β unlike freshness, which filters. Use off for timeless questions where the best answer may be months old (βhow do dividends workβ). |
news_onlyopt | bool | Restrict to newsroom sources β newspapers, wire services, broadcasters, magazines. Default false. Runs over a dedicated news channel, so it is faster than an unscoped search, not slower. |
include_domainsopt | string[] | Only return results from these hostnames. Max 50. Bare hosts or URLs accepted. |
exclude_domainsopt | string[] | Drop results from these hostnames. Max 50. |
start_dateopt | string | Publish window start β YYYY-MM-DD or epoch seconds. Applied alongside freshness. |
end_dateopt | string | Publish window end β YYYY-MM-DD or epoch seconds. |
languageopt | string | Restrict to one language, e.g. en, pt-br. |
offsetopt | int | Pagination offset, 0β200. Default 0. |
include_excerptopt | bool | Return a longer excerpt per result. Default false. |
excerpt_charsopt | int | Excerpt length cap, up to 1200. Implies a longer excerpt. |
include_contentopt | bool | Content mode. Return the cleaned page text inline (in each result's content) so you can read & reason without a separate fetch. Default false. |
min_wordsopt | int | Drop short pages. Only return results whose body has at least this many words (1–5000). Tag listings, stub pages and photo captions are keyword bait: they rank without saying anything. min_words: 120 is a good default when you want something to read. Leave it off for breaking news, where a two-line wire story is a legitimate answer. |
include_imagesopt | bool | Hero image URL per result. Beta. Off by default because it costs roughly 295 tokens per 10 results — which matters when the caller is a language model. Coverage is partial, so image is null on plenty of hits: always check before rendering, and never promise a picture before you have a non-null URL. |
topicsopt | string[] | Scope to whole subject areas. e.g. ["cybersecurity"]. Matched exactly against a published vocabulary — see the full topic vocabulary or call GET /v1/topics, because an unknown topic returns zero results rather than widening the search. A topic describes what a publication covers, not what an individual article is about: ["ai"] means “pages from AI-focused sites”, which is broader than “pages about AI”. |
exclude_topicsopt | string[] | Drop results from publications covering these topics, e.g. ["sports"]. Useful for de-noising a broad query. |
content_charsopt | int | Cap for inline content, up to 8000 (default 2000 when content mode is on). |
Freshness guide. For time-sensitive queries β breaking news, prices, "latest", release notes β use freshness: "pd" or "pw". It sharply improves relevance by prioritizing recently crawled pages. Leave it "all" for evergreen/reference lookups.
Thin pages. Set min_words: 120 when the question needs substance — analysis, background, a comparison, “how does X work”. It filters on the indexed word count, so it costs nothing and removes the tag pages and stubs that match your keywords without answering them. Keep it off for breaking news and for quick lookups, where a short page is often the right answer.
News scoping. Set news_only: true when the question is about events β what happened, who announced what, market reaction, election results, earnings news. It searches only sources with a newsroom over a dedicated news channel, so it is faster, and it removes vendor blogs, marketing pages, forums and documentation that otherwise crowd news results. Pair it with freshness: "pd" for breaking topics.
When not to use it. Leave news_only off when the answer lives in documentation, tutorials, forums, reference material or product pages β "how does asyncio work", "kubernetes ingress example", "what is a dividend". And if a question wants both β "what's new in Python 3.14" needs the release announcement and the changelog β leave it off: an unscoped search returns everything, so omitting it is always the safe choice.
Request#
Response#
Top-level fields: results[], count, offset, more_results (whether paging further would return more), and remaining_quota (your key's remaining monthly credits).
Result fields#
| Field | Type | Description |
|---|---|---|
title | string | Page title. |
url | string | Canonical page URL. |
snippet | string | Excerpt; longer when include_excerpt is set. |
domain | string | Registrable host, e.g. reuters.com. |
site_name | string | Human-readable site name. |
favicon | string | Favicon URL for the source. |
published_at | int | Publish time, epoch seconds (nullable). |
age_seconds | int | Seconds since publish (nullable). |
language | string | Detected language code. |
score | float | Normalized relevance, 0β1 (relevance, not site authority). |
word_count | int | Body length in words. Returned on every result whether or not you filter with min_words, so you can tell a 40-word stub from a real article before reading it. |
image | string | null | Hero image URL. Present only when the request set include_images, and null when the page has no hero. |
image_w, image_h | int | null | Hero image dimensions in pixels, when the crawler recorded them. |
topics | string[] | Subject areas of the publication this page came from. Useful for seeing why a result matched, and for learning real values to pass to the topics filter. See the vocabulary. |
fetched_at | int | When we crawled the page (epoch seconds). published_at falls back to this when the article carries no date, so compare the two if precise recency matters. |
duplicate_count | int | How many near-identical copies were collapsed into this result. 0 means unique. A syndicated wire story can collapse 20+ copies — which is why asking for 10 results can return 8. |
content | string | Cleaned full page text. Present only when the request set include_content. |
The response envelope
Alongside results, every search response carries fields that describe
the answer itself. They are easy to ignore and expensive to ignore: two of them tell
you the result set is not what you asked for.
| Field | Type | Why you care |
|---|---|---|
total | int | Approximate matches, capped for speed. Use it for “about N results”, never for exact arithmetic. |
more_results | bool | Whether paging further with
offset will return anything. |
engine | string | hybrid (keyword + semantic,
the normal path), bm25 (intended for chronological or empty queries), or
bm25_fallback. |
degraded | bool | Read this one.
true means we intended a hybrid search and could not run it, so you are getting
lexical-only results. They are still real results, but semantic matches are missing. If your
product depends on semantic recall, surface it or retry. |
quota_clamped | bool | true means we returned
fewer results than you asked for because the key’s remaining credits allowed only that
many — not because fewer exist. Without checking this you cannot tell
“out of credit” from “out of matches”. |
freshness_relaxed | bool | true means a tight
freshness window starved the result set and was widened automatically. Your
results may be older than the window you passed. |
note | string | Plain-language advice about this request. See below. |
The note field
Sometimes a search succeeds and is still the wrong search. The results look fine, so
nothing in the payload tells you otherwise. note is where we say so in plain
language, and it is aimed as much at an LLM reading the response as at a human.
It appears only when there is something worth saying. A note that fired on healthy results would train you — or your model — to ignore all of them.
| When it fires | What it tells you |
|---|---|
| The query merges several topics | “economy, sports and Iran” is three searches. No document is about all three, so the result set is a compromise. |
| The query is shaped like a question or a pasted sentence | Keyword-like queries of 2–8 words retrieve better than prose. |
| You are holding snippets only | A snippet is roughly one sentence — enough
to choose what to read, not enough to analyze or quote. Suggests fetch or
include_content. |
| Most results are thin | Tag listings and stubs rank on keywords without saying
anything. Suggests the exact min_words value to retry with. |
| Images were requested but are mostly missing | Image coverage is partial; treat a null image as normal rather than constructing a URL that 404s. |
| A topic filter matched nothing | Topics are exact-match, so an invented value returns zero results — indistinguishable from a genuine no-match unless we say so. |
| Results are dominated by one subject area | Names the topic, so you can scope to it or exclude it deliberately rather than inheriting a slant you did not choose. |
| Results are foreign coverage of a place | Searching in the local language reaches that country’s own press — measurably a different set of publications. |
| Your SDK is behind | Newer versions accept parameters yours cannot send. Shown at most once a day. |
If you are building an agent, pass note back to the model. It
is written to be acted on: each one names the concrete parameter to change.
GET /v1/topics
Prefer to browse? The same list is published at blopus.ai/docs/topics, no API key needed.
The vocabulary you may pass to topics and exclude_topics.
This call is not billed. Topics are matched exactly, so an unknown value
returns zero results — which you cannot tell apart from a genuine no-match unless you
know the vocabulary. Fetch it once at startup and cache it.
| Parameter | Type | Notes |
|---|---|---|
min_docsopt | int | Hide topics with
fewer than this many documents. Default 1000, which covers about 99% of all topic
assignments while dropping a long tail of near-empty labels. |
curl -s "https://api.blopus.ai/v1/topics?min_docs=100000" \
-H "Authorization: Bearer $BLOPUS_API_KEY"
{
"topics": [
{ "topic": "economy", "documents": 5033276 },
{ "topic": "politics", "documents": 3661143 }
],
"count": 100,
"min_docs": 100000
}
Topics are assigned per source, not per article. Use them to scope or de-noise a search — “only cybersecurity publications”, “no sports sites” — never as a substitute for putting the subject in the query itself.