Tell us who you are
There is no API key here and there never will be. But if you send one optional header saying what your agent is and what it runs through, you make it much more likely that it stays that way.
Entirely optional. Nothing is rejected, throttled or degraded if you send nothing. There is no registration behind it, no value to obtain from us, and no validation — you make the string up yourself. It is a courtesy, not a credential.
The header
X-Agent: agent_name=newsbot; version=1.4.2; software=langchain/0.3; model=gpt-4o; purpose=rag; contact=https://example.com/botOne header, semicolon-separated key=value pairs. Every key is optional,
including all of them. Send two if two is all you have:
X-Agent: agent_name=my-research-bot; software=n8nRecognised keys
Unknown keys are kept as-is and ignored, so you can invent your own without breaking anything, and we can add new ones without breaking you.
| Key | Example | Why it helps |
|---|---|---|
agent_name | newsbot | What your agent is called. The one key worth sending if you send only one. |
version | 1.4.2 | Your version. Lets us tell a regression in your build from a regression in ours. |
software | langchain/0.3 | The program or library the agent runs through: langchain, llamaindex, n8n, zapier, claude-desktop, claude-code, cursor, openai-assistants, crewai, autogen, dify, flowise, semantic-kernel, custom. Add a version after a slash if you like. |
model | gpt-4o | Which model is driving the agent. Different models phrase queries very differently, and that shapes what we tune. |
provider | openai | Who serves the model: openai, anthropic, google, mistral, local. |
mcp | claude-desktop | The MCP client, if the call arrives through Model Context Protocol rather than direct HTTP. |
purpose | rag | What the calls are for: rag, monitoring, research, digest, alerting, dataset, eval. |
org | example-labs | Your company or project, if you are happy to say. |
contact | https://example.com/bot | A URL or mailto: where we can reach a human. The only key we would ever act on individually. |
session | a91f3c | An opaque id that groups the calls of one run together. Make it random. Never put a user id, an email or anything personal here. |
sdk | python/3.12 | Language and runtime of your client. |
Also send a User-Agent
If you set nothing else, set this. It is the standard mechanism, every HTTP client supports it, and it is the convention Wikimedia and other large public services already ask of automated clients:
User-Agent: newsbot/1.4.2 (+https://example.com/bot)Default library user agents — python-requests/2.32,
node-fetch, Go-http-client/2.0 — tell us a language and
nothing else. That is not a problem, it is just a missed opportunity.
Or pass it as query parameters
Equally good, and often easier: a browser fetch from a page you do not control, a no-code tool with a fixed request shape, a shell one-liner. Unknown parameters are ignored by the API, so this is safe on every endpoint and cannot break a request:
curl "https://freenewsapi.ai/v1/search?q=climate&agent_name=newsbot&software=n8n&model=gpt-4o&purpose=digest"The parameter names mirror the header keys one for one:
agent_name, software, model, version,
purpose, contact. Send the two that matter —
agent_name and software — and skip the rest.
Every model integration page ships this already filled in for that model.
In code
Python
import requests
AGENT = {
"User-Agent": "newsbot/1.4.2 (+https://example.com/bot)",
"X-Agent": "agent_name=newsbot; version=1.4.2; software=langchain/0.3; "
"model=gpt-4o; purpose=rag; contact=https://example.com/bot",
}
r = requests.get("https://freenewsapi.ai/v1/search",
params={"q": "climate summit", "date": "24h", "size": 10},
headers=AGENT, timeout=20)JavaScript
const AGENT = {
"User-Agent": "newsbot/1.4.2 (+https://example.com/bot)",
"X-Agent": "agent_name=newsbot; version=1.4.2; software=custom; model=claude-opus-5; purpose=rag",
};
const r = await fetch("https://freenewsapi.ai/v1/search?q=climate&size=10",
{ headers: AGENT });Browsers refuse to let page scripts override User-Agent. From a
browser, send X-Agent only, or use the query-parameter form above.
curl
curl -H "X-Agent: agent_name=newsbot; software=cursor; model=claude-opus-5" \\
-A "newsbot/1.4.2 (+https://example.com/bot)" \\
"https://freenewsapi.ai/v1/search?q=climate&size=5"LangChain tool
import requests
from langchain_core.tools import tool
SESSION = requests.Session()
SESSION.headers.update({
"User-Agent": "research-agent/2.0 (+https://example.com)",
"X-Agent": "agent_name=research-agent; version=2.0; software=langchain/0.3; "
"model=gpt-4o; purpose=research",
})
@tool
def search_news(q: str, date: str = "7d", size: int = 10) -> list:
"""Search worldwide news from the last 30 days."""
return SESSION.get("https://freenewsapi.ai/v1/search",
params={"q": q, "date": date, "size": size},
timeout=20).json()["results"]Set it once on a session object and every call inherits it. That is the whole integration cost.
Why we ask
It is what keeps keys away
The usual reason an open API closes is that its operators cannot see who is using it, so the only lever left when something goes wrong is authentication. Voluntary identification gives us the visibility without the wall. Every agent that identifies itself is an argument against ever needing a key.
We can warn you before we break you
If a change would affect the way your agent queries, a contact means we
can tell you first instead of you finding out from a failing job.
We tune for what is actually used
Knowing that most traffic arrives from, say, n8n workflows asking for
date=today tells us exactly what to cache and what to optimise. Right now we
are guessing.
Abuse gets handled surgically
When one caller floods the service, the blunt response is a rule for everyone. An identified caller can be contacted, or given its own allowance, while everyone else is left alone.
What identifying will get you later
None of this exists yet, and none of it is a reason to identify today — but this is the direction, so you know why the header is worth wiring in now rather than later:
- Higher burst allowance for identified agents, once there is a reason to differentiate at all.
- Change notices ahead of time, to the
contactyou gave. - A public list of agents using the service, opt-in, with a link back to yours. Visibility in exchange for visibility.
- Usage insight for your own agent — what it asked for, how often it got nothing back, which queries wasted tokens.
What we will never do with it
- Require it. An anonymous request stays a first-class request. That is the point of the whole service.
- Validate it. There is nothing to register and nothing to verify. Two agents may call themselves the same thing; we do not care.
- Sell it or share it. It stays in our operational logs.
- Use it to price you. Free keyless search is permanent, identified or not.
Do not put personal data in the header. No end-user names, emails, IDs
or query context. session exists for grouping calls and should be a random
string. contact should reach an operator, not a user. Treat the header as
public: it travels through a CDN and lands in access logs.
Check what arrives
Send the header and it lands in our access log alongside the request. There is nothing to confirm and no response header to read — a request with the header and one without get identical responses, which is exactly the guarantee being made here.
curl -H "X-Agent: agent_name=test-bot; software=curl" \\
"https://freenewsapi.ai/v1/search?q=test&size=1"Related
OpenAI tool definition · Anthropic tool definition · Rate limits · Privacy