Skip to content

Market Data API

The Market Data API provides real-time stock prices, market indices, and financial news. This API integrates with multiple data sources including Yahoo Finance for market data, Finnhub for social sentiment analysis, and Financial Modeling Prep (FMP) for enhanced financial data.

Base URL

All market data endpoints are prefixed with:

/api/v1/market/

Authentication

All market data endpoints require authentication. Include the Bearer token in the Authorization header:

Authorization: Bearer <your_jwt_token>

Data Models

Stock

{
  "symbol": "AAPL",
  "name": "Apple Inc.",
  "price": 175.50,
  "change": 2.25,
  "changePercent": 1.30
}

Market Index

{
  "name": "S&P 500",
  "value": 4150.25,
  "change": 15.75,
  "changePercent": 0.38
}

Market Summary

{
  "indices": [
    {
      "name": "S&P 500",
      "value": 4150.25,
      "change": 15.75,
      "changePercent": 0.38
    }
  ],
  "topGainers": [
    {
      "symbol": "TSLA",
      "name": "Tesla Inc.",
      "price": 245.30,
      "change": 12.45,
      "changePercent": 5.35
    }
  ],
  "topLosers": [
    {
      "symbol": "NFLX",
      "name": "Netflix Inc.",
      "price": 385.20,
      "change": -8.75,
      "changePercent": -2.22
    }
  ]
}

News Item

{
  "title": "Apple Reports Strong Q4 Earnings",
  "description": "Apple Inc. reported better-than-expected quarterly earnings...",
  "url": "https://example.com/article",
  "source": "Financial Times",
  "publishedAt": "2025-01-15T10:30:00Z",
  "sentiment": "positive",
  "sentimentScore": 0.75
}

Stock Data Endpoints

Get Stock Data

Retrieve detailed information for a specific stock symbol.

GET /api/v1/market/stock/{symbol}

Path Parameters

Parameter Type Description
symbol string Stock ticker symbol (e.g., AAPL, GOOGL) - case insensitive

Response

Status Code: 200 OK

{
  "symbol": "AAPL",
  "name": "Apple Inc.",
  "price": 175.50,
  "change": 2.25,
  "changePercent": 1.30
}

Error Responses

404 Not Found

{
  "detail": "Stock INVALID not found"
}

500 Internal Server Error

{
  "detail": "Failed to retrieve stock data for AAPL"
}


Get Batch Stock Data

Retrieve stock data for multiple symbols in a single request.

GET /api/v1/market/stocks/batch?symbols=AAPL,GOOGL,MSFT

Query Parameters

Parameter Type Required Description
symbols string Yes Comma-separated list of stock symbols (max 10)

Response

Status Code: 200 OK

{
  "data": {
    "AAPL": {
      "symbol": "AAPL",
      "name": "Apple Inc.",
      "price": 175.50,
      "change": 2.25,
      "changePercent": 1.30
    },
    "GOOGL": {
      "symbol": "GOOGL",
      "name": "Alphabet Inc.",
      "price": 2950.25,
      "change": -15.75,
      "changePercent": -0.53
    },
    "INVALID": {
      "error": "Data not available"
    }
  },
  "requested_symbols": ["AAPL", "GOOGL", "INVALID"]
}

Error Responses

400 Bad Request - Too many symbols

{
  "detail": "Maximum 10 symbols allowed per batch request"
}

500 Internal Server Error

{
  "detail": "Failed to retrieve batch stock data"
}


Get Market Summary

Get current market overview including major indices and top movers.

GET /api/v1/market/summary

Response

Status Code: 200 OK

{
  "indices": [
    {
      "name": "S&P 500",
      "value": 4150.25,
      "change": 15.75,
      "changePercent": 0.38
    },
    {
      "name": "NASDAQ",
      "value": 12890.45,
      "change": 45.20,
      "changePercent": 0.35
    },
    {
      "name": "DOW",
      "value": 34250.80,
      "change": 125.30,
      "changePercent": 0.37
    }
  ],
  "topGainers": [
    {
      "symbol": "TSLA",
      "name": "Tesla Inc.",
      "price": 245.30,
      "change": 12.45,
      "changePercent": 5.35
    },
    {
      "symbol": "NVDA",
      "name": "NVIDIA Corporation",
      "price": 875.20,
      "change": 35.80,
      "changePercent": 4.27
    }
  ],
  "topLosers": [
    {
      "symbol": "NFLX",
      "name": "Netflix Inc.",
      "price": 385.20,
      "change": -8.75,
      "changePercent": -2.22
    },
    {
      "symbol": "ZM",
      "name": "Zoom Video Communications",
      "price": 72.45,
      "change": -3.25,
      "changePercent": -4.29
    }
  ]
}

Error Responses

500 Internal Server Error

{
  "detail": "Failed to retrieve market summary"
}

News Endpoints

Get Financial News

