Skip to content

Commit e2c1e85

Browse files
committed
v0.9.1: Fix analytics endpoint paths to production API
Align analytics SDK calls with production endpoints by switching ratios and compare to /analytics routes, and return analytics responses in the API's native JSON shape without transformation. Made-with: Cursor
1 parent 82a348a commit e2c1e85

7 files changed

Lines changed: 52 additions & 32 deletions

File tree

CHANGELOG.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,17 @@ All notable changes to the `sahmk` Python SDK will be documented in this file.
44

55
This project follows [Semantic Versioning](https://semver.org/).
66

7+
## [0.9.1] — 2026-04-30
8+
9+
### Fixed
10+
11+
- Fix analytics endpoint paths to match production API.
12+
- `ratios()` now calls `GET /analytics/ratios/{symbol}/`
13+
- `compare()` now calls `GET /analytics/compare/`
14+
- Analytics SDK methods now return the production response shape as-is:
15+
- ratios: `symbol`, `ratios`, `meta`
16+
- compare: `results`, `count`, `meta`
17+
718
## [0.9.0] — 2026-04-30
819

920
### Added

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -223,8 +223,8 @@ Base URL: `https://app.sahmk.sa/api/v1`
223223
| `GET /companies/` | Free | Company directory and symbol discovery |
224224
| `GET /company/{symbol}/` | Free+ | Company info (tiered by plan) |
225225
| `GET /financials/{symbol}/` | Starter+ | Financial statements |
226-
| `GET /ratios/{symbol}/` | Starter+ | Analytics ratios for one company |
227-
| `GET /compare/` | Starter+ | Analytics comparison across companies |
226+
| `GET /analytics/ratios/{symbol}/` | Starter+ | Analytics ratios for one company |
227+
| `GET /analytics/compare/` | Starter+ | Analytics comparison across companies |
228228
| `GET /dividends/{symbol}/` | Starter+ | Dividend history and yield |
229229
| `GET /events/` | Pro+ | AI-generated stock events |
230230

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
44

55
[project]
66
name = "sahmk"
7-
version = "0.9.0"
7+
version = "0.9.1"
88
description = "Official Python SDK for Sahmk — Saudi market data and richer market workflows for developers."
99
readme = "README.md"
1010
requires-python = ">=3.9"

sahmk/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
Liquidity,
4040
)
4141

