API للمطورين

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.

Quick Start

  1. Create a free account
  2. Get your API key from the dashboard
  3. Make your first API request
  4. Browse code examples on GitHub

Base URL

text
https://app.sahmk.sa/api/v1

Your 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

json
{
  "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.

http
X-API-Key: YOUR_API_KEY

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

bash
pip install -U sahmk
export SAHMK_API_KEY="your_api_key"
sahmk quote 2222

Python SDK:

python
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-pythonPyPI: 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.

bash
pip install sahmk-mcp

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

json
{
  "mcpServers": {
    "sahmk": {
      "command": "sahmk-mcp",
      "env": {
        "SAHMK_API_KEY": "your_api_key_here"
      }
    }
  }
}

Cursor

Add to your project's .cursor/mcp.json

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

Free

Get current price and trading data for a single stock.

Path Parameters:

  • symbol — Stock ticker (e.g., 2222 for Aramco)
View Response
json
{
  "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 orders
  • outflow_value — Total SAR value of sell orders
  • net_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
json
{
  "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/

Free

Get TASI index value, volume, and market sentiment.

View Response
json
{
  "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/

Free

Get top gaining stocks by percentage change.

Query Parameters:

  • limit — Number of results (default: 10, max: 50)
View Response
json
{
  "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/

Free

Get top losing stocks by percentage change.

Query Parameters:

  • limit — Number of results (default: 10, max: 50)
View Response
json
{
  "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/

Free

Get top stocks by trading volume.

Query Parameters:

  • limit — Number of results (default: 10, max: 50)
View Response
json
{
  "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/

Free

Get top stocks by trading value (SAR).

Query Parameters:

  • limit — Number of results (default: 10, max: 50)
View Response
json
{
  "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/

Free

Get sector performance and statistics.

View Response
json
{
  "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}/

Free

Get 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)
json
{
  "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
json
{
  "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
json
{
  "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
json
{
  "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
json
{
  "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:

text
wss://app.sahmk.sa/ws/v1/stocks/?api_key=YOUR_API_KEY

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

PlanMax symbols/connectionMax symbols/callSubscribe all (*)
Pro6020
EnterpriseCustomCustom

Tip: Use multiple connections to track more than 60 symbols on Pro plan.

Client → Server Messages

ActionMessageDescription
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

TypeDescription
connectedConnection confirmed with plan info
subscribedSubscription confirmed with symbol list
quoteReal-time price update
pongPing response
errorError message
View Connected Message Format
json
{
  "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
json
{
  "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

MetricREST PollingWebSocket
Latency1-60+ seconds<1 second
API calls/dayThousands1 connection
Missed updatesPossibleNone
ComplexitySimpleSlightly more

WebSocket Error Codes

CodeMeaning
4001Invalid or missing API key
4003Free plan — upgrade required
4004Account 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

MethodEndpointDescription
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

MethodEndpointDescription
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

ConditionDescriptionExample
price_aboveFires when stock price goes above the valuevalue: 30.00
price_belowFires when stock price goes below the valuevalue: 28.50
pct_changeFires when daily % change exceeds ±valuevalue: 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:

json
{
  "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_LIMIT

Free/Starter tried to access webhooks, or alert/webhook limit reached.

400VALIDATION

Missing or invalid fields in the request body.

404NOT_FOUND

Webhook or alert doesn't belong to this developer.

409DUPLICATE

Webhook URL already registered.

Webhook & Alert Limits

PlanWebhooksActive Alerts
Free
Starter
Pro310
EnterpriseCustomCustom

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

PlanDaily LimitBurst LimitAPI KeysWebSocketWebhooksAlerts
Free100/day10/min1
Starter5,000/day100/min3
Pro50,000/day500/min10310
Enterprise A (Shared)High-volume (Custom)CustomCustomCustomCustom
Enterprise B (Dedicated)Scales with resourcesScales with resourcesCustomCustomCustom

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:

http
X-RateLimit-Limit: 5000
X-RateLimit-Remaining: 4987
X-RateLimit-Reset: 2026-01-30T00:00:00+03:00

Error Codes

The API uses standard HTTP status codes and returns structured JSON error responses.

401INVALID_API_KEY

API key is missing, invalid, or revoked.

403PLAN_LIMIT

Endpoint requires a higher plan (e.g., historical data requires Starter+).

404INVALID_SYMBOL

Stock symbol not found in TASI or Nomu.

429RATE_LIMIT

Daily quota or per-minute burst limit exceeded.

500SERVER_ERROR

Internal server error. Please retry or contact support.

Error Response Format

json
{
  "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.