finnhub-api

FinnHub financial data API integration for stocks, forex, crypto, news, and fundamentals. Use when fetching real-time quotes, company profiles, financial…

INSTALLATION
npx skills add https://github.com/adaptationio/skrillz --skill finnhub-api
Run in your project or agent environment. Adjust flags if your CLI version differs.

SKILL.md

FinnHub API Integration

Complete integration with FinnHub's financial data API providing access to stocks, forex, crypto, company fundamentals, news, and real-time market data.

Quick Start

Authentication

# Environment variable (recommended)

export FINNHUB_API_KEY="your_api_key"

# Or in .env file

FINNHUB_API_KEY=your_api_key

Basic Usage (Python)

import 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}%)")

### Using Official SDK

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")


## API Endpoints Reference

### Stock Market Data

| 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 |

### Fundamental Data

| 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 |

### Forex & Crypto

| Endpoint | Description | Free |
| --- | --- | --- |
| `/forex/rates` | Exchange rates | ✅ |
| `/forex/candle` | Forex OHLCV | ✅ |
| `/crypto/candle` | Crypto OHLCV | ✅ |
| `/crypto/exchanges` | Crypto exchanges | ✅ |
| `/crypto/symbol` | Crypto symbols | ✅ |

### News & Sentiment

| Endpoint | Description | Free |
| --- | --- | --- |
| `/company-news` | Company news | ✅ |
| `/news` | Market news | ✅ |
| `/press-releases` | Press releases | ⚠️ Premium |
| `/news-sentiment` | News sentiment | ⚠️ Premium |

### Calendar Events

| Endpoint | Description | Free |
| --- | --- | --- |
| `/calendar/earnings` | Earnings calendar | ✅ |
| `/calendar/ipo` | IPO calendar | ✅ |
| `/stock/dividends` | Dividend history | ✅ |
| `/stock/splits` | Stock splits | ✅ |

## Rate Limits

| Tier | Calls/Minute | Notes |
| --- | --- | --- |
| Free | 60 | US stocks, forex, crypto |
| Paid | 300+ | Per-market pricing |

**Rate limit headers:**

- `X-Ratelimit-Limit`: Max calls per minute

- `X-Ratelimit-Remaining`: Calls remaining

- `X-Ratelimit-Reset`: Reset timestamp

## Common Tasks

### Task: Get Stock Quote with Change

def 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")

}


### Task: Get Historical Candles

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()


### Task: Get Earnings Calendar

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")


### Task: Get Company News

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()


### Task: Get Financial Metrics

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")

}


## WebSocket Real-Time Data

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()


## Error Handling

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 {}


## Free vs Premium Features

### Free Tier Includes

- Real-time US stock quotes

- Historical data (1 year)

- Company profiles & peers

- Basic financials & metrics

- Earnings calendar

- Company news

- Forex & crypto data

- WebSocket (US stocks, forex, crypto)

### Premium Required

- Insider transactions & sentiment

- SEC filings

- ESG scores

- Patent data

- Congressional trading

- International markets

- Revenue/EPS estimates

- Lobbying data

- Extended historical data

## Best Practices

- **Cache static data** - Company profiles, metrics rarely change

- **Use WebSocket** - For real-time quotes instead of polling

- **Batch where possible** - Reduce API calls

- **Handle rate limits** - Implement exponential backoff

- **Store API key securely** - Use environment variables

## Installation

Python SDK

pip install finnhub-python

JavaScript SDK

npm install finnhub

BrowserAct

Let your agent run on any real-world website

Bypass CAPTCHA & anti-bot for free. Start local, scale to cloud.

Explore BrowserAct Skills →

Stop writing automation&scrapers

Install the CLI. Run your first Skill in 30 seconds. Scale when you're ready.

Start free
free · no credit card