Retrieve general financial news or filter by specific criteria.

GET /api/v1/market/news?limit=10&symbol=AAPL&keywords=earnings

Query Parameters

Parameter Type Required Description
limit integer No Number of articles (1-50, default: 10)
symbol string No Filter news by stock symbol
keywords string No Search news by keywords

Response

Status Code: 200 OK

[
  {
    "title": "Apple Reports Strong Q4 Earnings",
    "description": "Apple Inc. reported better-than-expected quarterly earnings with revenue of $94.9 billion...",
    "url": "https://example.com/article/apple-earnings",
    "source": "Financial Times",
    "publishedAt": "2025-01-15T10:30:00Z",
    "sentiment": "positive",
    "sentimentScore": 0.75
  },
  {
    "title": "iPhone Sales Boost Apple's Performance",
    "description": "Strong iPhone 15 sales contributed to Apple's record quarterly performance...",
    "url": "https://example.com/article/iphone-sales",
    "source": "Reuters",
    "publishedAt": "2025-01-15T09:15:00Z",
    "sentiment": "positive",
    "sentimentScore": 0.68
  }
]

Error Responses

422 Unprocessable Entity - Invalid parameters

{
  "detail": [
    {
      "loc": ["query", "limit"],
      "msg": "ensure this value is less than or equal to 50",
      "type": "value_error.number.not_le",
      "ctx": {"limit_value": 50}
    }
  ]
}

500 Internal Server Error

{
  "detail": "Failed to retrieve news. Please check your News API key configuration."
}


Search News

Search news articles by keywords.

GET /api/v1/market/news/search?query=tesla earnings&limit=5

Query Parameters

Parameter Type Required Description
query string Yes Search keywords
limit integer No Number of articles (1-50, default: 10)

Response

Status Code: 200 OK

[
  {
    "title": "Tesla Q4 Earnings Beat Expectations",
    "description": "Tesla reported fourth-quarter earnings that exceeded analyst expectations...",
    "url": "https://example.com/tesla-earnings",
    "source": "Bloomberg",
    "publishedAt": "2025-01-15T14:20:00Z",
    "sentiment": "positive",
    "sentimentScore": 0.82
  }
]

Error Responses

422 Unprocessable Entity - Missing query

{
  "detail": [
    {
      "loc": ["query", "query"],
      "msg": "field required",
      "type": "value_error.missing"
    }
  ]
}

500 Internal Server Error

{
  "detail": "Failed to search news. Please check your News API key configuration."
}


Get Stock News

Get news articles for a specific stock symbol.

GET /api/v1/market/news/stock/{symbol}?limit=5

Path Parameters

Parameter Type Description
symbol string Stock ticker symbol (e.g., AAPL, GOOGL)

Query Parameters

Parameter Type Required Description
limit integer No Number of articles (1-20, default: 5)

Response

Status Code: 200 OK

[
  {
    "title": "Apple Unveils New AI Features",
    "description": "Apple announced new artificial intelligence capabilities for iOS...",
    "url": "https://example.com/apple-ai",
    "source": "TechCrunch",
    "publishedAt": "2025-01-15T16:45:00Z",
    "sentiment": "positive",
    "sentimentScore": 0.70
  }
]

Error Responses

500 Internal Server Error

{
  "detail": "Failed to retrieve news for AAPL. Please check your News API key configuration."
}

Examples

Complete Market Data Workflow

1. Get Market Overview

curl -X GET "http://localhost:8000/api/v1/market/summary" \
  -H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9..."

2. Get Specific Stock Data

curl -X GET "http://localhost:8000/api/v1/market/stock/AAPL" \
  -H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9..."

3. Get Multiple Stocks

curl -X GET "http://localhost:8000/api/v1/market/stocks/batch?symbols=AAPL,GOOGL,MSFT" \
  -H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9..."

4. Get Stock News

curl -X GET "http://localhost:8000/api/v1/market/news/stock/AAPL?limit=5" \
  -H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9..."

JavaScript/TypeScript Examples

Using Fetch API

// Get stock data
async function getStockData(symbol) {
  const response = await fetch(`/api/v1/market/stock/${symbol}`, {
    headers: {
      'Authorization': `Bearer ${token}`,
      'Content-Type': 'application/json'
    }
  });

  if (!response.ok) {
    throw new Error(`Error ${response.status}: ${response.statusText}`);
  }

  return await response.json();
}

// Get market summary
async function getMarketSummary() {
  const response = await fetch('/api/v1/market/summary', {
    headers: {
      'Authorization': `Bearer ${token}`,
      'Content-Type': 'application/json'
    }
  });

  return await response.json();
}

// Get batch stock data
async function getBatchStockData(symbols) {
  const symbolsString = symbols.join(',');
  const response = await fetch(`/api/v1/market/stocks/batch?symbols=${symbolsString}`, {
    headers: {
      'Authorization': `Bearer ${token}`,
      'Content-Type': 'application/json'
    }
  });

  return await response.json();
}

