Viewing: Stocks
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 by symbol in minutes.
Build
Core API
Quotes, market data, company data, financials, and events.
Alerts & Webhooks
Notification workflow
Event webhooks, rules, delivery behavior, and 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 →
Quote path uses a symbol. If you need name/alias resolution, pass it through the optional identifier query param.
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.
Ambiguity note: If an identifier maps to multiple companies, pass the exact exchange symbol to disambiguate.
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 keysshmk_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 automated tooling.
pip install -U sahmk
export SAHMK_API_KEY="your_api_key"
sahmk quote "Saudi Aramco"If a newly documented SDK/CLI feature is missing locally, run pip install -U sahmk to upgrade.
Python SDK:
from sahmk import SahmkClient
client = SahmkClient(api_key="YOUR_API_KEY")
directory = client.companies(search="aramco", market="TASI", limit=20, offset=0)
symbol = directory["results"][0]["symbol"]
print(client.quote("أرامكو السعودية"))If symbol input is uncertain, call client.companies(...) first to discover a valid symbol before quote/company calls.
Use this when: you want less boilerplate than raw REST, typed workflows in Python, or quick command-line access to quotes and market data.
Quote methods accept identifiers (symbol, Arabic/English name, alias). Use symbol when the identifier is ambiguous.
Full examples: github.com/sahmk-sa/sahmk-python
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 -U sahmk-mcpIf MCP tools reject newer params (for example historical interval options), run pip install -U sahmk-mcp and restart your MCP client.
Package: pypi.org/project/sahmk-mcp · MCP quick start tutorial
Related Tutorials
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 extra integration glue first.
Use companies_list for symbol discovery (`search`, `market`, `limit`, `offset`) before quote tools.
Stocks
Get current stock quotes and prices for individual or multiple companies. See Real-time WebSocket for streaming updates.
GET /quote/{symbol}/
FreeGet current price and trading data for a single stock symbol.
Endpoint
https://app.sahmk.sa/api/v1/quote/2222/?identifier=أرامكو
Parameters
(*) Required
| Parameter | Type | Example |
|---|---|---|
| symbol * | string | 2222 |
| identifier | string | أرامكو |
| data_mode | string | delayed |
Use symbol when identifier lookup is ambiguous.data_mode supports realtime, delayed. If omitted, plan default behavior is used.
{
"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
}GET /quotes/
Starter+Get quotes for multiple companies in a single request. Requires Starter plan or higher.
Free tier fallback: GET /quote/{symbol}/ for single-company quotes.
Endpoint
https://app.sahmk.sa/api/v1/quotes/?symbols=2222,1120
Parameters
(*) Required
| Parameter | Type | Example |
|---|---|---|
| symbols * | string | 2222,1120 |
| identifiers | string | أرامكو، الراجحي |
| data_mode | string | realtime |
Use either symbols or identifiers, not both.data_mode supports realtime, delayed. If omitted, plan default behavior is used.
{
"quotes": [
{
"symbol": "2222",
"name": "أرامكو السعودية",
"name_en": "Saudi Arabian Oil Co",
"price": 25.86,
"change": 0.18,
"change_percent": 0.7,
"high": 25.90,
"low": 25.60,
"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,
"high": 109.10,
"low": 108.20,
"volume": 4023570,
"net_liquidity": 45230000.50,
"updated_at": "2026-02-10T12:18:56+00:00",
"is_delayed": false
}
],
"count": 2
}Need symbols? Use GET /companies/
Quick conventions: use path params for a single resource (for example /quote/{symbol}/) and query params for list filtering (for example /events/?symbol=2222&limit=20). Common HTTP/API errors are centralized in Error Codes.
Market
Get market-wide data including index values, top movers, and sector performance.
GET /market/summary/?index=TASI
FreeGet market index value, volume, and market sentiment.
Endpoint
https://app.sahmk.sa/api/v1/market/summary/?index=TASI
Parameters
(*) Required
| Parameter | Type | Example |
|---|---|---|
| index | string | TASI |
| data_mode | string | delayed |
Supported values: TASI, NOMU. Default is TASI.data_mode supports realtime, delayed. If omitted, plan default behavior is used.
{
"index": "TASI",
"is_delayed": true,
"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/?limit=10&index=TASI
FreeGet top gaining stocks by percentage change.
Endpoint
https://app.sahmk.sa/api/v1/market/gainers/?limit=10&index=TASI
Parameters
(*) Required
| Parameter | Type | Example |
|---|---|---|
| index | string | TASI |
| limit | number | 10 |
| data_mode | string | delayed |
data_mode supports realtime, delayed. If omitted, plan default behavior is used.
{
"index": "TASI",
"is_delayed": true,
"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/?limit=10&index=TASI
FreeGet top losing stocks by percentage change.
Endpoint
https://app.sahmk.sa/api/v1/market/losers/?limit=10&index=TASI
Parameters
(*) Required
| Parameter | Type | Example |
|---|---|---|
| index | string | TASI |
| limit | number | 10 |
| data_mode | string | delayed |
data_mode supports realtime, delayed. If omitted, plan default behavior is used.
{
"index": "TASI",
"is_delayed": true,
"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/?limit=10&index=TASI
FreeGet top stocks by trading volume.
Endpoint
https://app.sahmk.sa/api/v1/market/volume/?limit=10&index=TASI
Parameters
(*) Required
| Parameter | Type | Example |
|---|---|---|
| index | string | TASI |
| limit | number | 10 |
| data_mode | string | delayed |
data_mode supports realtime, delayed. If omitted, plan default behavior is used.
{
"index": "TASI",
"is_delayed": true,
"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/?limit=10&index=TASI
FreeGet top stocks by trading value (SAR).
Endpoint
https://app.sahmk.sa/api/v1/market/value/?limit=10&index=TASI
Parameters
(*) Required
| Parameter | Type | Example |
|---|---|---|
| index | string | TASI |
| limit | number | 10 |
| data_mode | string | delayed |
data_mode supports realtime, delayed. If omitted, plan default behavior is used.
{
"index": "TASI",
"is_delayed": true,
"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/?index=TASI
FreeGet sector performance and statistics.
Endpoint
https://app.sahmk.sa/api/v1/market/sectors/?index=TASI
Parameters
(*) Required
| Parameter | Type | Example |
|---|---|---|
| index | string | TASI |
| data_mode | string | delayed |
data_mode supports realtime, delayed. If omitted, plan default behavior is used.
{
"index": "TASI",
"is_delayed": true,
"sectors": [
{
"sector_name": "Banks",
"sector_name_ar": "البنوك",
"change_percent": 0.45,
"avg_change_percent": 0.38,
"volume": 45027873,
"num_stocks": 10
}
],
"count": 20
}View Endpoint-Specific Error (invalid index)
{
"error": {
"code": "INVALID_INDEX",
"message": "Invalid index 'XYZ'. Supported values: TASI, NOMU."
}
}Depth
Get order book depth snapshots for a symbol with selectable level controls. See Real-time WebSocket for streaming updates.
GET /market/depth/{symbol}/
Pro+Fetch depth snapshots for a symbol with requested level depth.
Endpoint
https://app.sahmk.sa/api/v1/market/depth/2222/?levels=5
Parameters
(*) Required
| Parameter | Type | Example |
|---|---|---|
| symbol * | string | 2222 |
| levels | integer | 5 (or any numeric value) |
Choose the depth you need with levels (typically 5 or up to 20). Returned depth may be lower based on your entitlement and current market-data availability.
Data availability by plan:
- Pro:Eligible for top-5 depth. Request access
- Business+:Eligible for top-20 Premium depth data. (Coming soon)
{
"symbol": "2222",
"updated_at": "2026-07-09T12:40:23.185897+00:00",
"session": "postmarket",
"book_state": "normal",
"levels": 5,
"best_bid": 26.68,
"best_ask": 26.72,
"spread": 0.04,
"spread_bps": 14.99,
"bids": [
{ "level": 0, "price": 26.68, "quantity": 79, "order_count": 10 },
{ "level": 1, "price": 26.66, "quantity": 82, "order_count": 4 },
{ "level": 2, "price": 26.64, "quantity": 565, "order_count": 10 },
{ "level": 3, "price": 26.62, "quantity": 7081, "order_count": 14 },
{ "level": 4, "price": 26.6, "quantity": 21278, "order_count": 26 }
],
"asks": [
{ "level": 0, "price": 26.72, "quantity": 41188, "order_count": 38 },
{ "level": 1, "price": 26.74, "quantity": 38841, "order_count": 23 },
{ "level": 2, "price": 26.76, "quantity": 20031, "order_count": 23 },
{ "level": 3, "price": 26.78, "quantity": 20361, "order_count": 23 },
{ "level": 4, "price": 26.8, "quantity": 384223, "order_count": 68 }
]
}Depth Serving Notes
- The API returns the best available snapshot at request time.
- Returned depth may be lower than requested based on entitlement and current market-data availability.
View Endpoint-Specific Errors
{
"error": {
"code": "DEPTH_NOT_AVAILABLE",
"message": "No usable depth snapshot found for '2222'."
}
}
{
"error": {
"code": "MARKET_DATA_ENTITLEMENT_REQUIRED",
"message": "Market-depth access requires an approved entitlement."
}
}Company / Symbol APIs
Discover valid symbols and fetch detailed company information.
GET /companies/
FreeLightweight company directory for symbol discovery before calling quote or company endpoints.
Endpoint
https://app.sahmk.sa/api/v1/companies/?search=aramco&market=TASI&limit=20&offset=0
Parameters
(*) Required
| Parameter | Type | Example |
|---|---|---|
| search | string | aramco |
| market | string | TASI |
| limit | number | 20 |
| offset | number | 0 |
{
"results": [
{
"symbol": "2222",
"name_ar": "أرامكو السعودية",
"name_en": "Saudi Arabian Oil Co",
"market": "TASI",
"status": "active"
}
],
"count": 1,
"total": 590,
"limit": 100,
"offset": 0
}View Errors
{
"error": {
"code": "INVALID_MARKET",
"message": "market must be one of: TASI, NOMU."
}
}
{
"error": {
"code": "INVALID_PARAM",
"message": "limit and offset must be valid integers."
}
}GET /company/{symbol}/
FreeGet company information. Response varies by plan.
Data Available by Plan:
- Free:Name, sector_name, sector_name_ar, market_id, sector (deprecated), industry (deprecated), description, website
- Starter:+ Full fundamentals (PE, EPS, book value, beta, week/month/52w ranges)
- Pro+:+ Technicals, valuation, analyst consensus
Endpoint
https://app.sahmk.sa/api/v1/company/2222/
Parameters
(*) Required
| Parameter | Type | Example |
|---|---|---|
| symbol * | string | 2222 |
{
"symbol": "2222",
"name": "أرامكو السعودية",
"name_en": "Saudi Arabian Oil Co",
"current_price": 25.64,
"is_delayed": false,
"market_id": "TASI",
"sector_name": "Energy",
"sector_name_ar": "الطاقة",
"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
}
}Deprecation plan: sector and industry remain available for backward compatibility and are planned for removal on 2026-07-01.
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.
Endpoint
https://app.sahmk.sa/api/v1/historical/2222/?from=2026-01-01&to=2026-01-28&interval=1d
Parameters
(*) Required
| Parameter | Type | Example |
|---|---|---|
| symbol * | string | 2222 |
| from | string | 2026-01-01 |
| to | string | 2026-01-28 |
| interval | string | 1d |
from: default is ~30 days ago. to: default is today. interval: 1d, 1w, 1m, 30m, 60m (default 1d).
Data Available by Plan:
- Free:No historical access
- Starter:
1d,1w,1m - Pro:Starter intervals +
60mup to 90 days - Business:Starter intervals +
30mup to 6 months +60mup to 1 year - Enterprise:Business availability by default; custom retention, intervals, and delivery options are available by agreement
If the requested interval or date range exceeds your plan limits, the API returns 403 PLAN_LIMIT.
Need a practical intraday workflow? See Intraday Data with SAHMK (SDK + MCP).
{
"symbol": "2222",
"interval": "1d",
"from": "2026-01-01",
"to": "2026-01-28",
"metadata": {
"interval": "1d",
"source": "daily_aggregate",
"is_intraday": false,
"is_final": true,
"partial": false,
"latest_bar_at": "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
}
]
}Candle Row Format
30m/60m return timestamped candles, while 1d/1w/1m return date-based candles.
Financials
Access structured income statement, balance sheet, and cash flow data for Saudi listed companies.
GET /financials/{symbol}/
Starter+Endpoint
https://app.sahmk.sa/api/v1/financials/1120/?period=annual&history=5y&metrics=extended
Parameters
(*) Required
| Parameter | Type | Example |
|---|---|---|
| symbol * | string | 1120 |
| type | string | all |
| period | string | quarterly |
| history | string | 5y |
| metrics | string | extended |
| result | string | series |
type: income, balance, cashflow, all. period: annual, quarterly, auto. history: 1y, 3y, 5y, 10y, max. metrics: core, extended. result: series, latest. Optional flags: include_future_placeholders=1, include_partial=1.
Behavior Notes
period=autoresolves toannualwhen the latest fiscal year is full-year, otherwisequarterly.- Annual history returns completed fiscal years by default; use
include_partial=1to include the current incomplete annual/YTD row. - Quarterly mode returns the latest available quarters by default.
result=latestfollows the selected/resolved granularity; in annual mode it returns the latest completed year by default unlessinclude_partial=1is used.- API default remains
period=annualfor backward compatibility. - Statements are returned in arrays such as
income_statements,balance_sheets, andcash_flows. - Responses also include context fields like
symbol,statement_period, and optionalqualitywhen requested.
Data Available by Plan:
- Starter:Annual + core + up to 3 completed fiscal years + latest snapshot
- Pro/Business:Quarterly + extended + 5Y/10Y/max + full views
- Enterprise:Custom financials feature set and access profile by agreement
Response Example
{
"symbol": "1120",
"statement_period": "annual",
"quality": {
"coverage": "high",
"warnings": []
},
"income_statements": [
{
"report_date": "2025-09-30",
"total_revenue": 123456789.0,
"net_income": 9876543.0
}
]
}Analytics
Compare and analyze company ratios with compact analytics endpoints.
GET /analytics/ratios/{symbol}/
Starter+Financial ratios for one symbol.
Endpoint
https://app.sahmk.sa/api/v1/analytics/ratios/1120/?history=5y&period=quarterly&metrics=extended
Parameters
(*) Required
| Parameter | Type | Example |
|---|---|---|
| symbol * | string | 1120 |
| history | string | 5y |
| period | string | quarterly |
| metrics | string | extended |
| meta | string | extended |
history: latest, 3y, 5y, 10y, max (default latest). period: annual, quarterly (default annual). metrics: core, extended (default core). meta: minimal (default) or extended.
Data Available by Plan:
- Free:No analytics access
- Starter:Latest + annual + core only
- Pro/Business:All ratios options (history, period, metrics)
- Enterprise:Custom ratios feature set and access profile by agreement
{
"symbol": "1120",
"ratios": [
{
"report_date": "2025-12-31",
"statement_period": "annual",
"fiscal_year": 2025,
"fiscal_quarter": null,
"ratios": {
"roe": 9.77,
"roa": 3.89,
"net_margin": 19.09,
"debt_to_equity": 0.6,
"revenue_growth_yoy": 10.0,
"net_income_growth_yoy": 16.67
},
"key_metrics": {
"total_revenue": 1100.0,
"operating_income": 250.0,
"net_income": 210.0,
"operating_cash_flow": 280.0,
"total_assets": 5400.0,
"stockholders_equity": 2150.0,
"total_debt": 1300.0
}
}
],
"meta": {
"period": "annual",
"metrics": "core",
"warnings": []
}
}GET /analytics/compare/
Starter+Compare ratio snapshots across multiple symbols.
Endpoint
https://app.sahmk.sa/api/v1/analytics/compare/?symbols=1120,1180,1010,2222&metrics=extended
Parameters
(*) Required
| Parameter | Type | Example |
|---|---|---|
| symbols * | string | 1120,1180,1010,2222 |
| metrics | string | extended |
| meta | string | extended |
symbols is required as comma-separated values (example 1120,1180,1010). metrics: core or extended (default core). meta: minimal (default) or extended.
Data Available by Plan:
- Starter:Up to 3 symbols + core metrics only
- Pro:Up to 10 symbols + core/extended metrics
- Business:Up to 20 symbols + core/extended metrics
- Enterprise:Custom symbol limits and compare feature profile by agreement
{
"results": [
{
"symbol": "1120",
"company_name": "الراجحي",
"market_id": "TASI",
"sector_name": "Financial Services",
"sector_name_ar": "الخدمات المالية",
"sector": "Financial Services",
"market_cap": 1000001120.0,
"current_price": 89.4,
"ratios": {
"roe": 9.77,
"roa": 3.89,
"net_margin": 19.09,
"debt_to_equity": 0.6,
"revenue_growth_yoy": 10.0,
"net_income_growth_yoy": 16.67,
"asset_turnover": 0.2037,
"debt_ratio": 0.2407
},
"key_metrics": {
"total_revenue": 1100.0,
"operating_income": 250.0,
"net_income": 210.0,
"operating_cash_flow": 280.0,
"total_assets": 5400.0,
"stockholders_equity": 2150.0,
"total_debt": 1300.0
}
}
],
"count": 1,
"meta": {
"period": "annual",
"metrics": "extended",
"warnings": []
}
}Deprecation plan: sector remains temporarily and is planned for removal on 2026-07-01. Use sector_name and sector_name_ar going forward.
Integration tips
- Default metadata is minimal:
meta.period,meta.metrics,meta.warnings. - Use
meta=extendedfor extra fields (ratios:coverage,periods_available,quality,partial_context; compare rows:coverage). - Ratio keys are dynamic, so render ratio objects dynamically.
Dividends
Get dividend history, upcoming distributions, and trailing yield for a stock.
GET /dividends/{symbol}/
Starter+Get dividend history and yield information.
Endpoint
https://app.sahmk.sa/api/v1/dividends/2222/?limit=10
Parameters
(*) Required
| Parameter | Type | Example |
|---|---|---|
| symbol * | string | 2222 |
| limit | number | 10 |
{
"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.
GET /events/
Pro+Get stock events with AI-generated analysis.
Note
Event types are UPPERCASE (e.g., FINANCIAL_REPORT, DIVIDEND_ANNOUNCEMENT).
Endpoint
https://app.sahmk.sa/api/v1/events/?symbol=4190&importance=IMPORTANT&limit=20
Parameters
(*) Required
| Parameter | Type | Example |
|---|---|---|
| symbol | string | 4190 |
| type | string | FINANCIAL_REPORT |
| importance | string | IMPORTANT |
| limit | number | 20 |
{
"events": [
{
"symbol": "4190",
"stock_name": "جرير للتسويق",
"event_type": "FINANCIAL_REPORT",
"importance": "important",
"sentiment": "positive",
"description": "شركة جرير للتسويق تعلن عن نتائج مالية قياسية للربع الرابع 2025...",
"event_date": "2026-01-29",
"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", "OTHER"
]
}available_types: Server-defined list that may expand in future releases.
importance: critical, important, regular
sentiment: very_positive, positive, slightly_positive, neutral, slightly_negative, negative, very_negative
Real-time WebSocket - Stocks
Stream real-time quote updates through the stocks channel.
WS /ws/v1/stocks/
Pro+Real-time quotes channel for live stock updates.
Endpoint
wss://app.sahmk.sa/ws/v1/stocks/?api_key=YOUR_API_KEY
Connected message
{
"type": "connected",
"plan": "enterprise",
"delivery_profile": "standard",
"limits": {
"max_symbols_per_connection": 200,
"max_symbols_per_call": 100,
"stream_modes": ["standard"]
},
"message": "Connected to SAHMK real-time stock stream",
"timestamp": "2026-07-09T15:05:37.749535+00:00"
}Client actions
{"action":"subscribe","symbols":["2222","1120"]}
{"action":"unsubscribe","symbols":["1120"]}
{"action":"ping"}
{"action":"subscribe","symbols":["*"]} // Enterprise onlyQuote message
{
"type": "quote",
"symbol": "2222",
"mode": "standard",
"data": {
"price": 25.86,
"bid": 25.84,
"ask": 25.88
},
"timestamp": "2026-07-09T15:05:41.114000+00:00",
"latency_ms": 14
}Related Tutorials
Real-time WebSocket - Depth
Stream real-time level-by-level bid/ask depth updates through the depth channel.
WS /ws/v1/market/depth/
Pro+Real-time depth channel for level-by-level bid/ask streaming.
Endpoint
wss://app.sahmk.sa/ws/v1/market/depth/?api_key=YOUR_API_KEY
Data availability by plan:
- Pro:Eligible for top-5 depth. Request access
- Business+:Eligible for top-20 Premium depth data. (Coming soon)
Connected message
{
"type": "connected",
"channel": "depth",
"plan": "enterprise",
"mode": "customer_production",
"limits": {
"entitled_levels": 20,
"max_symbols_per_connection": 200,
"max_symbols_per_call": 100,
"wildcard_allowed": true,
"max_concurrent_wildcard_streams": 1
},
"timestamp": "2026-07-09T15:05:37.840967+00:00"
}Client actions
{"action":"snapshot","symbol":"2222","levels":5}
{"action":"subscribe","symbols":["2222","1120"],"levels":20}
{"action":"unsubscribe","symbols":["1120"]}
{"action":"ping"}
{"action":"subscribe","symbols":["*"],"levels":20} // Enterprise onlyDepth snapshot message
{
"type": "depth_snapshot",
"symbol": "2222",
"available": true,
"session": "postmarket",
"book_state": "normal",
"bids": [
{
"level": 0,
"price": 26.68,
"quantity": 79,
"order_count": 10
}
],
"asks": [
{
"level": 0,
"price": 26.72,
"quantity": 41188,
"order_count": 38
}
],
"entitled_levels": 20,
"timestamp": "2026-07-09T15:05:37.872738+00:00"
}Real-time WebSocket - Errors
Handle websocket failures with a unified error envelope and reconnect policy.
WS_AUTH_OR_POLICYMARKET_DATA_ENTITLEMENT_*Account policy or entitlement issue blocks streaming access.
Action: Do not auto-reconnect. Resolve account state first.
WS_RATE_LIMITDEPTH_WS_*_LIMIT / *_RATE_LIMITEDConnection, subscription, or action throttles were exceeded.
Action: Backoff, reduce load, and retry.
WS_INVALID_REQUESTINVALID_JSON / UNKNOWN_ACTION / SYMBOL_REQUIREDMalformed payload or unsupported action.
Action: Fix payload and retry immediately.
Error Envelope
{
"type": "error",
"code": "ERROR_CODE",
"message": "Human-readable message",
"details": {}
}Real-time WebSocket - Limits
Compare plan limits across real-time Stocks and Depth channels.
Depth channel subscription limits
| Plan | Entitled levels | Max symbols/connection | Max symbols/call | Subscribe all (*) |
|---|---|---|---|---|
| Pro | 5 | 60 | 20 | No |
| Business | 20 | 120 | 40 | No |
| Enterprise | 20 | 200 | Up to 100 | Yes |
Stocks channel subscription limits
| Plan | Max symbols/connection | Max symbols/call | Subscribe all (*) |
|---|---|---|---|
| Pro | 60 | 20 | No |
| Business | 120 | 40 | No |
| Enterprise | 200 | Up to 100 | Yes |
Alerts & Webhooks - Overview
Configure event-driven notifications using alert rules and webhook destinations.
Dashboard + API model
/api/v1/webhooks/ and /api/v1/alerts/). Both paths produce the same webhook delivery envelope.Event Webhooks
Register secure destinations and verify delivery endpoints.
Event Rules
Define symbols, thresholds, and trigger conditions.
Delivery Lifecycle
Track statuses from queued to delivered or failed.
Payload Reference
Canonical event envelope and field contract.
Signature Verification
Validate webhook signatures before processing.
Event History
Inspect delivery outcomes and retries.
Event Types & Conditions
Review supported event types and conditions_matched shapes.
Error Codes
Use code-to-action mappings for integration troubleshooting.
Alerts & Webhooks - Event Webhooks
Register and verify webhook endpoints before enabling alert rules.
POST /api/v1/webhooks/
Pro+Create a webhook destination for alerts and webhook notifications.
Endpoint
https://app.sahmk.sa/api/v1/webhooks/
Parameters
(*) Required
| Parameter | Type | Example |
|---|---|---|
| url * | string | https://example.com/hooks/sahmk |
| name | string | Trading Production Hook |
Authentication uses X-API-Key: YOUR_API_KEY.
- Required:
url(HTTPS destination URL) - Optional:
name(friendly label) - Verification: a challenge handshake is sent on create; success requires HTTP 200.
- Secret handling:
signing_secretis returned only on create and is not included in list/get responses.
{
"id": 19,
"url": "https://example.com/hooks/sahmk",
"name": "Trading Production Hook",
"signing_secret": "xxxxxxxxxxxxxxxx",
"is_verified": false,
"is_active": true,
"created_at": "2026-05-08T13:30:12+03:00"
}Next step: continue with Signature Verification and Delivery Lifecycle for production readiness.
Alerts & Webhooks - Payload Reference
Webhook deliveries use one canonical envelope across all real-time event types, whether rules are created in Dashboard or via API.
Webhook Event Envelope
Pro+Canonical payload shape for webhook consumers.
{
"event_id": "9a6b8f22-2d1d-4b3f-b75f-7f9d5f101234",
"event_type": "large_move",
"symbol": "2222",
"detected_at": "2026-05-08T13:48:22+03:00",
"severity": "important",
"title": "Large move detected",
"summary": "Price moved more than configured threshold in the selected window.",
"metrics": {
"price": 25.86,
"pct_change": 3.4,
"volume": 9803705,
"value": 252308343.0,
"avg_volume": 8243000,
"reference_value": 245000000.0,
"rolling_volume_baseline": 4100000,
"rolling_value_baseline": 120000000.0,
"baseline_source": "rolling_window",
"baseline_sample_count": 30,
"volume_baseline_sample_count": 30,
"value_baseline_sample_count": 30,
"high": 25.86,
"low": 25.60,
"change": 0.85,
"window": "15m",
"threshold": 3.0
},
"conditions_matched": {
"window": "15m",
"operator": "abs>=",
"observed_pct_change": 3.4,
"threshold_pct": 3.0,
"baseline_price": 25.01,
"current_price": 25.86
},
"correlation_id": "webhook-evt-01HXY...",
"version": "v1"
}event_idevent_typesymboldetected_atseveritytitle,summary
metricsconditions_matchedcorrelation_idversion
Important
unusual_value_traded uses rolling traded-value baseline (value / rolling_value_baseline), not reference_value.Forward compatibility: clients should ignore unknown keys and rely on required top-level fields.
Alerts & Webhooks - Event Rules
Define market conditions and actions that trigger webhook deliveries. You can create rules in Dashboard or programmatically with this API.
POST /api/v1/alerts/
Pro+Create an alert rule that triggers webhook deliveries when conditions match.
Supported event types
price_alertlarge_moveabnormal_volumeunusual_value_tradedEndpoint
https://app.sahmk.sa/api/v1/alerts/
Parameters
(*) Required
| Parameter | Type | Example |
|---|---|---|
| symbol * | string | 2222 |
| event_type * | string | large_move |
| condition * | string | pct_change_abs_gte |
| value * | number | 3.0 |
| webhook_id * | number | 19 |
| once | boolean | false |
Rule design guidance
- Start with narrow symbol scope and explicit thresholds.
- Use cooldown windows to reduce notification noise.
- Validate in staging before enabling production rules.
{
"id": 57,
"symbol": "2222",
"event_type": "large_move",
"condition": "pct_change_abs_gte",
"value": 3.0,
"webhook_id": 19,
"status": "active"
}GET /api/v1/alerts/
Pro+List existing rules and optionally filter by status.
Endpoint
https://app.sahmk.sa/api/v1/alerts/?status=active
Parameters
(*) Required
| Parameter | Type | Example |
|---|---|---|
| status | string | active |
- Query:
status=active|paused|all - Status enum:
active,paused,triggered - Mapping:
oncemaps tofire_once.
{
"results": [
{
"id": 57,
"symbol": "2222",
"event_type": "large_move",
"status": "active",
"fire_once": false
}
],
"count": 1
}Alerts & Webhooks - Event Types & Conditions
Supported event types and primary condition selectors for rule configuration.
| Event type | Conditions |
|---|---|
| price_alert | price_above, price_below, pct_change |
| large_move | pct_change_abs_gte |
| abnormal_volume | ratio_gte |
| unusual_value_traded | ratio_gte |
conditions_matched Contracts
Event-specific shape differences are primarily expressed in conditions_matched.
{
"price_alert": {
"price_above": { "operator": ">", "observed": 26.1, "threshold": 26.0 },
"price_below": { "operator": "<", "observed": 24.8, "threshold": 25.0 },
"pct_change": { "operator": "abs>=", "observed": 3.2, "threshold": 3.0 }
},
"large_move": {
"window": "15m",
"operator": "abs>=",
"observed_pct_change": 3.4,
"threshold_pct": 3.0,
"baseline_price": 25.01,
"current_price": 25.86
},
"abnormal_volume": {
"event_type": "abnormal_volume",
"operator": ">=",
"metric": "volume_ratio",
"current_value": 9803705,
"baseline_value": 4100000,
"ratio": 2.39,
"threshold": 2.0
},
"unusual_value_traded": {
"event_type": "unusual_value_traded",
"operator": ">=",
"metric": "value_ratio",
"current_value": 252308343.0,
"baseline_value": 120000000.0,
"ratio": 2.1,
"threshold": 2.0
}
}Numeric encoding is JSON number (not string). ratio and observed_pct_change are rounded to 4 decimals.
Alerts & Webhooks - Delivery Lifecycle
Monitor queued, delivered, failed, and retry statuses for operational visibility.
Delivery Lifecycle
Pro+Current lifecycle states and retry sequence for webhook delivery attempts.
Status flow: pending -> retrying -> delivered or dead_letter.
Retry backoff: 2s, 10s, 60s.
Attempts: 4 total (initial attempt + 3 retries), with no jitter.
Retry trigger: all non-2xx outcomes are retried (4xx, 5xx, timeout, and connection errors) until attempts are exhausted.
Use event_id and correlation_id for end-to-end tracing.
No public replay endpoint is currently available for dead-letter events.
Where to manage
Alerts & Webhooks - Signature Verification
Verify each webhook request signature before processing events in production.
Use the endpoint-specific signing secret returned when creating the webhook destination.
Delivery headers include X-SAHMK-Signature, X-SAHMK-Event, and X-SAHMK-Event-Id.
- Each delivery includes
X-SAHMK-Signature. - Signature generation uses HMAC-SHA256 over canonical payload.
- Reject mismatches with HTTP 401.
# Header format:
# X-SAHMK-Signature: t=<unix_ts>,v1=<hex_hmac>
timestamp, received = parse_signature_header(request.headers["X-SAHMK-Signature"])
canonical_json = json.dumps(payload, sort_keys=True, separators=(",", ":"))
signed_payload = f"{timestamp}.{canonical_json}"
computed = HMAC_SHA256(signing_secret, signed_payload)
if computed != received:
return 401
process_event(payload)Timestamp is included in the signature header. Receivers should apply a time-window check for replay protection.
Alerts & Webhooks - Event History
Query recent delivery outcomes for observability and troubleshooting.
GET /api/v1/events/history/
Pro+List event delivery records by status/type with pagination.
Authentication: X-API-Key: YOUR_API_KEY
Endpoint
https://app.sahmk.sa/api/v1/events/history/?status=retrying&limit=20&offset=0
Parameters
(*) Required
| Parameter | Type | Example |
|---|---|---|
| status | string | retrying |
| event_type | string | abnormal_volume |
| workspace_id | number | 1 |
| limit | number | 20 |
| offset | number | 0 |
- Optional query:
status(pending, delivered, retrying, dead_letter) - Optional query:
event_type - Optional query:
workspace_id - Pagination:
limitandoffset
Defaults: limit=50, offset=0. Maximum limit=100.
Current Status
<!doctype html>
<html lang="en">
<head><title>Not Found</title></head>
<body>
<h1>Not Found</h1>
<p>The requested resource was not found on this server.</p>
</body>
</html>Alerts & Webhooks - Error Codes
Handle webhook delivery failures with retry-safe consumers and clear status mapping.
Operational guidance
- Treat delivery attempts as idempotent; duplicate deliveries can occur on retry.
- Return 2xx quickly after durable persistence; process heavy work asynchronously.
- Track delivery IDs and failure reasons for support and reconciliation.
400INVALID_PARAMInvalid payload field or unsupported query option.
Action: Fix request payload and retry.
401INVALID_API_KEYMissing, invalid, or revoked API key.
Action: Rotate/regenerate key and retry.
403PLAN_LIMIT / FEATURE_DISABLEDPlan lacks feature access or limits were reached.
Action: Upgrade plan or adjust usage.
404NOT_FOUNDWebhook or alert resource was not found for this account.
Action: Verify resource id and ownership context.
429RATE_LIMITEDBurst or quota throttle reached.
Action: Backoff and retry with jitter.
Error Response Format
{
"error": {
"code": "ERROR_CODE",
"message": "Human-readable message"
}
}Realtime WebSocket errors
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 | Event Webhooks | Event Rules |
|---|---|---|---|---|---|---|
| Free | 100/day | 10/min | 1 | ✗ | 0 | 0 |
| Starter | 5,000/day | 100/min | 3 | ✗ | 0 | 0 |
| Pro | 50,000/day | 500/min | 10 | ✓ | 3 | 10 |
| Business | 150,000/day | 1,000/min | 30 | ✓ | 10 | 50 |
| Enterprise | Custom | Custom | Custom | ✓ | Custom | Custom |
Burst Protection: To prevent abuse and protect stability, per-minute throttling is applied at both API-key and account levels. Requests exceeding these limits return HTTP 429. Daily limits reset at midnight (UTC+3). Enterprise limits are contract-based and may be 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: 1769816400X-RateLimit-Reset is a Unix timestamp (seconds).
Error Codes
The API uses standard HTTP status codes and returns structured JSON error responses.
400INVALID_ROUTEWrong endpoint path was used. The API returns a suggested correct route.
401INVALID_API_KEYAPI key is missing, invalid, or revoked.
403PLAN_LIMITEndpoint requires a higher plan (e.g., historical data requires Starter+, or higher-tier financials combinations are requested on Starter).
404INVALID_SYMBOLCompany identifier not resolved in TASI or Nomu. Use the exchange symbol when ambiguous.
429RATE_LIMITDaily quota or per-minute burst limit exceeded.
500SERVER_ERRORInternal server error. Please retry or contact support.
Some new free accounts may temporarily hit a security limit. If this happens, the API may return HTTP 429 with error code TEMP_SECURITY_LIMIT. User action: try again later or upgrade for higher limits.
Common integration error: Calling GET /api/v1/quote/batch/ returns 400 INVALID_ROUTE with route guidance.
{
"error": {
"code": "INVALID_ROUTE",
"message": "Did you mean /api/v1/quotes/?symbols=2222,1120 ?"
}
}Error Response Format
{
"error": {
"code": "RATE_LIMIT",
"message": "Daily request limit exceeded. Resets at midnight UTC+3."
}
}