Search API
Searches are sent as POST requests to https://api.opoint.com/search/, with a JSON body. The body has two parts: searchterm, what to search for, and params, what to return.
You need an API token. Send it in the Authorization header as Token yourtoken; the examples below have yourtoken as a placeholder.
Your first search
Replace yourtoken with your token, and spotify with what you want to find.
curl "https://api.opoint.com/search/" \
-H "Authorization: Token yourtoken" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{
"searchterm": "spotify",
"params": {
"requestedarticles": 10,
"groupidentical": 1,
"main": {
"header": 1,
"summary": 1,
"text": 1
},
"textrazor": 30975,
"readership": 1
}
}'
import requests
response = requests.post(
"https://api.opoint.com/search/",
headers={
"Authorization": "Token yourtoken",
"Accept": "application/json",
},
json={
"searchterm": "spotify",
"params": {
"requestedarticles": 10,
"groupidentical": 1,
"main": {
"header": 1,
"summary": 1,
"text": 1,
},
"textrazor": 30975,
"readership": 1,
},
},
)
response.raise_for_status()
for article in response.json()["searchresult"]["document"]:
print(article["header"]["text"])
const response = await fetch("https://api.opoint.com/search/", {
method: "POST",
headers: {
"Authorization": "Token yourtoken",
"Accept": "application/json",
"Content-Type": "application/json",
},
body: JSON.stringify({
"searchterm": "spotify",
"params": {
"requestedarticles": 10,
"groupidentical": 1,
"main": {
"header": 1,
"summary": 1,
"text": 1
},
"textrazor": 30975,
"readership": 1
}
}),
});
const { searchresult } = await response.json();
for (const article of searchresult.document) {
console.log(article.header.text);
}
The search term can be more than a keyword: phrases, boolean expressions, and filters on language, country, sources and topics. See search syntax.
What the request asks for
Every param is optional. Params marked requires license only take effect if your account has that data licensed; without it, the request works but leaves that data out.
-
requestedarticles int, default 10
Number of articles to return.
-
groupidentical boolean
Group identical articles. If you enable this you will only receive one article from the group of identicals in your response. If you also enable
include_ogae_identicalyou will also receive the identical articles in an array inidentical_documents. -
main object
Which parts of each article to return. All are off by default.
To get the full article text, set
main.header,main.summary, andmain.textto non-zero values. -
textrazor interror_outline Requires license
Add data about topics and entities to the response. The value is a bit field: add up the values of the options you want.
Topics and entities, added in a
topics_and_entitiesfield on each document:1: IPTC topics2: Entities4: Entities without a Wikidata id32768: Wikidata topics
Highlighting:
8: Adds wikidata ids to match tags (<match ent="1,23...">), pluswikinames,wikidescriptionsandwikiwebsitesdictionaries with the wikidata items' names, descriptions and urls respectively. Match tags are enabled bymain.matches, so set that too.
Company identifiers on entities:
2048: Crunchbase4096: PermID8192: LEI16384: FIGI
Minimum topic score: to leave out weakly matching topics, add
16 × N, with N from 0 to 127. Topics scoring below N / 100 are then dropped; for example, adding160drops topics scoring below 0.10.Some useful values:
30975: topics, entities, highlighting and company identifiers, with a minimum topic score of 0.15. A good starting point.7: topics and entities without highlighting.15: topics, entities and highlighting.
-
readership booleanerror_outline Requires license
Include
similarweb.readershipandsimilarweb.article_readershipfields in the response, with readership estimates.
The response
The response is JSON (or XML), with the matching articles in searchresult.document. Here is one article, shortened:
{
"searchresult": {
"documents": 2,
"count": 3,
"context": "534348478:1:0;TOTDOC=2",
"document": [
{
"id_site": 131,
"id_article": 2122020,
"unix_timestamp": 1613135182,
"url": "https://www.bbc.com/news/uk-wales-56041927",
"language": {
"encoding": "iso-639",
"text": "en"
},
"countrycode": "GB",
"header": {
"text": "Stonehenge: Did animals pull stones from Wales to England?"
},
"summary": {
"text": "One of Britain's biggest and oldest stone circles has been found in Wales - and could be the original building blocks of Stonehenge."
},
"body": {
"text": "<p> Archaeologists uncovered the remains of the Waun Mawn site in Pembrokeshire's Preseli Hills.</p> <p> They believe the stones could have been dismantled and …"
},
"similarweb": {
"domain": "bbc.com",
"readership": {
"P": 0.012741,
"value": 2162922
}
}
}
]
}
}
- header, summary and body hold the text, because the request set main. The summary is often the article's first paragraph, and the body continues after it, so you need all three for the full article. The header and summary are plain text; the body usually contains HTML.
- topics_and_entities and similarweb hold the topics, entities and readership data, when your license includes them and there is data for the article.
- searchresult.context is where this batch ended. Pass it back to get the next batch; see getting more articles.
XML
To get XML instead, send Accept: application/xml instead of application/json. The fields have the same names, but some are attributes, like id_site on <document>, and text is in <text> elements, with the body split into <p> paragraphs. The same article in XML:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<searchresult documents="2" count="3" context="534348478:1:0">
<document id_site="131" id_article="2122020">
<unix_timestamp>1613135182</unix_timestamp>
<url>https://www.bbc.com/news/uk-wales-56041927</url>
<language encoding="iso-639">en</language>
<countrycode>GB</countrycode>
<header matches="false">
<text>Stonehenge: Did animals pull stones from Wales to England?</text>
</header>
<summary matches="false">
<text>One of Britain's biggest and oldest stone circles has been found in Wales - and could be the original building blocks of Stonehenge.</text>
</summary>
<body matches="false">
<p>
<text>Archaeologists uncovered the remains of the Waun Mawn site in Pembrokeshire's Preseli Hills.</text>
</p>
<p>
<text>They believe the stones could have been dismantled and …</text>
</p>
</body>
<similarweb>
<domain>bbc.com</domain>
<readership P="0.012741">2162922</readership>
</similarweb>
</document>
</searchresult>
Every field is described in the API reference.
Common tasks
Each example shows only the request body. Send it like the first search.
Get more articles, pagination
requestedarticles sets how many articles come back at a time. To get all articles matching a search, fetch them in batches: send the first search with an empty context,
{
"searchterm": "spotify",
"params": {
"requestedarticles": 100,
"context": "",
"main": {
"header": 1,
"summary": 1,
"text": 1
}
}
}
then send the same search again with the context value from the response, to get the next, older batch. Repeat until the returned context is empty.
{
"searchterm": "spotify",
"params": {
"requestedarticles": 100,
"context": "540062299:1:0;TOTDOC=10",
"main": {
"header": 1,
"summary": 1,
"text": 1
}
}
}
Search a time window
oldest and newest limit the search to articles published in between, as Unix timestamps. This example covers January 2026 (UTC).
{
"searchterm": "spotify",
"params": {
"requestedarticles": 10,
"oldest": 1767225600,
"newest": 1769904000,
"main": {
"header": 1,
"summary": 1,
"text": 1
}
}
}
Group duplicates
The same story is often published by several outlets. With groupidentical, each group of identical articles is returned once. Setting identical to {"inherit": true} also returns the duplicates, with the same fields as the main article, in its identical_documents field. Articles without duplicates also have the field, with a cnt of 0.
{
"searchterm": "spotify",
"params": {
"requestedarticles": 10,
"main": {
"header": 1,
"summary": 1,
"text": 1
},
"groupidentical": 1,
"identical": {
"inherit": true
}
}
}
Highlight matches
Set the main fields to 2 and main.matches to true, and the words matching the search are wrapped in <match> tags in the header, summary and body.
{
"searchterm": "spotify",
"params": {
"requestedarticles": 10,
"main": {
"header": 2,
"summary": 2,
"text": 2,
"matches": true
}
}
}
Get specific articles
To fetch articles you already know, list their ids in articles and set select_by_ids, so no search term is needed. Set requestedarticles to at least the number of ids.
{
"params": {
"requestedarticles": 2,
"select_by_ids": true,
"articles": [
{
"id_site": 11,
"id_article": 887677
},
{
"id_site": 11,
"id_article": 887676
}
],
"main": {
"header": 1,
"summary": 1,
"text": 1
}
}
}
Get new articles as they arrive
Searching again and again for the latest articles returns the same ones each time. To get only new articles matching a search, use StoredSearch instead.
Reference
Search syntax explains how to write search terms. Every param is described in the API reference.