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:
Authentication
All market data endpoints require authentication. Include the Bearer token in the Authorization header:
Data Models
Stock
Market Index
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.
Path Parameters
Parameter | Type | Description |
---|---|---|
symbol |
string | Stock ticker symbol (e.g., AAPL, GOOGL) - case insensitive |
Response
Status Code: 200 OK
Error Responses
404 Not Found
500 Internal Server Error
Get Batch Stock Data
Retrieve stock data for multiple symbols in a single request.
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
500 Internal Server Error
Get Market Summary
Get current market overview including major indices and top movers.
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
News Endpoints
Get Financial News
Retrieve general financial news or filter by specific criteria.
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
Search News
Search news articles by keywords.
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
Get Stock News
Get news articles for a specific stock symbol.
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
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
- Yahoo Finance: Real-time stock data via yfinance library
- Finnhub: Social sentiment analysis and alternative market data
- Financial Modeling Prep (FMP): Enhanced financial data and historical analysis
- 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
- Invalid Stock Symbol: Returns 404 with specific error message
- API Key Issues: Returns 500 with configuration guidance
- Rate Limiting: Automatic retry with exponential backoff
- 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
Related APIs
- Portfolio API - Portfolio management and stock tracking
- Authentication API - User authentication and token management
- User API - API key configuration and user preferences
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.