OpenSpace finnhub-stock-api

Integrate with Finnhub Stock API for real-time and historical stock market data. Covers quote fetching, company profiles, and WebSocket streaming.

install
source · Clone the upstream repo
git clone https://github.com/HKUDS/OpenSpace
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/HKUDS/OpenSpace "$T" && mkdir -p ~/.claude/skills && cp -r "$T/showcase/skills/finnhub-stock-api" ~/.claude/skills/hkuds-openspace-finnhub-stock-api && rm -rf "$T"
manifest: showcase/skills/finnhub-stock-api/SKILL.md
source content

Finnhub Stock API Integration

Finnhub provides free stock market data (REST + WebSocket). API key required (free tier: 60 calls/min).

  • Docs: https://finnhub.io/docs/api
  • Base URL:
    https://finnhub.io/api/v1
  • Auth: Query param
    token=YOUR_API_KEY
  • Rate limit: 60 requests/minute (free), 300/min (premium)
  • CORS: Unknown (use server-side proxy)

Key Endpoints

1. Stock Quote (Real-Time)

GET /quote?symbol=AAPL&token=API_KEY

Response:

{
  "c": 178.72,     // Current price
  "d": 2.38,       // Change (absolute)
  "dp": 1.35,      // Change percent
  "h": 179.60,     // High price of the day
  "l": 175.10,     // Low price of the day
  "o": 176.15,     // Open price
  "pc": 176.34,    // Previous close
  "t": 1702569600  // Timestamp
}

2. Company Profile

GET /stock/profile2?symbol=AAPL&token=API_KEY

Response:

{
  "country": "US",
  "currency": "USD",
  "exchange": "NASDAQ NMS - GLOBAL MARKET",
  "name": "Apple Inc",
  "ticker": "AAPL",
  "ipo": "1980-12-12",
  "marketCapitalization": 2794000,
  "logo": "https://static.finnhub.io/logo/..."
}

3. Stock Candles (Historical)

GET /stock/candle?symbol=AAPL&resolution=D&from=1609459200&to=1640995200&token=API_KEY
  • resolution
    : 1, 5, 15, 30, 60, D, W, M
  • from
    /
    to
    : UNIX timestamps

Response:

{
  "c": [130.21, 131.96, ...],  // Close prices
  "h": [131.74, 132.63, ...],  // Highs
  "l": [128.50, 130.23, ...],  // Lows
  "o": [130.92, 130.87, ...],  // Opens
  "v": [143301900, ...],       // Volumes
  "t": [1609459200, ...],      // Timestamps
  "s": "ok"                     // Status
}

4. Market News

GET /news?category=general&token=API_KEY

Categories:

general
,
forex
,
crypto
,
merger

Frontend Service Implementation

// src/services/stock-market.ts
import { createCircuitBreaker } from '@/utils/circuit-breaker';

export interface StockQuote {
  symbol: string;
  name: string;
  price: number | null;
  change: number | null;
  changePercent: number | null;
  high: number | null;
  low: number | null;
  sparkline?: number[];
}

const quoteBreaker = createCircuitBreaker<StockQuote[]>({
  name: 'StockQuotes',
  cacheTtlMs: 30_000,
});

const DEFAULT_SYMBOLS = ['AAPL', 'MSFT', 'GOOGL', 'AMZN', 'TSLA', 'NVDA', 'META'];

export async function fetchStockQuotes(symbols = DEFAULT_SYMBOLS): Promise<StockQuote[]> {
  return quoteBreaker.execute(async () => {
    const resp = await fetch(`/api/stocks?symbols=${symbols.join(',')}`);
    if (!resp.ok) throw new Error(`HTTP ${resp.status}`);
    const data = await resp.json();
    return data.quotes.map((q: any) => ({
      symbol: q.symbol,
      name: q.name || q.symbol,
      price: q.price ?? q.c ?? null,
      change: q.change ?? q.d ?? null,
      changePercent: q.changePercent ?? q.dp ?? null,
      high: q.high ?? q.h ?? null,
      low: q.low ?? q.l ?? null,
    }));
  }, []);
}

Alternative APIs (from public-apis)

If Finnhub rate limits are a concern, these alternatives are available:

APIFree TierNotes
Alpha Vantage25 req/day (free)
https://www.alphavantage.co/
Twelve Data800 req/day
https://twelvedata.com/
Financial Modeling Prep250 req/day
https://financialmodelingprep.com/
Yahoo Finance (via RapidAPI)Varies
https://www.yahoofinanceapi.com/
Polygon5 req/min (free)
https://polygon.io/
IEX Cloud50k credits/month
https://iexcloud.io/
Marketstack100 req/month
https://marketstack.com/

Server-Side Proxy

The frontend should never call Finnhub directly. Use the API proxy pattern (see

api-proxy-endpoint
skill) to:

  1. Hide the API key
  2. Batch multiple symbol requests
  3. Add edge caching (30s
    Cache-Control
    )
  4. Handle rate limit errors gracefully (return cached data)