// Search news
async function searchNews(query, limit = 10) {
  const response = await fetch(`/api/v1/market/news/search?query=${encodeURIComponent(query)}&limit=${limit}`, {
    headers: {
      'Authorization': `Bearer ${token}`,
      'Content-Type': 'application/json'
    }
  });

  return await response.json();
}

Using Axios

import axios from 'axios';

const api = axios.create({
  baseURL: '/api/v1',
  headers: {
    'Authorization': `Bearer ${token}`
  }
});

// Get stock data
const stockData = await api.get('/market/stock/AAPL');

// Get market summary
const marketSummary = await api.get('/market/summary');

// Get batch data
const batchData = await api.get('/market/stocks/batch', {
  params: { symbols: 'AAPL,GOOGL,MSFT' }
});

// Get stock news
const stockNews = await api.get('/market/news/stock/AAPL', {
  params: { limit: 5 }
});

// Search news
const newsResults = await api.get('/market/news/search', {
  params: { query: 'tesla earnings', limit: 10 }
});

Python Examples

import httpx
import asyncio

async def get_stock_data(token: str, symbol: str):
    async with httpx.AsyncClient() as client:
        response = await client.get(
            f"http://localhost:8000/api/v1/market/stock/{symbol}",
            headers={"Authorization": f"Bearer {token}"}
        )
        response.raise_for_status()
        return response.json()

async def get_market_summary(token: str):
    async with httpx.AsyncClient() as client:
        response = await client.get(
            "http://localhost:8000/api/v1/market/summary",
            headers={"Authorization": f"Bearer {token}"}
        )
        response.raise_for_status()
        return response.json()

async def search_news(token: str, query: str, limit: int = 10):
    async with httpx.AsyncClient() as client:
        response = await client.get(
            "http://localhost:8000/api/v1/market/news/search",
            headers={"Authorization": f"Bearer {token}"},
            params={"query": query, "limit": limit}
        )
        response.raise_for_status()
        return response.json()

# Usage
stock_data = await get_stock_data(token, "AAPL")
market_summary = await get_market_summary(token)
news_results = await search_news(token, "tesla earnings", 5)

Data Sources and Caching

Primary Data Sources

  1. Yahoo Finance: Real-time stock data via yfinance library
  2. Finnhub: Social sentiment analysis and alternative market data
  3. Financial Modeling Prep (FMP): Enhanced financial data and historical analysis
  4. NewsAPI: Financial news and sentiment analysis

Caching Strategy

  • Market Data: Cached for 60 seconds to reduce API calls
  • News Data: Cached for 5 minutes for search queries
  • Sentiment Analysis: Processed server-side using TextBlob

Rate Limiting

  • Market Data: 0.3-second delay between requests
  • News API: Respects NewsAPI rate limits
  • Batch Requests: Limited to 10 symbols per request

Error Handling

If Yahoo Finance is unavailable: 1. Returns appropriate error messages 2. Maintains consistent error format 3. Logs errors for monitoring

Sentiment Analysis

News articles include sentiment analysis:

  • Sentiment: "positive", "negative", or "neutral"
  • Sentiment Score: Numeric score from -1.0 (very negative) to 1.0 (very positive)
  • Processing: Server-side analysis using TextBlob

Sentiment Score Interpretation

Score Range Sentiment Description
0.6 to 1.0 Very Positive Strong positive sentiment
0.1 to 0.6 Positive Mild to moderate positive sentiment
-0.1 to 0.1 Neutral Neutral or balanced sentiment
-0.6 to -0.1 Negative Mild to moderate negative sentiment
-1.0 to -0.6 Very Negative Strong negative sentiment

Error Handling

Common Error Scenarios

  1. Invalid Stock Symbol: Returns 404 with specific error message
  2. API Key Issues: Returns 500 with configuration guidance
  3. Rate Limiting: Automatic retry with exponential backoff
  4. Network Issues: Fallback to alternative data sources

Monitoring and Logging

All API calls are logged with: - User ID and request details - Response times and success rates - Fallback usage statistics - Error rates by endpoint

Testing

Unit Tests

Market data endpoints are thoroughly tested:

# Run market data service tests
uv run pytest tests/unit/test_services/test_market_service.py -v

# Run market data API tests
uv run pytest tests/integration/test_api/test_market.py -v

# Run news service tests
uv run pytest tests/unit/test_services/test_news_service.py -v

Mock Data

For testing, external APIs are mocked:

@patch('app.services.market_service.yfinance.download')
async def test_get_stock_data(mock_yf_download):
    mock_yf_download.return_value = create_mock_dataframe()
    result = await get_stock_price("AAPL")
    assert result.symbol == "AAPL"

For more information about testing, see the Testing Guide.