FinnHub financial data API integration for stocks, forex, crypto, news, and fundamentals. Use when fetching real-time quotes, company profiles, financial statements, insider trading, earnings calendars, or market news.
67
81%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Low
Low-risk findings worth noting
The canonical home for this skill is finnhub-api in fernandezbaptiste/Skrillz
Complete integration with FinnHub's financial data API providing access to stocks, forex, crypto, company fundamentals, news, and real-time market data.
# Environment variable (recommended)
export FINNHUB_API_KEY="your_api_key"
# Or in .env file
FINNHUB_API_KEY=your_api_keyimport requests
import os
API_KEY = os.getenv("FINNHUB_API_KEY")
BASE_URL = "https://finnhub.io/api/v1"
def get_quote(symbol: str) -> dict:
"""Get real-time quote for a symbol."""
response = requests.get(
f"{BASE_URL}/quote",
params={"symbol": symbol, "token": API_KEY}
)
return response.json()
# Example
quote = get_quote("AAPL")
print(f"AAPL: ${quote['c']:.2f} ({quote['dp']:+.2f}%)")import finnhub
client = finnhub.Client(api_key="your_api_key")
# Get quote
quote = client.quote("AAPL")
# Get company profile
profile = client.company_profile2(symbol="AAPL")
# Get financials
financials = client.company_basic_financials("AAPL", "all")| Endpoint | Description | Free |
|---|---|---|
/quote | Real-time quote | ✅ |
/stock/candle | Historical OHLCV | ✅ |
/stock/profile2 | Company profile | ✅ |
/stock/peers | Similar companies | ✅ |
/company-news | Company news | ✅ |
/stock/metric | Basic financials | ✅ |
/stock/financials | Financial statements | ✅ |
/stock/insider-transactions | Insider trades | ⚠️ Premium |
/stock/insider-sentiment | Insider sentiment | ⚠️ Premium |
| Endpoint | Description | Free |
|---|---|---|
/stock/financials-reported | SEC reported | ✅ |
/stock/earnings | Earnings history | ✅ |
/stock/recommendation | Analyst ratings | ✅ |
/stock/price-target | Price targets | ✅ |
/stock/revenue-estimate | Revenue estimates | ⚠️ Premium |
/stock/eps-estimate | EPS estimates | ⚠️ Premium |
| Endpoint | Description | Free |
|---|---|---|
/forex/rates | Exchange rates | ✅ |
/forex/candle | Forex OHLCV | ✅ |
/crypto/candle | Crypto OHLCV | ✅ |
/crypto/exchanges | Crypto exchanges | ✅ |
/crypto/symbol | Crypto symbols | ✅ |
| Endpoint | Description | Free |
|---|---|---|
/company-news | Company news | ✅ |
/news | Market news | ✅ |
/press-releases | Press releases | ⚠️ Premium |
/news-sentiment | News sentiment | ⚠️ Premium |
| Endpoint | Description | Free |
|---|---|---|
/calendar/earnings | Earnings calendar | ✅ |
/calendar/ipo | IPO calendar | ✅ |
/stock/dividends | Dividend history | ✅ |
/stock/splits | Stock splits | ✅ |
| Tier | Calls/Minute | Notes |
|---|---|---|
| Free | 60 | US stocks, forex, crypto |
| Paid | 300+ | Per-market pricing |
Rate limit headers:
X-Ratelimit-Limit: Max calls per minuteX-Ratelimit-Remaining: Calls remainingX-Ratelimit-Reset: Reset timestampdef get_stock_info(symbol: str) -> dict:
"""Get comprehensive stock info."""
quote = requests.get(
f"{BASE_URL}/quote",
params={"symbol": symbol, "token": API_KEY}
).json()
profile = requests.get(
f"{BASE_URL}/stock/profile2",
params={"symbol": symbol, "token": API_KEY}
).json()
return {
"symbol": symbol,
"name": profile.get("name"),
"price": quote["c"],
"change": quote["d"],
"change_percent": quote["dp"],
"high": quote["h"],
"low": quote["l"],
"market_cap": profile.get("marketCapitalization"),
"industry": profile.get("finnhubIndustry")
}import time
def get_candles(symbol: str, resolution: str = "D", days: int = 30) -> dict:
"""
Get historical OHLCV data.
Resolutions: 1, 5, 15, 30, 60, D, W, M
"""
end = int(time.time())
start = end - (days * 24 * 60 * 60)
response = requests.get(
f"{BASE_URL}/stock/candle",
params={
"symbol": symbol,
"resolution": resolution,
"from": start,
"to": end,
"token": API_KEY
}
)
return response.json()def get_earnings_calendar(from_date: str, to_date: str) -> list:
"""Get upcoming earnings releases."""
response = requests.get(
f"{BASE_URL}/calendar/earnings",
params={
"from": from_date,
"to": to_date,
"token": API_KEY
}
)
return response.json().get("earningsCalendar", [])
# Example: Get next week's earnings
earnings = get_earnings_calendar("2025-12-05", "2025-12-12")def get_company_news(symbol: str, days: int = 7) -> list:
"""Get recent company news."""
from datetime import datetime, timedelta
end = datetime.now()
start = end - timedelta(days=days)
response = requests.get(
f"{BASE_URL}/company-news",
params={
"symbol": symbol,
"from": start.strftime("%Y-%m-%d"),
"to": end.strftime("%Y-%m-%d"),
"token": API_KEY
}
)
return response.json()def get_financials(symbol: str) -> dict:
"""Get key financial metrics."""
response = requests.get(
f"{BASE_URL}/stock/metric",
params={
"symbol": symbol,
"metric": "all",
"token": API_KEY
}
)
data = response.json()
metrics = data.get("metric", {})
return {
"pe_ratio": metrics.get("peBasicExclExtraTTM"),
"pb_ratio": metrics.get("pbQuarterly"),
"ps_ratio": metrics.get("psAnnual"),
"roe": metrics.get("roeTTM"),
"roa": metrics.get("roaTTM"),
"debt_equity": metrics.get("totalDebt/totalEquityQuarterly"),
"current_ratio": metrics.get("currentRatioQuarterly"),
"gross_margin": metrics.get("grossMarginTTM"),
"operating_margin": metrics.get("operatingMarginTTM"),
"52w_high": metrics.get("52WeekHigh"),
"52w_low": metrics.get("52WeekLow"),
"beta": metrics.get("beta")
}import websocket
import json
def on_message(ws, message):
data = json.loads(message)
if data["type"] == "trade":
for trade in data["data"]:
print(f"{trade['s']}: ${trade['p']:.2f} x {trade['v']}")
def on_open(ws):
# Subscribe to symbols
ws.send(json.dumps({"type": "subscribe", "symbol": "AAPL"}))
ws.send(json.dumps({"type": "subscribe", "symbol": "MSFT"}))
ws = websocket.WebSocketApp(
f"wss://ws.finnhub.io?token={API_KEY}",
on_message=on_message,
on_open=on_open
)
ws.run_forever()def safe_api_call(endpoint: str, params: dict) -> dict:
"""Make API call with error handling."""
params["token"] = API_KEY
try:
response = requests.get(f"{BASE_URL}/{endpoint}", params=params)
response.raise_for_status()
# Check for rate limit
remaining = response.headers.get("X-Ratelimit-Remaining")
if remaining and int(remaining) < 5:
print(f"Warning: Only {remaining} API calls remaining")
return response.json()
except requests.exceptions.HTTPError as e:
if response.status_code == 429:
print("Rate limit exceeded. Waiting 60 seconds...")
time.sleep(60)
return safe_api_call(endpoint, params)
raise
except Exception as e:
print(f"API error: {e}")
return {}# Python SDK
pip install finnhub-python
# JavaScript SDK
npm install finnhubtwelvedata-api - Alternative market data sourcealphavantage-api - Technical indicators focusfmp-api - Fundamental analysis focus93ed392
Canonical home
since Sep 12, 2026
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.