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
| Offre | 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 — renvoyer aussi les contenus de routine (horoscopes, loteries, fêtes du jour, programmes TV, cours quotidiens) ; masqués par défaut, champ 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 }
]
}
}
Faits avec liens vers les sources, citations, contradictions, inconnues, changements depuis la version précédente et longueur de texte conseillée. Deux couches : extractive (tous les forfaits) et affinée par Claude (forfait Business) — voir la section « Événements et preuves » ci-dessous. La première requête met l'événement en file d'attente (202, réessayez dans ~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 | Couche de preuves : auto (par défaut), refined (Business uniquement) 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
}
}
La couche des événements regroupe les articles de tous les flux en événements : une information reprise par des dizaines de médias est un seul événement avec un seul event_id. Voici comment chaque champ est calculé, pour que vous puissiez expliquer les données à vos lecteurs.
Les articles sont regroupés par sens (embeddings multilingues multilingual-e5) dans une fenêtre de 72 heures au sein du pays du flux. Les mots-clés communs et la géographie sont aussi vérifiés pour ne pas fusionner des événements différents sur un sujet proche. L'event_id (format ev_ + 13 caractères) ne change pas tant que l'événement est mis à jour : les nouveaux articles rejoignent l'événement existant au lieu d'en créer un nouveau.
Les articles partagent un independence_group lorsqu'ils viennent du même site, citent la même agence (Reuters, AP, AFP, PTI, ANI, Ukrinform, etc.) ou sont des copies quasi identiques. sources_total compte tous les médias, independent_sources les groupes indépendants. Une dépêche reprise par vingt sites compte comme une seule source. Par défaut, /v1/events renvoie les événements ayant au moins 2 sources indépendantes (paramètre min_independent).
original_published_at est la date de publication fiable la plus ancienne parmi les sources, first_seen le moment où nous avons vu l'événement pour la première fois. Pour chaque article, published_at_quality indique l'origine de la date : feed — du flux ; feed_timezone_corrected — le flux donnait l'heure locale étiquetée UTC et nous l'avons corrigée selon le fuseau du pays ; page_metadata — des métadonnées de la page ; unknown_used_first_seen — pas de date, l'heure de première détection est utilisée.
geo.source_country est le pays du flux où l'article a été publié. geo.event indique où l'événement a eu lieu : pays, région avec un code GeoNames (region_code, p. ex. IN.35 — Madhya Pradesh), ville avec city_geonames_id et coordonnées. Les lieux sont repérés dans les titres et descriptions grâce au référentiel GeoNames (villes de plus de 15 000 habitants et régions, y compris les formes locales). Filtres de /v1/events : region (code ou nom) et city (nom ou identifiant GeoNames). Si le lieu n'est pas déterminé avec assurance, geo.event vaut null.
La langue de chaque article est détectée d'après son texte (fastText) et remplace celle du flux si la confiance est d'au moins 0,8. La langue de l'événement est celle de la majorité de ses articles. La catégorie résulte d'un vote des articles de l'événement ; category.confidence est la part des votes en sa faveur.
Le champ trend est transparent : mentions_1h, mentions_6h, mentions_24h sont les nouveaux articles sur 1, 6 et 24 heures, independent_sources_24h les groupes indépendants sur une journée, velocity le rythme des 6 dernières heures par rapport aux 18 précédentes. La formule de score est aussi renvoyée dans 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 lit les textes complets de jusqu'à 10 sources (indépendantes d'abord, dans le respect de robots.txt) et renvoie des faits avec liens, citations, contradictions, inconnues, what_changed et suggested_length_words. Ce dernier est une longueur de texte conseillée : elle dépend du nombre de faits confirmés, pour ne pas délayer l'article.
Couche extractive (tous les forfaits) : un fait est une phrase citée mot pour mot d'une source, et les phrases de même sens sont regroupées. confirmed signifie que l'affirmation figure dans au moins deux sources indépendantes, single_source dans une seule, disputed que les sources donnent des chiffres différents.
Couche affinée (forfait Business) : Claude reformule les phrases des sources en faits atomiques et ajoute un court summary neutre. Le modèle ne peut rien ajouter de lui-même : chaque fait doit citer des phrases des sources, un fait sans citation est écarté, snippet est une citation mot pour mot, et le statut confirmed est calculé par le système selon l'indépendance des sources citées, pas par le modèle. Une contradiction n'est signalée que lorsque des sources donnent des valeurs qui s'excluent pour le même fait.
Le paramètre layer : auto (par défaut : couche affinée pour Business, extractive pour les autres forfaits), refined (Business uniquement, sinon 403 plan_required), extractive. Le champ layer de la réponse indique la couche renvoyée. La première requête d'un client Business met l'affinage en file d'attente : pendant sa préparation (généralement moins de 30 s), la couche extractive est renvoyée avec refined_status: processing et l'en-tête Retry-After. Au forfait Pro, vous pouvez essayer la couche affinée : layer=refined pour 20 événements différents par mois (le reste dans l'en-tête X-Refined-Trial-Remaining). Pour les autres forfaits, la réponse contient refined_layer avec un lien vers les forfaits. Le champ llm indique le modèle et le nombre de tokens.
« Confirmé » signifie qu'au moins deux sources indépendantes l'ont rapporté, pas que l'affirmation est vraie. Pour les sujets sensibles, vérifiez les sources d'origine via les liens de sources.
Les événements sont recalculés toutes les heures avec la collecte des actualités. Les preuves sont actualisées automatiquement pour les événements ayant 3 sources indépendantes ou plus et pour ceux dont un client Business a demandé l'affinage au cours des dernières 24 heures. stale: true signifie que de nouveaux articles sont arrivés depuis le dernier calcul et qu'une mise à jour est déjà en file d'attente. Articles, événements et preuves sont conservés 3 jours après leur dernière mise à jour ; les posts et tendances, plus longtemps.
Au lieu d'interroger l'API, recevez un POST avec du JSON à votre adresse https. Configuration dans l'espace client, onglet « Webhooks » : adresse, pays, minimum de sources indépendantes et types d'événements. event.created est envoyé une fois, lorsqu'un événement atteint votre nombre de sources indépendantes ; evidence.updated lorsque ses preuves changent (avec what_changed ; pour Business, la couche affinée si elle existe).
Chaque requête est signée : en-tête X-TrendNews-Signature: t=<heure unix>,v1=<hex>, où v1 = HMAC-SHA256 de <t>.<corps brut> avec votre secret. Vérifiez la signature et rejetez les requêtes de plus de 5 minutes. Répondez en 2xx sous 8 secondes ; sinon nous réessayons après 1, 5, 30, 120 et 360 minutes. X-TrendNews-Delivery est un identifiant unique de livraison contre les doublons.
Exemple de corps 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"
}
}
Vérification de la signature (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);
Une recherche enregistrée est une requête que nous relançons chaque heure sur les nouvelles actualités. Les résultats sont conservés 30 jours et disponibles dans votre RSS privé (rss_url), via l'API et — avec Business — dans un webhook de type watch.match. Limites : Free — 1 recherche, Pro — 10, Business — 100. Créez-les dans votre compte ou via l'API.
Syntaxe : les mots séparés par des espaces doivent tous apparaître (dans le titre ou le chapô) ; "phrase exacte" ; OR pour les alternatives ; -mot pour exclure. Le mode events envoie chaque événement avec une correspondance et au moins min_sources sources indépendantes (2 ou plus) ; le mode articles, chaque nouvel article correspondant.
# 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"
Exemple de corps 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" }
}
}
La première exécution d'une nouvelle recherche remplit le RSS avec les résultats de la dernière journée sans les envoyer au webhook ; ensuite seuls les nouveaux résultats y sont envoyés. Signature et nouvelles tentatives comme pour les autres webhooks.
Cours du Bitcoin, d'Ethereum, de Solana, de XRP, de l'or, de l'argent, du pétrole Brent, du S&P 500, du Nasdaq, de l'EUR/USD et de l'USD/UAH avec l'actualité qui les fait bouger. Claude étiquette chaque événement ayant au moins deux sources indépendantes : de quel actif il s'agit, dans quel sens il pousse le cours (up, down, neutral) et son importance (impact 1–3). Cours issus de Binance et Yahoo Finance, actualisés toutes les 15 minutes.
| Requête | Renvoie |
|---|---|
GET /v1/markets | Tous les actifs : cours, variation sur 1 h / 24 h / 7 jours, news_24h — combien d'actualités poussent à la hausse et à la baisse et le solde score de −1 à 1, le dernier mouvement brusque. |
GET /v1/markets/{asset} | Un actif, ses actualités des hours dernières heures (48 par défaut) et les 5 derniers mouvements brusques. |
GET /v1/markets/{asset}/prices | Bougies OHLC : res=1h (jusqu'à 120 jours) ou res=1d (jusqu'à 2 ans), paramètre limit. |
GET /v1/markets/{asset}/moves | Mouvements brusques : une bougie horaire au-delà du seuil de l'actif (de 0,5 % pour EUR/USD à 3 % pour Solana et XRP). Claude rédige l'explication uniquement à partir des titres autour du mouvement ; lang — en, uk, es, pt, de, fr. |
GET /v1/markets/{asset}/news | Actualités sur l'actif avec direction et poids ; paramètres hours et limit. |
Actifs : bitcoin, ethereum, solana, xrp, gold, silver, brent, sp500, nasdaq, eurusd, usduah. Les mêmes données sont sur la page 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"
Le lien entre l'actualité et le cours est probable, non prouvé. Ceci n'est pas un conseil en investissement.
TrendNews dispose d'un serveur MCP (Model Context Protocol) : un agent IA — Claude, Cursor ou le vôtre — recherche lui-même des événements, lit les preuves avec citations, consulte les tendances et gère les recherches enregistrées. Adresse : https://trendnews.uk.app/mcp (Streamable HTTP). L'autorisation se fait avec la même clé API dans l'en-tête X-API-Key ; chaque appel d'outil compte comme une requête API dans le quota de votre offre.
Outils : 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" }
}
}
}
Le serveur indique à l'agent que « confirmé » signifie « rapporté par au moins deux sources indépendantes », et non « vrai », et lui demande de citer les sources d'origine.
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.