Skills sectors-api
git clone https://github.com/openclaw/skills
T=$(mktemp -d) && git clone --depth=1 https://github.com/openclaw/skills "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/aidityasadhakim/sectors-financial-agents" ~/.claude/skills/clawdbot-skills-sectors-api && rm -rf "$T"
skills/aidityasadhakim/sectors-financial-agents/SKILL.mdSectors API
Query IDX and SGX financial market data through the Sectors REST API.
Full API docs: https://sectors.app/api
Constraints
- ONLY make HTTP requests to
. Never call any other domain, database, or external service.https://api.sectors.app/v1 - All endpoints are
requests returning JSON.GET - Never hardcode or guess an API key. Always read it from the
environment variable.SECTORS_API_KEY - If
is not set, prompt the user to set it:SECTORS_API_KEY
or run the setup check script atexport SECTORS_API_KEY="your-api-key-here"
.scripts/check_setup.py
Setup
1. Set the API key
The API key must be available as the
SECTORS_API_KEY environment variable.
# Option A: Set in your current shell export SECTORS_API_KEY="your-api-key-here" # Option B: Add to your shell profile (~/.bashrc, ~/.zshrc) for persistence echo 'export SECTORS_API_KEY="your-api-key-here"' >> ~/.bashrc # Option C: Use a .env file in the project root (see .env.example)
For agent-specific configuration:
- Claude Code:
claude config set env SECTORS_API_KEY your-api-key-here - OpenCode: Set in
under~/.config/opencode/config.jsonenv - Cursor: Settings > Features > Environment Variables
2. Install the dependency
pip install requests
3. Verify setup (optional)
python scripts/check_setup.py
Making requests
import os import requests API_KEY = os.environ["SECTORS_API_KEY"] BASE_URL = "https://api.sectors.app/v1" headers = {"Authorization": API_KEY} response = requests.get(f"{BASE_URL}/subsectors/", headers=headers) data = response.json()
The
Authorization header takes the raw API key. Do NOT prefix it with Bearer.
Endpoint decision table
Pick the right endpoint based on what the user needs:
Market structure
| User wants | Endpoint | Required params |
|---|---|---|
| List all subsectors | | none |
| List all industries | | none |
| List all subindustries | | none |
| SGX sector list | | none |
Company discovery
| User wants | Endpoint | Required params |
|---|---|---|
| Companies in a subsector | | |
| Companies in a subindustry | | |
| Companies in a stock index | | |
| Companies with segment data | | none |
| SGX companies by sector | | |
Company details
| User wants | Endpoint | Required params |
|---|---|---|
| Full company report (IDX) | | |
| SGX company report | | |
| Listing performance | | |
| Quarterly financial dates | | |
| Quarterly financials | | |
| Company segments | | |
Market data
| User wants | Endpoint | Required params |
|---|---|---|
| Daily stock price | | |
| Index daily data | | |
| Index summary | | |
| IDX total market cap | | none |
Rankings and screening
| User wants | Endpoint | Required params |
|---|---|---|
| Top gainers/losers | | none (all optional) |
| Top companies by metric | | none (all optional) |
| Top growth companies | | none (all optional) |
| Most traded stocks | | none (all optional) |
| SGX top companies | | none (all optional) |
For full parameter lists and response schemas, see:
- references/idx-endpoints.md -- all 18 IDX endpoints
- references/sgx-endpoints.md -- all 6 SGX endpoints
- assets/endpoint-map.md -- quick-lookup table
Common patterns
Fetch a company report
import os import requests API_KEY = os.environ["SECTORS_API_KEY"] BASE_URL = "https://api.sectors.app/v1" headers = {"Authorization": API_KEY} ticker = "BBCA" params = {"sections": "overview,valuation,financials"} resp = requests.get(f"{BASE_URL}/company/report/{ticker}/", headers=headers, params=params) report = resp.json() print(report["company_name"]) print(report["overview"]["market_cap"])
Available sections:
overview, valuation, future, peers, financials, dividend, management, ownership. Use all or omit for everything.
Get daily stock prices in a date range
import os import requests API_KEY = os.environ["SECTORS_API_KEY"] BASE_URL = "https://api.sectors.app/v1" headers = {"Authorization": API_KEY} ticker = "BBRI.JK" # Normalize: uppercase, strip .JK clean = ticker.upper().replace(".JK", "") params = {"start": "2025-01-01", "end": "2025-01-31"} resp = requests.get(f"{BASE_URL}/daily/{clean}", headers=headers, params=params) prices = resp.json() for day in prices: print(day["date"], day["close"], day["volume"])
Find top gainers and losers
import os import requests API_KEY = os.environ["SECTORS_API_KEY"] BASE_URL = "https://api.sectors.app/v1" headers = {"Authorization": API_KEY} params = { "classifications": "top_gainers,top_losers", "periods": "7d,30d", "n_stock": 5, "min_mcap_billion": 5000, } resp = requests.get(f"{BASE_URL}/companies/top-changes/", headers=headers, params=params) movers = resp.json() for stock in movers["top_gainers"]["7d"]: print(stock["symbol"], stock["price_change"])
List companies in an index
import os import requests API_KEY = os.environ["SECTORS_API_KEY"] BASE_URL = "https://api.sectors.app/v1" headers = {"Authorization": API_KEY} # Available: lq45, idx30, kompas100, jii70, idxhidiv20, srikehati, etc. resp = requests.get(f"{BASE_URL}/index/lq45/", headers=headers) companies = resp.json() for c in companies: print(c["symbol"], c["company_name"])
SGX company report
import os import requests API_KEY = os.environ["SECTORS_API_KEY"] BASE_URL = "https://api.sectors.app/v1" headers = {"Authorization": API_KEY} ticker = "D05" # DBS Group resp = requests.get(f"{BASE_URL}/sgx/company/report/{ticker}", headers=headers) report = resp.json() print(report["name"]) print(report["valuation"]["pe"]) print(report["financials"]["gross_margin"])
Ticker normalization
| Market | Rule | Example |
|---|---|---|
| IDX | Uppercase, strip suffix | -> |
| SGX | Uppercase, strip suffix | -> |
Always normalize before passing to an endpoint.
Gotchas
-
Auth header format: Use
. NOTAuthorization: <raw_key>
. NOTBearer <key>
.Authorization: Bearer <key> -
Date format: Always
. Example:YYYY-MM-DD
.2025-06-15 -
Date range limit: The
endpoint requires start and end dates within 90 days of each other./most-traded/ -
Kebab-case for subsectors and sectors: Use
,banks
,financing-service
. Not camelCase or snake_case.consumer-defensive -
Nested response structure: Ranking endpoints (
,top-changes
,top
) return objects keyed by classification, then by period. Always navigate both levels.top-growth# top-changes returns: { "top_gainers": { "7d": [...], "30d": [...] } } # top returns: { "dividend_yield": [...], "revenue": [...] } -
Market cap units: IDX values are in billion IDR (
). SGX values are in million SGD (min_mcap_billion
).min_mcap_million -
Default values matter: Many optional params default to
or specific values (e.g."all"
defaults to 5,n_stock
defaults to 5000). Be explicit when you need different behavior.min_mcap_billion -
Index codes: IDX index daily data uses lowercase codes:
,ihsg
,lq45
. Company-by-index uses the same codes.idx30 -
Quarterly financials
flag: Whenapprox
, the API returns the closest available quarter if an exact match forapprox=true
is not found.report_date -
Company report sections param: Only appended to the URL when not
. If you want all sections, omit the"all"
parameter entirely.sections
Available IDX indices
ftse, idx30, idxbumn20, idxesgl, idxg30, idxhidiv20, idxq30, idxv30, jii70, kompas100, lq45, sminfra18, srikehati, economic30, idxvesta28
Top companies classifications
IDX (
/companies/top/): dividend_yield, total_dividend, revenue, earnings, market_cap, pb, pe, ps
IDX growth (
/companies/top-growth/): top_earnings_growth_gainers, top_earnings_growth_losers, top_revenue_growth_gainers, top_revenue_growth_losers
IDX movers (
/companies/top-changes/): top_gainers, top_losers
SGX (
/sgx/companies/top/): dividend_yield, revenue, earnings, market_cap, pe
Error handling
Always check the response status:
resp = requests.get(url, headers=headers) if resp.status_code == 403: raise ValueError("Invalid or missing API key. Ensure SECTORS_API_KEY is set correctly.") if resp.status_code == 404: raise ValueError(f"Resource not found: {url}") if not resp.ok: raise RuntimeError(f"API error {resp.status_code}: {resp.text}") data = resp.json()