API Documentation
Welcome to the SAHMK API. Real-time and historical Saudi stock market data for all 350+ companies on TASI and Nomu — complete reference for endpoints, authentication, streaming, and tools.
Getting Started
Create an account, get your API key, and make your first request. Then move from core REST endpoints to SDKs, automation, and real-time streaming as your product grows.
Start Here
First request
Get a live Saudi stock quote working in minutes.
Build
Core API
Quotes, market data, company data, financials, and events.
Scale
Real-time & automation
WebSocket, webhooks, alerts, and production limits.
Quick Start
- Create a free account
- Get your API key from the dashboard
- Make your first API request
- Browse code examples on GitHub
Base URL
https://app.sahmk.sa/api/v1Your First Request
curl -X GET "https://app.sahmk.sa/api/v1/quote/2222/" \
-H "X-API-Key: YOUR_API_KEY"Full examples available on GitHub →
Expected Response
{
"symbol": "2222",
"name_en": "Saudi Arabian Oil Co",
"price": 25.86,
"change_percent": 0.7,
"volume": 9803705,
"updated_at": "2026-02-10T12:19:22+00:00",
"is_delayed": false
}Success: You just fetched live Saudi market data from SAHMK. Next, use the SDK for faster integration, explore core endpoints, or move to WebSocket if you need streaming updates.
Authentication
All API requests require authentication using an API key. Include your key in the X-API-Key header.
X-API-Key: YOUR_API_KEYAPI Key Types:
• shmk_live_* — Production keys
• shmk_test_* — Test keys (same data, separate quota)
curl -X GET "https://app.sahmk.sa/api/v1/quote/2222/" \
-H "X-API-Key: YOUR_API_KEY"Python SDK & CLI
Start here if you want the fastest path from API key to working integration. The official SDK gives you a cleaner client, while the CLI is useful for testing, demos, and internal tooling.
pip install -U sahmk
export SAHMK_API_KEY="your_api_key"
sahmk quote 2222Python SDK:
from sahmk import SahmkClient
client = SahmkClient(api_key="YOUR_API_KEY")
print(client.quote("2222"))Use this when: you want less boilerplate than raw REST, typed workflows in Python, or quick command-line access to quotes and market data.
Full examples: github.com/sahmk-sa/sahmk-python • PyPI: pypi.org/project/sahmk
AI & Agents
Use SAHMK inside Claude Desktop, Cursor, and other MCP-compatible clients. For direct agent consumption, use the MCP server for tool calling and/api-docs.mdfor machine-readable API docs.
pip install sahmk-mcpPackage: pypi.org/project/sahmk-mcp · MCP quick start tutorial
Claude Desktop
macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
Windows: %APPDATA%\Claude\claude_desktop_config.json
{
"mcpServers": {
"sahmk": {
"command": "sahmk-mcp",
"env": {
"SAHMK_API_KEY": "your_api_key_here"
}
}
}
}Cursor
Add to your project's .cursor/mcp.json
{
"mcpServers": {
"sahmk": {
"command": "sahmk-mcp",
"env": {
"SAHMK_API_KEY": "your_api_key_here"
}
}
}
}Use this when: your team wants Sahmk available inside AI workflows, research assistants, or agentic tools without building a custom wrapper first.
Stocks
Get real-time stock quotes and prices for individual or multiple stocks.
GET /quote/{symbol}/
FreeGet current price and trading data for a single stock.
Path Parameters:
symbol— Stock ticker (e.g., 2222 for Aramco)
View Response
{
"symbol": "2222",
"name": "أرامكو السعودية",
"name_en": "Saudi Arabian Oil Co",
"price": 25.86,
"change": 0.18,
"change_percent": 0.7,
"open": 25.6,
"high": 25.86,
"low": 25.6,
"previous_close": 25.68,
"volume": 9803705,
"value": 252308343.0,
"bid": 25.82,
"ask": 25.86,
"liquidity": {
"inflow_value": 184950463.03,
"inflow_volume": 7182468,
"inflow_trades": 7261,
"outflow_value": 67357881.91,
"outflow_volume": 2621237,
"outflow_trades": 5028,
"net_value": 117592581.12
},
"updated_at": "2026-02-10T12:19:22+00:00",
"is_delayed": false
}Liquidity Fields:
inflow_value— Total SAR value of buy ordersoutflow_value— Total SAR value of sell ordersnet_value— Net liquidity (inflow - outflow)
GET /quotes/
Starter+Get quotes for multiple stocks in a single request. Requires Starter plan or higher.
Note: This bulk endpoint requires a Starter plan or higher. Free-tier users can use GET /quote/{symbol}/ for individual stock quotes.
Query Parameters:
symbols— Comma-separated tickers (max 50)
Pro Tip: Use this batch endpoint instead of polling individual /quote/{symbol}/ calls — it's more efficient and counts as a single API request.
View Response
{
"quotes": [
{
"symbol": "2222",
"name": "أرامكو السعودية",
"name_en": "Saudi Arabian Oil Co",
"price": 25.86,
"change": 0.18,
"change_percent": 0.7,
"volume": 9803705,
"net_liquidity": 117592581.12,
"updated_at": "2026-02-10T12:19:22+00:00",
"is_delayed": false
},
{
"symbol": "1120",
"name": "الراجحي",
"name_en": "Al Rajhi Banking & Investment Corp SJSC",
"price": 108.6,
"change": 0.2,
"change_percent": 0.18,
"volume": 4023570,
"net_liquidity": 45230000.50,
"updated_at": "2026-02-10T12:18:56+00:00",
"is_delayed": false
}
],
"count": 2
}net_liquidity — Net money flow (buy value - sell value) in SAR
Market
Get market-wide data including index values, top movers, and sector performance.
GET /market/summary/
FreeGet TASI index value, volume, and market sentiment.
View Response
{
"timestamp": "2026-01-28T12:20:00+00:00",
"index_value": 11458.11,
"index_change": 76.28,
"index_change_percent": 0.67,
"total_volume": 279874553,
"advancing": 117,
"declining": 139,
"unchanged": 14,
"market_mood": "bullish"
}GET /market/gainers/
FreeGet top gaining stocks by percentage change.
Query Parameters:
limit— Number of results (default: 10, max: 50)
View Response
{
"gainers": [
{
"symbol": "4194",
"name": "مجموعة منزل التسويق للتجارة",
"name_en": "Maison Marketing Trade Group",
"price": 59.5,
"change": 4.9,
"change_percent": 8.97,
"volume": 611349,
"updated_at": "2026-01-28T12:19:50+00:00"
}
],
"count": 10
}GET /market/losers/
FreeGet top losing stocks by percentage change.
Query Parameters:
limit— Number of results (default: 10, max: 50)
View Response
{
"losers": [
{
"symbol": "9639",
"name": "شركة أنماط التقنية للتجارة",
"name_en": "Anmat Technology Trading Co",
"price": 8.2,
"change": -0.8,
"change_percent": -8.89,
"volume": 9206,
"updated_at": "2026-01-28T12:10:18+00:00"
}
],
"count": 10
}GET /market/volume/
FreeGet top stocks by trading volume.
Query Parameters:
limit— Number of results (default: 10, max: 50)
View Response
{
"stocks": [
{
"symbol": "2222",
"name": "أرامكو السعودية",
"name_en": "Saudi Arabian Oil Co",
"price": 25.64,
"change": 0.38,
"change_percent": 1.5,
"volume": 15738067,
"updated_at": "2026-01-28T12:19:48+00:00"
}
],
"count": 10
}GET /market/value/
FreeGet top stocks by trading value (SAR).
Query Parameters:
limit— Number of results (default: 10, max: 50)
View Response
{
"stocks": [
{
"symbol": "2222",
"name": "أرامكو السعودية",
"name_en": "Saudi Arabian Oil Co",
"price": 25.64,
"change": 0.38,
"change_percent": 1.5,
"volume": 15738067,
"value": 402108076.72,
"updated_at": "2026-01-28T12:19:48+00:00"
}
],
"count": 10
}GET /market/sectors/
FreeGet sector performance and statistics.
View Response
{
"sectors": [
{
"id": "TBNI",
"name": "Banks",
"change_percent": 0.45,
"avg_change_percent": 0.38,
"volume": 45027873,
"num_stocks": 10
}
],
"count": 20
}Company Info
Get detailed company information including fundamentals, technicals, and valuation data.
GET /company/{symbol}/
FreeGet company information. Response varies by plan.
Data Available by Plan:
- Free: Name, sector, industry, description, website
- Starter: + Full fundamentals (PE, EPS, book value, beta, week/month/52w ranges)
- Pro: + Technicals, valuation, analyst consensus
New: week_high/low, month_high/low — Price levels in last 7/30 days
View Response (Pro)
{
"symbol": "2222",
"name": "أرامكو السعودية",
"name_en": "Saudi Arabian Oil Co",
"current_price": 25.64,
"sector": "Energy",
"industry": "Oil & Gas",
"description": "Saudi Aramco is the world's largest oil producer...",
"website": "https://www.aramco.com",
"country": "Saudi Arabia",
"currency": "SAR",
"fundamentals": {
"market_cap": 6258120000000,
"pe_ratio": 16.77,
"forward_pe": 15.48,
"eps": 1.54,
"book_value": 6.16,
"price_to_book": 4.19,
"beta": 0.104,
"shares_outstanding": 242000000000,
"float_shares": 5969578000,
"week_high": 26.10,
"week_low": 25.40,
"month_high": 27.20,
"month_low": 24.80,
"fifty_two_week_high": 27.85,
"fifty_two_week_low": 23.04
},
"technicals": {
"rsi_14": 55.3,
"macd_line": 0.12,
"macd_signal": 0.08,
"macd_histogram": 0.04,
"fifty_day_average": 26.1,
"technical_strength": 0.65,
"price_direction": "bullish",
"updated_at": "2026-01-28T10:00:00+03:00"
},
"valuation": {
"fair_price": 28.50,
"fair_price_confidence": 0.85,
"calculated_at": "2026-01-28T10:00:00+03:00"
},
"analysts": {
"target_mean": 29.5,
"target_median": 29.0,
"target_high": 35.0,
"target_low": 24.0,
"consensus": "buy",
"consensus_score": 2.1,
"num_analysts": 15
}
}Historical Data
Access historical OHLCV (Open, High, Low, Close, Volume) data for technical analysis and backtesting.
GET /historical/{symbol}/
Starter+Get historical price data for a stock.
Query Parameters:
from— Start date YYYY-MM-DD (default: 30 days ago)to— End date YYYY-MM-DD (default: today)interval— Data interval: 1d, 1w, 1m (default: 1d)
View Response
{
"symbol": "2222",
"interval": "1d",
"from": "2026-01-01",
"to": "2026-01-28",
"count": 20,
"data": [
{
"date": "2026-01-28",
"open": 25.3,
"high": 25.68,
"low": 25.3,
"close": 25.64,
"volume": 15738067,
"adjusted_close": 25.64,
"turnover": 402108076.72
}
]
}Financials
Access financial statements including income statements, balance sheets, and cash flow data.
GET /financials/{symbol}/
Starter+Get financial statements for a company.
View Response
{
"symbol": "2222",
"income_statements": [
{
"report_date": "2025-09-30",
"total_revenue": 418116750000.0,
"gross_profit": 215000000000.0,
"operating_income": 180000000000.0,
"net_income": 105000000000.0
}
],
"balance_sheets": [
{
"report_date": "2025-09-30",
"total_assets": 2516431000000.0,
"total_liabilities": 1026431000000.0,
"stockholders_equity": 1490000000000.0,
"total_debt": 356540000000.0
}
],
"cash_flows": [
{
"report_date": "2025-09-30",
"operating_cash_flow": 135375000000.0,
"investing_cash_flow": -45000000000.0,
"financing_cash_flow": -82337000000.0,
"free_cash_flow": 88500000000.0
}
]
}Dividends
Get dividend history, upcoming distributions, and trailing yield for a stock.
GET /dividends/{symbol}/
Starter+Get dividend history and yield information.
View Response
{
"symbol": "2222",
"current_price": 25.64,
"trailing_12m_yield": 4.2,
"trailing_12m_dividends": 1.60,
"payments_last_year": 4,
"upcoming": [
{
"value": 0.40,
"period": "Q4",
"eligibility_date": "2026-03-15",
"distribution_date": "2026-04-01"
}
],
"history": [
{
"value": 0.40,
"value_percent": 1.5,
"period": "Q3",
"fiscal_year": 2025,
"announcement_date": "2025-09-01",
"eligibility_date": "2025-09-15",
"distribution_date": "2025-10-01"
}
]
}Stock Events
Get AI-generated summaries of significant stock events and news (Arabic only).
GET /events/
Pro+Get stock events with AI-generated analysis.
Query Parameters:
symbol— Filter by stock ticker (optional)limit— Number of results (default: 20)
Note: Event descriptions are in Arabic only. Event types are UPPERCASE (e.g., FINANCIAL_REPORT, DIVIDEND_ANNOUNCEMENT).
View Response
{
"events": [
{
"symbol": "4190",
"stock_name": "جرير للتسويق",
"event_type": "FINANCIAL_REPORT",
"importance": "important",
"sentiment": "positive",
"description": "شركة جرير للتسويق تعلن عن نتائج مالية قياسية للربع الرابع 2025...",
"article_date": "2026-01-29T17:10:06+00:00",
"created_at": "2026-01-29T17:10:12+00:00"
}
],
"count": 1,
"available_types": [
"FINANCIAL_REPORT", "DIVIDEND_ANNOUNCEMENT", "STOCK_SPLIT",
"MERGER_ACQUISITION", "MANAGEMENT_CHANGE", "NEW_LISTING",
"REGULATORY_ACTION", "PARTNERSHIP", "MARKET_EXPANSION",
"RESTRUCTURING", "EARNINGS_SURPRISE", "PRODUCT_LAUNCH", "OTHER"
]
}importance: critical, important, regular
sentiment: very_positive, positive, slightly_positive, neutral, slightly_negative, negative, very_negative
WebSocket Streaming
Real-time stock price streaming via WebSocket, with market updates pushed as soon as they change.
Connection
Pro+WebSocket URL:
wss://app.sahmk.sa/ws/v1/stocks/?api_key=YOUR_API_KEYPro/Enterprise Only: WebSocket streaming requires Pro or Enterprise plan. Updates are delivered during market hours (Sun-Thu, 10:00-15:30 Saudi time). Enterprise connection limits are contract-based.
Subscription Limits
| Plan | Max symbols/connection | Max symbols/call | Subscribe all (*) |
|---|---|---|---|
| Pro | 60 | 20 | ✗ |
| Enterprise | Custom | Custom | ✓ |
Tip: Use multiple connections to track more than 60 symbols on Pro plan.
Client → Server Messages
| Action | Message | Description |
|---|---|---|
| Subscribe | {"action": "subscribe", "symbols": ["2222", "1120"]} | Subscribe to specific stocks |
| Subscribe All | {"action": "subscribe", "symbols": ["*"]} | Subscribe to all stocks (Enterprise only) |
| Unsubscribe | {"action": "unsubscribe", "symbols": ["2222"]} | Stop receiving updates |
| Ping | {"action": "ping"} | Keep-alive |
Server → Client Messages
| Type | Description |
|---|---|
| connected | Connection confirmed with plan info |
| subscribed | Subscription confirmed with symbol list |
| quote | Real-time price update |
| pong | Ping response |
| error | Error message |
View Connected Message Format
{
"type": "connected",
"plan": "pro",
"limits": {
"max_symbols_per_connection": 60,
"max_symbols_per_call": 20
},
"message": "Connected to SAHMK real-time stock stream",
"timestamp": "2026-02-10T10:00:00.000Z"
}View Quote Message Format
{
"type": "quote",
"symbol": "2222",
"timestamp": "2026-02-10T10:30:15.123Z",
"data": {
"price": 25.86,
"open": 25.60,
"high": 25.86,
"low": 25.60,
"close": 25.86,
"change": 0.18,
"change_percent": 0.7,
"previous_close": 25.68,
"volume": 9803705,
"value": 252308343.0,
"bid": 25.82,
"ask": 25.86,
"liquidity": {
"inflow_value": 184950463.03,
"inflow_volume": 7182468,
"outflow_value": 67357881.91,
"outflow_volume": 2621237,
"net_value": 117592581.12
},
"trade_time": "2026-02-10T10:30:12+00:00"
}
}Code Examples
const API_KEY = 'shmk_live_xxxxxxxxxxxxxxxx';
const ws = new WebSocket(`wss://app.sahmk.sa/ws/v1/stocks/?api_key=${API_KEY}`);
ws.onopen = () => {
console.log('Connected');
ws.send(JSON.stringify({
action: 'subscribe',
symbols: ['2222', '1120', '4191']
}));
};
ws.onmessage = (event) => {
const msg = JSON.parse(event.data);
if (msg.type === 'quote') {
console.log(`${msg.symbol}: ${msg.data.price} (${msg.data.change_percent}%)`);
}
};
// Keep-alive ping every 30 seconds
setInterval(() => {
if (ws.readyState === WebSocket.OPEN) {
ws.send(JSON.stringify({ action: 'ping' }));
}
}, 30000);View more examples on GitHub →
REST vs WebSocket Comparison
| Metric | REST Polling | WebSocket |
|---|---|---|
| Latency | 1-60+ seconds | <1 second |
| API calls/day | Thousands | 1 connection |
| Missed updates | Possible | None |
| Complexity | Simple | Slightly more |
WebSocket Error Codes
| Code | Meaning |
|---|---|
| 4001 | Invalid or missing API key |
| 4003 | Free plan — upgrade required |
| 4004 | Account inactive or expired |
Webhooks Pro+
Register webhook URLs to receive real-time HTTP POST callbacks when price alert conditions are met during trading hours. Pro plans support up to 3 webhooks; Enterprise limits are custom (contract-based).
Endpoints
| Method | Endpoint | Description |
|---|---|---|
GET | /api/v1/webhooks/ | List registered webhooks |
POST | /api/v1/webhooks/ | Register a new webhook URL |
DELETE | /api/v1/webhooks/{id}/ | Remove webhook and all its alerts |
POST | /api/v1/webhooks/{id}/verify/ | Retry webhook verification |
Register a Webhook
curl -X POST "https://app.sahmk.sa/api/v1/webhooks/" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://your-server.com/callback",
"name": "My Production Hook"
}'Verification: On creation, SAHMK sends a POST to your URL with { "event": "webhook.verify", "challenge": "..." }. Respond with HTTP 200 to verify. Alerts won't fire until the webhook is verified.
Safety Features
- • HTTPS-only webhook URLs required
- • Webhooks auto-disabled after 3 consecutive delivery failures
- • 3 retry attempts with backoff (2s, 10s, 60s) if delivery fails
- • Duplicate URLs are rejected (409 DUPLICATE)
Price Alerts Pro+
Create price alerts that fire webhook callbacks when conditions are met. Pro plans support up to 10 active alerts; Enterprise limits are custom (contract-based).
Endpoints
| Method | Endpoint | Description |
|---|---|---|
GET | /api/v1/alerts/ | List alerts (filter: ?status=active|triggered|all) |
POST | /api/v1/alerts/ | Create a price alert |
DELETE | /api/v1/alerts/{id}/ | Delete an alert |
Create an Alert
curl -X POST "https://app.sahmk.sa/api/v1/alerts/" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"symbol": "2222",
"condition": "price_below",
"value": 28.50,
"webhook_id": 1,
"once": true
}'Alert Conditions
| Condition | Description | Example |
|---|---|---|
| price_above | Fires when stock price goes above the value | value: 30.00 |
| price_below | Fires when stock price goes below the value | value: 28.50 |
| pct_change | Fires when daily % change exceeds ±value | value: 3.0 (means ±3%) |
once parameter: When true, the alert fires once then auto-deactivates. When false, it keeps firing with a 5-minute cooldown between triggers.
Webhook Payload
When an alert triggers, your webhook URL receives a POST request with this payload:
{
"event": "price_alert",
"alert_id": 42,
"symbol": "2222",
"condition": "price_below",
"threshold": 28.5,
"current_price": 28.40,
"pct_change": -1.5,
"volume": 12500000,
"high": 29.8,
"low": 28.2,
"change": -0.45,
"triggered_at": "2026-02-21T12:30:15+03:00"
}Error Responses
403PLAN_LIMITFree/Starter tried to access webhooks, or alert/webhook limit reached.
400VALIDATIONMissing or invalid fields in the request body.
404NOT_FOUNDWebhook or alert doesn't belong to this developer.
409DUPLICATEWebhook URL already registered.
Webhook & Alert Limits
| Plan | Webhooks | Active Alerts |
|---|---|---|
| Free | ✗ | ✗ |
| Starter | ✗ | ✗ |
| Pro | 3 | 10 |
| Enterprise | Custom | Custom |
See Rate Limits for the full plan comparison including API quotas, burst limits, and API keys.
Rate Limits
API access is rate-limited based on your subscription plan. There are two types of limits: daily quotas and per-minute burst limits.
Full Plan Comparison
| Plan | Daily Limit | Burst Limit | API Keys | WebSocket | Webhooks | Alerts |
|---|---|---|---|---|---|---|
| Free | 100/day | 10/min | 1 | ✗ | ✗ | ✗ |
| Starter | 5,000/day | 100/min | 3 | ✗ | ✗ | ✗ |
| Pro | 50,000/day | 500/min | 10 | ✓ | 3 | 10 |
| Enterprise A (Shared) | High-volume (Custom) | Custom | Custom | ✓ | Custom | Custom |
| Enterprise B (Dedicated) | Scales with resources | Scales with resources | Custom | ✓ | Custom | Custom |
Burst Protection: To prevent abuse, all plans have per-minute burst limits. Requests exceeding the burst limit will receive a 429 response. Daily limits reset at midnight (UTC+3). Enterprise limits are contract-based and may be designed as monthly quotas or resource-based.
Rate Limit Headers
Each response includes headers to help track your usage:
X-RateLimit-Limit: 5000
X-RateLimit-Remaining: 4987
X-RateLimit-Reset: 2026-01-30T00:00:00+03:00Error Codes
The API uses standard HTTP status codes and returns structured JSON error responses.
401INVALID_API_KEYAPI key is missing, invalid, or revoked.
403PLAN_LIMITEndpoint requires a higher plan (e.g., historical data requires Starter+).
404INVALID_SYMBOLStock symbol not found in TASI or Nomu.
429RATE_LIMITDaily quota or per-minute burst limit exceeded.
500SERVER_ERRORInternal server error. Please retry or contact support.
Error Response Format
{
"error": {
"code": "RATE_LIMIT",
"message": "Daily request limit exceeded. Resets at midnight UTC+3."
}
}Market Data Usage
Sahmk market data may be used within your applications, tools, or products.
Developer plans are intended for development, internal tools, and small-scale applications.
Large-scale public market data platforms, commercial display services, or data redistribution may require an enterprise agreement.
Reselling market data or providing it as a standalone API or data feed is not permitted without a separate agreement with Sahmk.
Need More Help?
Check the machine-readable docs at /api-docs.md, browse examples on GitHub, or contact our team.