42-
__version__ = "0.9.0"
42+
__version__ = "0.9.1"
4343
__all__ = [
4444
"SahmkClient",
4545
"SahmkError",

sahmk/client.py

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -728,12 +728,11 @@ def ratios(self, symbol, history="latest", period="annual", metrics="core"):
728728
Get analytics ratios for a symbol.
729729
730730
Returns:
731-
RatiosResponse object
731+
Raw API response dict
732732
"""
733-
from .models import RatiosResponse
734-
data = self._request(
733+
return self._request(
735734
"GET",
736-
f"/ratios/{symbol}/",
735+
f"/analytics/ratios/{symbol}/",
737736
params=self._clean_params(
738737
{
739738
"history": history,
@@ -742,7 +741,6 @@ def ratios(self, symbol, history="latest", period="annual", metrics="core"):
742741
}
743742
),
744743
)
745-
return RatiosResponse.from_dict(data)
746744

747745
def compare(self, symbols, metrics="core"):
748746
"""
@@ -753,21 +751,19 @@ def compare(self, symbols, metrics="core"):
753751
metrics: Optional metrics set selector.
754752
755753
Returns:
756-
CompareResponse object
754+
Raw API response dict
757755
"""
758-
from .models import CompareResponse
759756
joined_symbols = ",".join(self._normalize_symbols(symbols))
760-
data = self._request(
757+
return self._request(
761758
"GET",
762-
"/compare/",
759+
"/analytics/compare/",
763760
params=self._clean_params(
764761
{
765762
"symbols": joined_symbols,
766763
"metrics": metrics,
767764
}
768765
),
769766
)
770-
return CompareResponse.from_dict(data)
771767

772768
def dividends(self, symbol):
773769
"""

tests/test_client.py

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -858,10 +858,10 @@ class TestAnalyticsEndpoints:
858858
def test_ratios_url_and_params(self, mock_client):
859859
responses.add(
860860
responses.GET,
861-
f"{mock_client.base_url}/ratios/1120/",
861+
f"{mock_client.base_url}/analytics/ratios/1120/",
862862
json={
863863
"symbol": "1120",
864-
"rows": [],
864+
"ratios": [],
865865
"meta": {"history": "latest", "period": "annual", "metrics": "core"},
866866
},
867867
status=200,
@@ -879,17 +879,18 @@ def test_ratios_url_and_params(self, mock_client):
879879
def test_compare_url_and_params(self, mock_client):
880880
responses.add(
881881
responses.GET,
882-
f"{mock_client.base_url}/compare/",
882+
f"{mock_client.base_url}/analytics/compare/",
883883
json={
884-
"rows": [],
884+
"results": [],
885+
"count": 0,
885886
"meta": {"metrics": "core"},
886887
},
887888
status=200,
888889
)
889890

890891
result = mock_client.compare(["1120", "1180", "1010"])
891892

892-
assert "rows" in result
893+
assert "results" in result
893894
request_url = responses.calls[0].request.url
894895
assert (
895896
"symbols=1120%2C1180%2C1010" in request_url
@@ -901,8 +902,8 @@ def test_compare_url_and_params(self, mock_client):
901902
def test_compare_accepts_comma_string_symbols(self, mock_client):
902903
responses.add(
903904
responses.GET,
904-
f"{mock_client.base_url}/compare/",
905-
json={"rows": [], "meta": {}},
905+
f"{mock_client.base_url}/analytics/compare/",
906+
json={"results": [], "count": 0, "meta": {}},
906907
status=200,
907908
)
908909

@@ -919,9 +920,9 @@ def test_compare_accepts_comma_string_symbols(self, mock_client):
919920
def test_compare_includes_coverage_in_response(self, mock_client):
920921
responses.add(
921922
responses.GET,
922-
f"{mock_client.base_url}/compare/",
923+
f"{mock_client.base_url}/analytics/compare/",
923924
json={
924-
"rows": [
925+
"results": [
925926
{
926927
"symbol": "1120",
927928
"company_name": "Al Rajhi",
@@ -933,14 +934,15 @@ def test_compare_includes_coverage_in_response(self, mock_client):
933934
"key_metrics": {"revenue_growth": 0.12},
934935
}
935936
],
937+
"count": 1,
936938
"meta": {"metrics": "core"},
937939
},
938940
status=200,
939941
)
940942

941943
result = mock_client.compare(["1120"])
942944

943-
assert result.rows[0].coverage["quality"] == "full"
945+
assert result["results"][0]["coverage"]["quality"] == "full"
944946

945947

946948
class TestEventsEndpoint:

tests/test_models.py

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -477,25 +477,36 @@ def test_compare_includes_coverage(self):
477477
def test_client_returns_ratios(self, client):
478478
responses.add(
479479
responses.GET,
480-
f"{client.base_url}/ratios/1120/",
481-
json=self.RATIOS_DATA,
480+
f"{client.base_url}/analytics/ratios/1120/",
481+
json={
482+
"symbol": "1120",
483+
"ratios": self.RATIOS_DATA["rows"],
484+
"meta": self.RATIOS_DATA["meta"],
485+
},
482486
status=200,
483487
)
484488
result = client.ratios("1120")
485-
assert isinstance(result, RatiosResponse)
486-
assert result.rows[0].report_date == "2025-12-31"
489+
assert isinstance(result, dict)
490+
assert result["symbol"] == "1120"
491+
assert "ratios" in result
492+
assert "meta" in result
487493

488494
@responses.activate
489495
def test_client_returns_compare(self, client):
490496
responses.add(
491497
responses.GET,
492-
f"{client.base_url}/compare/",
493-
json=self.COMPARE_DATA,
498+
f"{client.base_url}/analytics/compare/",
499+
json={
500+
"results": self.COMPARE_DATA["rows"],
501+
"count": len(self.COMPARE_DATA["rows"]),
502+
"meta": self.COMPARE_DATA["meta"],
503+
},
494504
status=200,
495505
)
496506
result = client.compare(["1120", "1180"])
497-
assert isinstance(result, CompareResponse)
498-
assert result.rows[0].company_name == "Al Rajhi Bank"
507+
assert isinstance(result, dict)
508+
assert "results" in result
509+
assert result["results"][0]["company_name"] == "Al Rajhi Bank"
499510

500511

501512
class TestEventsModel:

0 commit comments

Comments
 (0)