Recent Activity API
Recent endpoints return the latest data entries sorted by date across all tracked stocks. Use these endpoints to stay on top of breaking news and fresh analyst actions without querying tickers individually.
Authentication
Section titled “Authentication”Supports multiple authentication methods (in order of preference):
| Method | Example |
|---|---|
| Bearer token (recommended) | Authorization: Bearer YOUR_API_KEY |
| X-API-Key header | X-API-Key: YOUR_API_KEY |
| Query parameter | ?apiKey=YOUR_API_KEY |
| Legacy query parameter | ?token=YOUR_API_KEY |
Endpoints
Section titled “Endpoints”| Endpoint | Description |
|---|---|
GET /v2/recent/news | Most recent news articles |
GET /v2/recent/analyst-ratings | Most recent analyst ratings |
Common Query Parameters
Section titled “Common Query Parameters”| Parameter | Type | Required | Description |
|---|---|---|---|
apiKey | string | No | Your API key (if not using header auth) |
limit | integer | No | Number of results to return (1-20,000, default 100) |
market | string | No | Filter by market name (e.g., NASDAQ, S&P 500) |
region | string | No | Filter by region code (e.g., US, UK) |
Request
Section titled “Request”Recent News
Section titled “Recent News”from finbrain import FinBrainClient
fb = FinBrainClient(api_key="YOUR_API_KEY")
# Recent newsdf = fb.recent.news(limit=20, as_dataframe=True)print(df)
# Recent analyst ratingsdf = fb.recent.analyst_ratings(limit=10, as_dataframe=True)print(df)# Get 100 most recent news articles (default)curl -H "Authorization: Bearer YOUR_API_KEY" \ "https://api.finbrain.tech/v2/recent/news"
# Filter by market with custom limitcurl -H "Authorization: Bearer YOUR_API_KEY" \ "https://api.finbrain.tech/v2/recent/news?market=NASDAQ&limit=50"import requests
headers = {"Authorization": "Bearer YOUR_API_KEY"}
# Get 100 most recent news articles (default)response = requests.get( "https://api.finbrain.tech/v2/recent/news", headers=headers)result = response.json()
for article in result["data"]["data"]: print(f"{article['symbol']} - {article['headline']} " f"(sentiment: {article['sentiment']:.3f})")
# Filter by marketresponse = requests.get( "https://api.finbrain.tech/v2/recent/news", headers=headers, params={"market": "NASDAQ", "limit": 50})result = response.json()print(f"Total articles: {result['data']['summary']['totalArticles']}")#include <iostream>#include <string>#include <curl/curl.h>#include <nlohmann/json.hpp>
using json = nlohmann::json;
size_t WriteCallback(void* contents, size_t size, size_t nmemb, std::string* userp) { userp->append((char*)contents, size * nmemb); return size * nmemb;}
json get_recent_news(int limit, const std::string& api_key) { CURL* curl = curl_easy_init(); std::string response;
if (curl) { std::string url = "https://api.finbrain.tech/v2/recent/news?limit=" + std::to_string(limit);
struct curl_slist* headers = nullptr; std::string auth_header = "Authorization: Bearer " + api_key; headers = curl_slist_append(headers, auth_header.c_str());
curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback); curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response); curl_easy_perform(curl); curl_slist_free_all(headers); curl_easy_cleanup(curl); }
return json::parse(response);}
int main() { auto result = get_recent_news(100, "YOUR_API_KEY");
for (auto& article : result["data"]["data"]) { std::cout << article["symbol"].get<std::string>() << " - " << article["headline"].get<std::string>() << " (" << article["sentiment"].get<double>() << ")" << std::endl; }
return 0;}use reqwest::blocking::Client;use serde::Deserialize;use std::error::Error;
#[derive(Debug, Deserialize)]struct RecentNewsResponse { success: bool, data: RecentNewsData,}
#[derive(Debug, Deserialize)]struct RecentNewsData { data: Vec<NewsEntry>, summary: NewsSummary,}
#[derive(Debug, Deserialize)]struct NewsEntry { symbol: String, name: String, date: String, headline: String, source: String, url: String, sentiment: f64,}
#[derive(Debug, Deserialize)]struct NewsSummary { #[serde(rename = "totalArticles")] total_articles: i64, #[serde(rename = "totalTickers")] total_tickers: i64, #[serde(rename = "averageSentiment")] average_sentiment: f64,}
fn get_recent_news(limit: i32, api_key: &str) -> Result<RecentNewsResponse, Box<dyn Error>> { let url = format!( "https://api.finbrain.tech/v2/recent/news?limit={}", limit );
let client = Client::new(); let response: RecentNewsResponse = client .get(&url) .bearer_auth(api_key) .send()? .json()?;
Ok(response)}
fn main() -> Result<(), Box<dyn Error>> { let result = get_recent_news(100, "YOUR_API_KEY")?;
for article in &result.data.data { println!("{} - {} (sentiment: {:.3})", article.symbol, article.headline, article.sentiment); }
println!("Total articles: {}", result.data.summary.total_articles);
Ok(())}const response = await fetch( "https://api.finbrain.tech/v2/recent/news?limit=100", { headers: { "Authorization": "Bearer YOUR_API_KEY" } });const result = await response.json();
for (const article of result.data.data) { console.log(`${article.symbol} - ${article.headline} (sentiment: ${article.sentiment})`);}
console.log(`Total articles: ${result.data.summary.totalArticles}`);Recent Analyst Ratings
Section titled “Recent Analyst Ratings”# Get 100 most recent analyst ratings (default)curl -H "Authorization: Bearer YOUR_API_KEY" \ "https://api.finbrain.tech/v2/recent/analyst-ratings"
# Filter by regioncurl -H "Authorization: Bearer YOUR_API_KEY" \ "https://api.finbrain.tech/v2/recent/analyst-ratings?region=US&limit=200"import requests
headers = {"Authorization": "Bearer YOUR_API_KEY"}
response = requests.get( "https://api.finbrain.tech/v2/recent/analyst-ratings", headers=headers, params={"limit": 200})result = response.json()
for rating in result["data"]["data"]: print(f"{rating['symbol']} - {rating['institution']}: " f"{rating['action']} ({rating['rating']}) " f"Target: {rating['targetPrice']}")
summary = result["data"]["summary"]print(f"\nUpgrades: {summary['upgradeCount']}, " f"Downgrades: {summary['downgradeCount']}")#include <iostream>#include <string>#include <curl/curl.h>#include <nlohmann/json.hpp>
using json = nlohmann::json;
size_t WriteCallback(void* contents, size_t size, size_t nmemb, std::string* userp) { userp->append((char*)contents, size * nmemb); return size * nmemb;}
json get_recent_analyst_ratings(int limit, const std::string& api_key) { CURL* curl = curl_easy_init(); std::string response;
if (curl) { std::string url = "https://api.finbrain.tech/v2/recent/analyst-ratings?limit=" + std::to_string(limit);
struct curl_slist* headers = nullptr; std::string auth_header = "Authorization: Bearer " + api_key; headers = curl_slist_append(headers, auth_header.c_str());
curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback); curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response); curl_easy_perform(curl); curl_slist_free_all(headers); curl_easy_cleanup(curl); }
return json::parse(response);}
int main() { auto result = get_recent_analyst_ratings(200, "YOUR_API_KEY");
for (auto& rating : result["data"]["data"]) { std::cout << rating["symbol"].get<std::string>() << " - " << rating["institution"].get<std::string>() << ": " << rating["action"].get<std::string>() << " (" << rating["rating"].get<std::string>() << ") " << "Target: " << rating["targetPrice"].get<std::string>() << std::endl; }
return 0;}use reqwest::blocking::Client;use serde::Deserialize;use std::error::Error;
#[derive(Debug, Deserialize)]struct AnalystRatingsResponse { success: bool, data: AnalystRatingsData,}
#[derive(Debug, Deserialize)]struct AnalystRatingsData { data: Vec<RatingEntry>, summary: RatingsSummary,}
#[derive(Debug, Deserialize)]struct RatingEntry { symbol: String, name: String, date: String, institution: String, action: String, rating: String, #[serde(rename = "targetPrice")] target_price: String,}
#[derive(Debug, Deserialize)]struct RatingsSummary { #[serde(rename = "totalRatings")] total_ratings: i64, #[serde(rename = "totalTickers")] total_tickers: i64, #[serde(rename = "upgradeCount")] upgrade_count: i64, #[serde(rename = "downgradeCount")] downgrade_count: i64,}
fn get_recent_analyst_ratings(limit: i32, api_key: &str) -> Result<AnalystRatingsResponse, Box<dyn Error>> { let url = format!( "https://api.finbrain.tech/v2/recent/analyst-ratings?limit={}", limit );
let client = Client::new(); let response: AnalystRatingsResponse = client .get(&url) .bearer_auth(api_key) .send()? .json()?;
Ok(response)}
fn main() -> Result<(), Box<dyn Error>> { let result = get_recent_analyst_ratings(200, "YOUR_API_KEY")?;
for rating in &result.data.data { println!("{} - {}: {} ({}) Target: {}", rating.symbol, rating.institution, rating.action, rating.rating, rating.target_price); }
println!("Upgrades: {}, Downgrades: {}", result.data.summary.upgrade_count, result.data.summary.downgrade_count);
Ok(())}const response = await fetch( "https://api.finbrain.tech/v2/recent/analyst-ratings?limit=200", { headers: { "Authorization": "Bearer YOUR_API_KEY" } });const result = await response.json();
for (const rating of result.data.data) { console.log(`${rating.symbol} - ${rating.institution}: ${rating.action} (${rating.rating}) Target: ${rating.targetPrice}`);}
const { upgradeCount, downgradeCount } = result.data.summary;console.log(`Upgrades: ${upgradeCount}, Downgrades: ${downgradeCount}`);Responses
Section titled “Responses”Recent News Response (200 OK)
Section titled “Recent News Response (200 OK)”{ "success": true, "data": { "data": [ { "symbol": "VRT", "name": "Vertiv Holdings Co", "date": "2026-01-19", "headline": "Amazon, Carvana And Others: Bank Of America Reveals 5 Stocks", "source": "Benzinga", "url": "https://www.benzinga.com/news/280015", "sentiment": 0.6705 } ], "summary": { "totalArticles": 100, "totalTickers": 87, "averageSentiment": 0.42 } }, "meta": { "timestamp": "2026-01-19T15:23:13.813Z" }}News Entry Fields
Section titled “News Entry Fields”| Field | Type | Description |
|---|---|---|
symbol | string | Stock ticker symbol |
name | string | Company name |
date | string | Article date (YYYY-MM-DD) |
headline | string | News article headline |
source | string | News source (e.g., Benzinga, Reuters) |
url | string | Link to the original article |
sentiment | number | Sentiment score from -1 (bearish) to 1 (bullish) |
News Summary Fields
Section titled “News Summary Fields”| Field | Type | Description |
|---|---|---|
totalArticles | integer | Total number of articles returned |
totalTickers | integer | Number of unique tickers mentioned |
averageSentiment | number | Average sentiment across all articles |
Recent Analyst Ratings Response (200 OK)
Section titled “Recent Analyst Ratings Response (200 OK)”{ "success": true, "data": { "data": [ { "symbol": "AFYA", "name": "Afya Ltd", "date": "2026-01-16", "institution": "UBS", "action": "Downgrade", "rating": "Buy → Neutral", "targetPrice": "$16" } ], "summary": { "totalRatings": 100, "totalTickers": 95, "upgradeCount": 18, "downgradeCount": 12 } }, "meta": { "timestamp": "2026-01-19T15:23:11.771Z" }}Analyst Rating Entry Fields
Section titled “Analyst Rating Entry Fields”| Field | Type | Description |
|---|---|---|
symbol | string | Stock ticker symbol |
name | string | Company name |
date | string | Rating date (YYYY-MM-DD) |
institution | string | Analyst firm (e.g., UBS, Goldman Sachs) |
action | string | Rating action (e.g., Upgrade, Downgrade, Initiate, Reiterate) |
rating | string | Rating change (e.g., “Buy to Neutral”) |
targetPrice | string | Price target set by the analyst |
Analyst Ratings Summary Fields
Section titled “Analyst Ratings Summary Fields”| Field | Type | Description |
|---|---|---|
totalRatings | integer | Total number of ratings returned |
totalTickers | integer | Number of unique tickers with ratings |
upgradeCount | integer | Number of upgrades |
downgradeCount | integer | Number of downgrades |
Usage Examples
Section titled “Usage Examples”News Sentiment Monitor
Section titled “News Sentiment Monitor”import requests
headers = {"Authorization": "Bearer YOUR_API_KEY"}
response = requests.get( "https://api.finbrain.tech/v2/recent/news", headers=headers, params={"limit": 500})result = response.json()
# Group articles by tickerfrom collections import defaultdictby_ticker = defaultdict(list)for article in result["data"]["data"]: by_ticker[article["symbol"]].append(article)
# Find tickers with the most news activityprint("Most mentioned tickers:")for symbol, articles in sorted(by_ticker.items(), key=lambda x: -len(x[1]))[:10]: avg_sentiment = sum(a["sentiment"] for a in articles) / len(articles) print(f" {symbol:>6}: {len(articles)} articles, avg sentiment {avg_sentiment:.3f}")Track Analyst Upgrades and Downgrades
Section titled “Track Analyst Upgrades and Downgrades”import requests
headers = {"Authorization": "Bearer YOUR_API_KEY"}
response = requests.get( "https://api.finbrain.tech/v2/recent/analyst-ratings", headers=headers, params={"limit": 500})result = response.json()
upgrades = [r for r in result["data"]["data"] if r["action"] == "Upgrade"]downgrades = [r for r in result["data"]["data"] if r["action"] == "Downgrade"]
print(f"Recent Upgrades ({len(upgrades)}):")for r in upgrades[:5]: print(f" {r['symbol']:>6} - {r['institution']}: {r['rating']} (Target: {r['targetPrice']})")
print(f"\nRecent Downgrades ({len(downgrades)}):")for r in downgrades[:5]: print(f" {r['symbol']:>6} - {r['institution']}: {r['rating']} (Target: {r['targetPrice']})")Errors
Section titled “Errors”| Code | Error | Description |
|---|---|---|
| 400 | Bad Request | Invalid parameters |
| 401 | Unauthorized | Invalid or missing API key |
| 404 | Not Found | Endpoint not found |
| 500 | Internal Server Error | Server-side error |
Related
Section titled “Related”- Sentiments API - Get sentiment for a single ticker
- Analyst Ratings API - Get analyst ratings for a single ticker
- Screener API - Screen and filter across multiple tickers
- News Sentiment Dataset - Use cases and analysis examples
- Analyst Ratings Dataset - Use cases and analysis examples