Base URL: https://trendnews.uk.app/api/v1. Sign up, create an API key in your account and send your first request:
curl -H "X-API-Key: YOUR_KEY" "https://trendnews.uk.app/api/v1/posts?country=UA&limit=5"
Countries are given as ISO-2 codes (UA, US, DE, PL…). The full list with feed languages is returned by /api/v1/countries. New posts appear every hour.
Every request except /v1/health, must include the API key in a header:
X-API-Key: tn_live_…
Also accepted: Authorization: Bearer tn_live_…. Passing the key in URL parameters is not allowed: it would end up in logs and browser history.
Limits depend on the account's plan. The daily quota is shared by all keys of the account and resets at 00:00 UTC. The per-minute limit applies to each key separately. All plans and prices
| Plano | Requests per day | Requests per minute | API keys |
|---|---|---|---|
| Free | 1 000 | 60 | 1 |
| Pro | 50 000 | 300 | 5 |
| Business | 500 000 | 1 200 | 20 |
The current state is returned in the headers of every response:
| Header | Meaning |
|---|---|
X-Plan | the account's plan: free, pro ou business |
X-Quota-Limit | daily quota of the account |
X-Quota-Remaining | requests left for today |
X-Quota-Reset | seconds until the quota resets (00:00 UTC) |
X-RateLimit-Limit | per-minute request limit of the key |
X-RateLimit-Remaining | requests left in the current minute |
Retry-After | only with a 429 response: seconds until you can retry |
Responses may be cached for up to 60 seconds (Cache-Control: private, max-age=60): data is updated once an hour. Caching also saves your quota.
A successful response always has the data; lists also have meta with pagination. An error has the error field with a machine-readable code and a message.
// success{ "data": [ … ], "meta": { "total": 856, "limit": 20, "offset": 0, "has_more": true } }
// error{
"error": {
"code": "invalid_country",
"message": "Unknown country code. The list of supported ISO-2 codes: /api/v1/countries"
}
}
| HTTP | code | When |
|---|---|---|
| 400 | missing_param | a required parameter is missing |
| 400 | invalid_param, invalid_country, invalid_date | a parameter has an invalid value or format |
| 401 | missing_api_key | request without a key |
| 401 | invalid_api_key | the key is invalid or revoked |
| 403 | account_blocked | the key owner's account is blocked |
| 404 | not_found | unknown endpoint or the post does not exist |
| 405 | method_not_allowed | a method other than GET |
| 429 | rate_limited | per-minute request limit exceeded |
| 429 | quota_exceeded | the plan's daily quota is used up (resets at 00:00 UTC) |
| 500 | server_error | internal server error |
Lists return at most limit records (up to 100). To get the next page, increase offset by limit, as long as meta.has_more is true.
Checks that the API is up and returns the time of the latest post. No key needed — handy for monitoring.
{
"data": {
"status": "ok",
"last_post_at": "2026-10-24T14:05:09Z",
"countries": 6,
"time": "2026-10-24T14:31:38Z"
}
}
All countries we collect news for: ISO-2 code, name, flag, feed language, number of posts and the date of the latest one.
{
"data": [
{ "code": "UA", "name": "Україна", "flag": "🇺🇦", "lang": "uk", "post_count": 856, "last_post_date": "2026-10-24" },
{ "code": "SI", "name": "Словенія", "flag": "🇸🇮", "lang": "sl", "post_count": 150, "last_post_date": "2026-10-24" },
{ "code": "GB", "name": "Велика Британія", "flag": "🇬🇧", "lang": "en", "post_count": 284, "last_post_date": "2026-10-24" }
]
}
Post categories of a country with the number of posts in each. Category names are in the country's language.
| Parameter | Required | Description |
|---|---|---|
country | yes | ISO-2 country code (full list: /v1/countries) |
{
"data": [
{ "slug": "politics", "label": "Politics", "posts": 61 },
{ "slug": "sport", "label": "Sport", "posts": 54 },
{ "slug": "other", "label": "Other", "posts": 48 }
],
"meta": { "country": "GB" }
}
Digest posts, newest first. All filters are optional and can be combined.
| Parameter | Required | Description |
|---|---|---|
country | no | ISO-2 country code |
category | no | Category slug: politics, economy, war, society, sport, culture, world, tech, other |
date | no | A specific day, YYYY-MM-DD |
from | no | Start of the date range, YYYY-MM-DD (inclusive) |
to | no | End of the date range, YYYY-MM-DD (inclusive) |
q | no | Search in title and topic, up to 100 characters |
limit | no | Number of items, 1–100; default 20 |
offset | no | Pagination offset; default 0 |
{
"data": [
{
"id": 24239,
"country": "SI",
"lang": "sl",
"category": { "slug": "other", "label": "Drugo" },
"trend": "češka korak bližje ukinitvi prispevka",
"date": "2026-10-24",
"title": "Tema dneva: Češka korak bližje ukinitvi prispevka",
"digest": "»češka korak bližje ukinitvi prispevka« se danes pojavlja v več medijih (2). …",
"source_count": 2,
"published_at": "2026-10-24T14:05:09Z",
"url": "https://trendnews.uk.app/post.php?id=24239"
}
],
"meta": { "total": 150, "limit": 1, "offset": 0, "has_more": true }
}
Full post data together with the list of original sources it was built from.
| Parameter | Required | Description |
|---|---|---|
id | yes | Post ID (part of the path) |
{
"data": {
"id": 24242,
"country": "GB",
"lang": "en",
"category": { "slug": "sport", "label": "Sport" },
"trend": "aston villa man city",
"date": "2026-10-24",
"title": "Story of the day: Aston villa man city",
"digest": "One of the day's top stories is “aston villa man city”, reported by 3 sources. …",
"source_count": 3,
"published_at": "2026-10-24T14:05:10Z",
"url": "https://trendnews.uk.app/post.php?id=24242",
"sources": [
{ "title": "…", "url": "https://www.standard.co.uk/…", "host": "www.standard.co.uk", "sitename": "Evening Standard" }
]
}
}
Today's topics from the latest hourly analysis: the phrase, its score, the number of independent outlets covering it and an example headline.
| Parameter | Required | Description |
|---|---|---|
country | no | One country; all countries if omitted |
date | no | Day, YYYY-MM-DD; defaults to the latest available |
top | no | Trends per country, 1–50; default 15 |
{
"data": [
{
"country": "SK",
"lang": "sk",
"date": "2026-10-24",
"trends": [
{ "rank": 1, "term": "bayernu mníchov vincent kompany", "score": 24, "mentions": 2,
"example_headline": "Ako dlho bude Bayernu Mníchov chýbať hlavný tréner? …" }
]
}
]
}
Events are groups of articles from different outlets about the same thing, with a stable event_id. Reprints, articles from one site and from one wire agency count as one independent source. The trend metric is transparent: mentions over 1/6/24 h, independent sources, velocity; the formula is in meta.trend_formula.
| Parameter | Required | Description |
|---|---|---|
country | no | Feed country, ISO-2 |
region | no | Event region: GeoNames code (IN.35) or name (Madhya Pradesh) |
city | no | Event city: name (Satna) or GeoNames ID |
category | no | Category slug |
lang | no | Language, ISO 639-1 |
since | no | Events updated after this moment (UTC); default: the last 48 h |
include_routine | no | 1 — retornar também conteúdos de rotina (horóscopos, loterias, calendários de feriados, programação de TV, cotações diárias); ocultos por padrão, campo routine |
min_independent | no | Minimum independent sources; default 2 |
q | no | Search in the event title |
sort | no | trend (default), recent or sources |
limit | no | Number of items, 1–100; default 20 |
offset | no | Pagination offset; default 0 |
{
"data": [
{
"id": "ev_k3v9q2m7x1a4d",
"title": "Satna: Two killed as truck rams bike near Maihar",
"country": "IN",
"lang": "en",
"category": { "slug": "society", "confidence": 0.67 },
"first_seen": "2026-10-25T09:12:40Z",
"original_published_at": "2026-10-25T08:41:00Z",
"last_updated": "2026-10-25T13:05:12Z",
"articles": 7,
"sources_total": 6,
"independent_sources": 4,
"geo": {
"source_country": "IN",
"event": { "country": "IN", "region": "Madhya Pradesh", "region_code": "IN.35", "city": "Satna",
"city_geonames_id": 1257806, "lat": 24.6, "lon": 80.83, "confidence": 0.86 }
},
"trend": { "mentions_1h": 1, "mentions_6h": 5, "mentions_24h": 7, "independent_sources_24h": 4, "velocity": 2.5, "score": 18.6 },
"evidence": { "available": true, "version": 2, "computed_at": "2026-10-25T13:20:03Z", "url": "https://trendnews.uk.app/api/v1/events/ev_k3v9q2m7x1a4d/evidence" }
}
],
"meta": { "total": 1, "limit": 20, "offset": 0, "has_more": false, "sort": "trend",
"trend_formula": "score = independent_sources_24h × log2(1 + mentions_6h) × (1 + min(velocity, 3) / 3); …" }
}
The event with all its articles: publisher, publication date and its quality (from the feed, timezone-corrected, or from the page metadata), when we first saw the article, wire agency and independence group.
| Parameter | Required | Description |
|---|---|---|
id | yes | Event ID (part of the path) |
{
"data": {
"id": "ev_k3v9q2m7x1a4d",
"title": "Satna: Two killed as truck rams bike near Maihar",
"independent_sources": 4,
"…": "усі поля з /v1/events",
"sources": [
{ "url": "https://…", "publisher": "Dainik Bhaskar", "title": "…", "lang": "hi",
"published_at": "2026-10-25T08:41:00Z", "published_at_quality": "page_metadata",
"first_seen": "2026-10-25T09:12:40Z", "agency": null, "independence_group": 1 },
{ "url": "https://…", "publisher": "…", "agency": "PTI", "independence_group": 2 },
{ "url": "https://…", "publisher": "…", "agency": "PTI", "independence_group": 2 }
]
}
}
Fatos com links para as fontes, citações, contradições, incógnitas, mudanças desde a versão anterior e um tamanho de texto recomendado. Duas camadas: extrativa (todos os planos) e refinada pelo Claude (plano Business); veja a seção "Eventos e evidências" abaixo. A primeira solicitação coloca o evento na fila (202, tente novamente em ~30 s).
| Parameter | Required | Description |
|---|---|---|
id | yes | Event ID (part of the path) |
since | no | Return in what_changed every change after this moment (UTC) |
layer | no | Camada de evidências: auto (padrão), refined (só Business) ou extractive |
{
"data": {
"event_id": "ev_k3v9q2m7x1a4d",
"version": 2,
"computed_at": "2026-10-25T13:20:03Z",
"independent_sources": 4,
"sources_read": 6,
"full_text_read": 5,
"layer": "refined",
"summary": "A speeding truck hit a motorcycle near Maihar in Satna district on Saturday morning, killing two people; police say the driver fled.",
"facts": [
{ "claim": "Two people were killed when a speeding truck hit a motorcycle near Maihar in Satna district on Saturday morning.",
"kind": "number", "status": "confirmed", "independent_sources": 3,
"sources": [ { "url": "https://…", "publisher": "…", "published_at": "2026-10-25T08:41:00Z", "snippet": "…" } ] },
{ "claim": "Police said the truck driver fled the spot.", "kind": "statement", "status": "single_source", "independent_sources": 1, "sources": [ … ] }
],
"quotes": [ { "text": "The driver fled after the accident, a search is under way", "speaker": "SP Ashutosh Gupta", "source": { "url": "https://…", "publisher": "…" } } ],
"contradictions": [ { "topic": "Three people were injured…", "versions": [ { "claim": "Three people were injured…", "source": "https://…" }, { "claim": "Four people were injured…", "source": "https://…" } ] } ],
"unknowns": [ { "statement": "The cause of the accident is not yet known.", "source": "https://…" } ],
"what_changed": { "since_version": 1, "since": "2026-10-25T10:02:11Z",
"items": [ { "type": "new_fact", "claim": "Police said the truck driver fled the spot.", "status": "single_source" } ] },
"suggested_length_words": 250,
"method": "extractive + LLM: … confirmed = cited in >= 2 independent sources (computed, not by the model)",
"llm": { "model": "claude-haiku-5-5", "input_tokens": 6050, "output_tokens": 1800 },
"stale": false
}
}
A camada de eventos agrupa os artigos de todos os feeds em eventos: uma notícia republicada por dezenas de veículos é um único evento com um único event_id. Abaixo explicamos como cada campo é calculado, para que você possa explicar os dados aos seus leitores.
Os artigos são agrupados por significado (embeddings multilíngues multilingual-e5) numa janela de 72 horas dentro do país do feed. Palavras-chave em comum e a geografia também são verificadas, para não juntar eventos diferentes sobre um tema parecido. O event_id (formato ev_ + 13 caracteres) não muda enquanto o evento é atualizado: novos artigos entram no evento existente em vez de criar um novo.
Os artigos partilham um independence_group quando vêm do mesmo site, citam a mesma agência (Reuters, AP, AFP, PTI, ANI, Ukrinform etc.) ou são cópias quase idênticas. sources_total conta todos os veículos, independent_sources conta os grupos independentes. Uma notícia de agência republicada por vinte sites conta como uma única fonte. Por padrão /v1/events retorna eventos com pelo menos 2 fontes independentes (parâmetro min_independent).
original_published_at é a data de publicação confiável mais antiga entre as fontes, first_seen é quando vimos o evento pela primeira vez. Para cada artigo, published_at_quality indica a origem da data: feed — do feed; feed_timezone_corrected — o feed deu a hora local marcada como UTC e nós a corrigimos pelo fuso horário do país; page_metadata — dos metadados da página; unknown_used_first_seen — sem data, usa-se a hora da primeira detecção.
geo.source_country é o país do feed onde o artigo foi publicado. geo.event é onde o evento aconteceu: país, região com código GeoNames (region_code, p. ex. IN.35 — Madhya Pradesh), cidade com city_geonames_id e coordenadas. Os locais são procurados em títulos e descrições no dicionário geográfico GeoNames (cidades com mais de 15 000 habitantes e regiões, incluindo formas locais). Filtros de /v1/events: region (código ou nome) e city (nome ou ID GeoNames). Se o local não for determinado com confiança, geo.event é null.
O idioma de cada artigo é detectado pelo texto (fastText) e substitui o idioma do feed quando a confiança é de pelo menos 0,8. O idioma do evento é o da maioria dos seus artigos. A categoria é uma votação dos artigos do evento; category.confidence é a parcela de votos a favor dela.
O campo trend é transparente: mentions_1h, mentions_6h, mentions_24h são artigos novos em 1, 6 e 24 horas, independent_sources_24h são grupos independentes num dia e velocity é o ritmo das últimas 6 horas em relação às 18 anteriores. A fórmula de score também é retornada em meta.trend_formula:
score = independent_sources_24h × log2(1 + mentions_6h) × (1 + min(velocity, 3) / 3)
velocity = (mentions_6h / 6) / ((mentions_24h − mentions_6h) / 18)
/v1/events/{id}/evidence lê os textos completos de até 10 fontes (primeiro as independentes, respeitando o robots.txt) e retorna fatos com links, citações, contradições, incógnitas, what_changed e suggested_length_words. Este último é um tamanho de texto recomendado: depende do número de fatos confirmados, para que a matéria não seja inflada com enchimento.
Camada extrativa (todos os planos): um fato é uma frase literal de uma fonte, e frases com o mesmo significado são agrupadas. confirmed significa que a afirmação aparece em pelo menos duas fontes independentes, single_source em uma, disputed que as fontes dão números diferentes.
Camada refinada (plano Business): o Claude reescreve as frases das fontes como fatos atômicos e adiciona um breve summary neutro. O modelo não pode acrescentar nada por conta própria: cada fato deve citar frases das fontes, um fato sem citação é descartado, snippet é uma citação literal e o status confirmed é calculado pelo sistema a partir da independência das fontes citadas, não pelo modelo. Uma contradição só é registrada quando as fontes dão valores mutuamente exclusivos para o mesmo fato.
O parâmetro layer: auto (padrão: camada refinada para Business, extrativa para os demais planos), refined (só Business; caso contrário, 403 plan_required), extractive. O campo layer da resposta indica qual camada foi retornada. A primeira solicitação de um cliente Business coloca o refinamento na fila: enquanto ele é preparado (geralmente menos de 30 s), a camada extrativa é retornada com refined_status: processing e o cabeçalho Retry-After. No plano Pro é possível experimentar a camada refinada: layer=refined para 20 eventos diferentes por mês (o restante no cabeçalho X-Refined-Trial-Remaining). Para outros planos a resposta inclui refined_layer com um link para os planos. O campo llm indica o modelo e o número de tokens.
"Confirmado" significa que pelo menos duas fontes independentes o publicaram, não que a afirmação seja verdadeira. Em temas sensíveis, confira as fontes originais pelos links em sources.
Os eventos são recalculados a cada hora junto com a coleta de notícias. As evidências são atualizadas automaticamente para eventos com 3 ou mais fontes independentes e para eventos cujo refinamento um cliente Business solicitou nas últimas 24 horas. stale: true significa que chegaram artigos novos após o último cálculo e a atualização já está na fila. Artigos, eventos e evidências são mantidos por 3 dias após a última atualização; posts e tendências, por mais tempo.
Em vez de consultar a API, receba um POST com JSON no seu endereço https. Configure no painel, aba “Webhooks”: endereço, países, mínimo de fontes independentes e tipos de eventos. event.created é enviado uma vez, quando um evento atinge o seu número de fontes independentes; evidence.updated, quando as evidências mudam (com what_changed; para Business, a camada refinada quando houver).
Cada solicitação é assinada: cabeçalho X-TrendNews-Signature: t=<hora unix>,v1=<hex>, onde v1 = HMAC-SHA256 de <t>.<corpo bruto> com o seu segredo. Verifique a assinatura e rejeite solicitações com mais de 5 minutos. Responda com 2xx em até 8 segundos; caso contrário, tentamos de novo após 1, 5, 30, 120 e 360 minutos. X-TrendNews-Delivery é um id único de entrega para evitar duplicatas.
Exemplo de corpo event.created:
{
"type": "event.created",
"created_at": "2026-10-25T18:04:11Z",
"data": {
"id": "ev_aacw4p3jhkye6", "title": "Storm Boelo brings 80mph gusts and travel disruption to Scotland",
"country": "GB", "lang": "en", "category": "society",
"first_seen": "2026-10-23T18:16:53Z", "original_published_at": "2026-10-23T18:16:53Z",
"independent_sources": 17, "sources_total": 22,
"geo": { "country": "GB", "region": "Scotland", "region_code": "GB.SCT", "city": null },
"api_url": "https://trendnews.uk.app/api/v1/events/ev_aacw4p3jhkye6",
"evidence_url": "https://trendnews.uk.app/api/v1/events/ev_aacw4p3jhkye6/evidence",
"page_url": "https://trendnews.uk.app/event.php?id=ev_aacw4p3jhkye6"
}
}
Verificação da assinatura (PHP):
$body = file_get_contents('php://input');
preg_match('/t=(\d+),v1=([0-9a-f]{64})/', $_SERVER['HTTP_X_TRENDNEWS_SIGNATURE'] ?? '', $m);
$ok = $m && abs(time() - (int)$m[1]) < 300
&& hash_equals(hash_hmac('sha256', $m[1] . '.' . $body, getenv('TRENDNEWS_WEBHOOK_SECRET')), $m[2]);
if (!$ok) { http_response_code(401); exit; }
$event = json_decode($body, true); // handle $event['type'] … then
http_response_code(204);
Uma busca salva é uma consulta que executamos a cada hora sobre as notícias novas. Os resultados ficam guardados 30 dias e estão disponíveis no seu RSS privado (rss_url), pela API e — no Business — num webhook do tipo watch.match. Limites: Free — 1 busca, Pro — 10, Business — 100. Crie buscas na sua conta ou pela API.
Sintaxe: as palavras separadas por espaços devem aparecer todas (no título ou no lead); "frase exata"; OR para alternativas; -palavra para excluir. O modo events envia cada evento com resultado e pelo menos min_sources fontes independentes (2 ou mais); o modo articles, cada artigo novo correspondente.
# create
curl -X POST -H "X-API-Key: $KEY" -H "Content-Type: application/json" \
-d '{"query": "\"green hydrogen\" OR electrolyser", "countries": ["DE","NL"], "mode": "events", "min_sources": 2}' \
https://trendnews.uk.app/api/v1/watches
# list, one, delete
curl -H "X-API-Key: $KEY" https://trendnews.uk.app/api/v1/watches
curl -H "X-API-Key: $KEY" https://trendnews.uk.app/api/v1/watches/12
curl -X DELETE -H "X-API-Key: $KEY" https://trendnews.uk.app/api/v1/watches/12
# new hits since the last one you have
curl -H "X-API-Key: $KEY" "https://trendnews.uk.app/api/v1/watches/12/hits?since_id=3051&limit=100"
Exemplo de corpo watch.match:
{
"type": "watch.match",
"created_at": "2026-10-26T19:12:40Z",
"data": {
"watch": { "id": 12, "name": "Hydrogen", "query": "\"green hydrogen\" OR electrolyser" },
"hit": { "kind": "event", "id": "ev_x8ox05csqqyae", "title": "…", "url": "https://trendnews.uk.app/event.php?id=ev_x8ox05csqqyae",
"country": "DE", "lang": "de", "independent_sources": 3, "published_at": "2026-10-26T17:40:02Z",
"api_url": "https://trendnews.uk.app/api/v1/events/ev_x8ox05csqqyae" }
}
}
A primeira execução de uma busca nova preenche o RSS com os resultados do último dia sem enviá-los ao webhook; depois, ao webhook chega apenas o que é novo. Assinatura e novas tentativas funcionam como nos outros webhooks.
Preços de Bitcoin, Ethereum, Solana, XRP, ouro, prata, petróleo Brent, S&P 500, Nasdaq, EUR/USD e USD/UAH junto com as notícias que os pressionam. O Claude marca cada evento com pelo menos duas fontes independentes: de qual ativo se trata, para onde pressiona o preço (up, down, neutral) e quão importante é (impact 1–3). Preços da Binance e do Yahoo Finance, atualizados a cada 15 minutos.
| Consulta | Retorna |
|---|---|
GET /v1/markets | Todos os ativos: preço, variação em 1 h / 24 h / 7 dias, news_24h — quantas notícias pressionam para cima e para baixo e o saldo score de −1 a 1, o último movimento brusco. |
GET /v1/markets/{asset} | Um ativo, suas notícias das últimas hours horas (48 por padrão) e os 5 últimos movimentos bruscos. |
GET /v1/markets/{asset}/prices | Candles OHLC: res=1h (até 120 dias) ou res=1d (até 2 anos), parâmetro limit. |
GET /v1/markets/{asset}/moves | Movimentos bruscos: um candle de uma hora além do limite do ativo (de 0,5% para EUR/USD a 3% para Solana e XRP). O Claude escreve a explicação apenas com as manchetes em torno do movimento; lang — en, uk, es, pt, de, fr. |
GET /v1/markets/{asset}/news | Notícias sobre o ativo com direção e peso; parâmetros hours e limit. |
Ativos: bitcoin, ethereum, solana, xrp, gold, silver, brent, sp500, nasdaq, eurusd, usduah. Os mesmos dados estão na página https://trendnews.uk.app/markets/.
curl -H "X-API-Key: YOUR_KEY" "https://trendnews.uk.app/api/v1/markets/bitcoin/moves?lang=en&limit=5"
A relação entre as notícias e o preço é provável, não comprovada. Isto não é aconselhamento de investimento.
O TrendNews tem um servidor MCP (Model Context Protocol): um agente de IA — Claude, Cursor ou o seu próprio — busca eventos, lê evidências com citações, consulta tendências e gerencia buscas salvas por conta própria. Endereço: https://trendnews.uk.app/mcp (Streamable HTTP). A autorização é a mesma chave de API no cabeçalho X-API-Key; cada chamada de ferramenta conta como uma requisição à API na cota do seu plano.
Ferramentas: search_events, get_event, get_event_evidence, get_trends, list_digests, list_countries, get_markets, explain_price_moves, list_saved_searches, create_saved_search, get_saved_search_hits.
# Claude Code
claude mcp add --transport http trendnews https://trendnews.uk.app/mcp --header "X-API-Key: YOUR_KEY"
# Cursor, Windsurf, Claude Desktop… (mcp.json)
{
"mcpServers": {
"trendnews": {
"url": "https://trendnews.uk.app/mcp",
"headers": { "X-API-Key": "YOUR_KEY" }
}
}
}
O servidor informa ao agente que «confirmado» significa «noticiado por pelo menos duas fontes independentes», não «verdadeiro», e pede que cite as fontes originais.
Get the 10 latest economy posts for Ukraine:
curl -H "X-API-Key: $TN_KEY" \
"https://trendnews.uk.app/api/v1/posts?country=UA&category=economy&limit=10"
// Node.js 18+ (on the server — not in the browser)
const res = await fetch(
"https://trendnews.uk.app/api/v1/posts?country=UA&category=economy&limit=10",
{ headers: { "X-API-Key": process.env.TN_KEY } }
);
if (!res.ok) throw new Error((await res.json()).error.message);
const { data, meta } = await res.json();
data.forEach(p => console.log(p.date, p.title, p.url));
$ch = curl_init('https://trendnews.uk.app/api/v1/posts?country=UA&category=economy&limit=10');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['X-API-Key: ' . getenv('TN_KEY')],
CURLOPT_TIMEOUT => 10,
]);
$body = json_decode(curl_exec($ch), true);
$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($code !== 200) throw new RuntimeException($body['error']['message'] ?? "HTTP $code");
foreach ($body['data'] as $p) echo $p['date'], ' ', $p['title'], PHP_EOL;
import os, requests
r = requests.get(
"https://trendnews.uk.app/api/v1/posts",
params={"country": "UA", "category": "economy", "limit": 10},
headers={"X-API-Key": os.environ["TN_KEY"]},
timeout=10,
)
r.raise_for_status()
for p in r.json()["data"]:
print(p["date"], p["title"], p["url"])
Iterate over all result pages:
offset = 0
while True:
page = requests.get(f"{BASE}/api/v1/posts", params={"country": "GB", "limit": 100, "offset": offset},
headers={"X-API-Key": KEY}, timeout=10).json()
handle(page["data"])
if not page["meta"]["has_more"]:
break
offset += 100
You can create a key in your account. The request goes straight from your browser. The key is not stored anywhere and is gone after a page reload.