SPB Git forge

spb/hfmarketdata

Public

Open high-frequency market data platform — FirstRate full-history downloader, DuckDB/Parquet lake, open REST API and React docs platform (www.hfmarketdata.io)

127commits 1branches 0releases
24.7 MBsize
maindefault branch
11 days agolast push
JavaScript 53.7% Python 38.3% CSS 4.6% TypeScript 3.1%

mcp: formulation « plateforme 100 % gratuite » (MCP, skills, page Integrations)

- plus aucune notion de tiers/tarif : « free API key (free account) », « keyless mode has low hourly limits », « higher limits granted on request by e-mail to contact@spboucher.ai (also free) », lien /limits
- ressource hfmarketdata://limits renommée (LIMITS, everything_is_free), instructions serveur et message 429 alignés
- tarball et zip skills régénérés ; 45 tests vitest verts, build web vert, e2e Integrations 25/25

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Simon-Pierre Boucher committed 20 days ago (Sep 4, 2026) parent 09b9bf0

17 changed files +43 −33

modified hfmarketdata/web/public/downloads/hfmarketdata-mcp-1.0.0.tgz +0 −0

Binary file not shown.

modified hfmarketdata/web/public/downloads/hfmarketdata-skills.zip +0 −0

Binary file not shown.

modified hfmarketdata/web/src/pages/integrations/Integrations.jsx +5 −5
@@ -96,7 +96,7 @@ function InstallControls({ showKey = true }) {
96 96 <div className="int-field">
97 97 <label htmlFor="int-key">API key (optional)</label>
98 98 <input id="int-key" value={key} onChange={(e) => setKey(e.target.value.trim())} placeholder={KEY_PLACEHOLDER} autoComplete="off" spellCheck="false" />
99 − <span className="hint">Stays in this tab — only used to fill the snippets. No key = keyless mode (30 req/h).</span>
99 + <span className="hint">Stays in this tab — only used to fill the snippets. No key = keyless mode (low hourly limits); the key is free.</span>
100 100 </div>
101 101 )}
102 102 {mode === 'npm' && <div className="int-callout warn">The npm package is being published; until it resolves on the registry, use the tarball tab (same binary, same version {MCP_VERSION}).</div>}
@@ -158,7 +158,7 @@ function Hero() {
158 158 <span className="int-badge">14 tools · 2 resources · 3 prompts</span>
159 159 <span className="int-badge">Node ≥ 20 · zero heavy deps</span>
160 160 <span className="int-badge">MIT</span>
161 − <span className="int-badge">Keyless works · free key = 120 req/min</span>
161 + <span className="int-badge">100 % free · keyless works · free API key = 120 req/min</span>
162 162 </div>
163 163 </div>
164 164 <DemoTerminal />
@@ -209,7 +209,7 @@ function Overview() {
209 209 <h2>How it behaves</h2>
210 210 <ul>
211 211 <li><strong>Bounded outputs.</strong> Compact <code>{'{columns, rows}'}</code> tables; above 200 rows the tool returns count, first/last rows, numeric ranges and a hint to narrow — an agent cannot flood its context by accident.</li>
212 − <li><strong>Quota-aware.</strong> Every result ends with the remaining requests/rows from <code>X-RateLimit-*</code>; a 429 explains <code>Retry-After</code> and how to get a key.</li>
212 + <li><strong>Quota-aware.</strong> Every result ends with the remaining requests/rows from <code>X-RateLimit-*</code>; a 429 explains <code>Retry-After</code> and how to get a free API key (see <Link to="/limits">/limits</Link>).</li>
213 213 <li><strong>Honest data.</strong> Missing values stay <code>null</code>; coverage and gaps are first-class (<code>get_coverage</code>). Intraday timestamps are US/Eastern, daily bars are dates.</li>
214 214 <li><strong>Read-only.</strong> No tool writes anything. The API key is read from <code>HFMD_API_KEY</code> and never logged or echoed.</li>
215 215 </ul>
@@ -239,7 +239,7 @@ function McpPage() {
239 239 <div className="int-table"><table>
240 240 <thead><tr><th>Variable</th><th>Default</th><th>Purpose</th></tr></thead>
241 241 <tbody>
242 − <tr><td><code>HFMD_API_KEY</code></td><td><em>(unset = keyless)</em></td><td>Bearer key from your <Link to="/dashboard">dashboard</Link>. Keyless: 30 requests/hour per IP, 5 000 rows/request. Free account: 120 req/min, 50 000 rows/request.</td></tr>
242 + <tr><td><code>HFMD_API_KEY</code></td><td><em>(unset = keyless)</em></td><td>Free API key from your <Link to="/dashboard">dashboard</Link> (free account). Keyless mode has low hourly limits (30 requests/hour per IP, 5 000 rows/request); a free key gives 120 req/min and 50 000 rows/request; higher limits are granted on request by e-mail to <a href={`mailto:${CONTACT_EMAIL}`}>{CONTACT_EMAIL}</a> (also free). See <Link to="/limits">/limits</Link>.</td></tr>
243 243 <tr><td><code>HFMD_BASE_URL</code></td><td><code>{PUBLIC_BASE}</code></td><td>Point the server at a staging or self-hosted API. The websocket URL is derived (<code>wss://…/v1/stream</code>).</td></tr>
244 244 </tbody>
245 245 </table></div>
@@ -251,7 +251,7 @@ function McpPage() {
251 251 <thead><tr><th>Tool</th><th>What it does</th><th>Endpoint(s)</th></tr></thead>
252 252 <tbody>{TOOLS.map(([n, d, e]) => <tr key={n}><td><code>{n}</code></td><td>{d}</td><td className="mono muted" style={{ fontSize: 12 }}>{e}</td></tr>)}</tbody>
253 253 </table></div>
254 − <p><strong>Resources:</strong> <code>hfmarketdata://status</code> (dataset inventory) · <code>hfmarketdata://limits</code> (tiers + live headroom). <strong>Prompts:</strong> <code>term-structure-analysis</code>, <code>compare-contracts</code>, <code>fundamentals-snapshot</code>.</p>
254 + <p><strong>Resources:</strong> <code>hfmarketdata://status</code> (dataset inventory) · <code>hfmarketdata://limits</code> (rate limits + live headroom — everything is free). <strong>Prompts:</strong> <code>term-structure-analysis</code>, <code>compare-contracts</code>, <code>fundamentals-snapshot</code>.</p>
255 255 <div className="int-callout">The futures v2 and fundamentals endpoints roll out progressively on the API. Until an endpoint is live, the corresponding tool returns a clear <code>404 NOT_FOUND</code> message pointing to <code>hfmarketdata://status</code> — nothing is fabricated.</div>
256 256 </section>
257 257
modified mcp/README.md +3 −3
@@ -40,7 +40,7 @@ Then just ask:
40 40
41 41 > *"Plot me the CL term structure"* · *"Compare ESZ25 and ESH26 over 30 days"* · *"Screen US stocks with PE<15 and FCF yield>6% and show their last 3 quarters"*
42 42
43 −A free account (`https://www.hfmarketdata.io/signup`) gives you an API key and **120 requests / minute** instead of 30 / hour. Set it as `HFMD_API_KEY`; the server never logs it.
43 +The platform is entirely free. Keyless mode has low hourly limits (30 requests / hour); a free API key (free account at `https://www.hfmarketdata.io/signup`) gives **120 requests / minute**, and higher limits are granted on request by e-mail to contact@spboucher.ai (also free). Set the key as `HFMD_API_KEY`; the server never logs it. Details: <https://www.hfmarketdata.io/limits>.
44 44
45 45 ## Tools
46 46
@@ -61,7 +61,7 @@ A free account (`https://www.hfmarketdata.io/signup`) gives you an API key and *
61 61 | `get_filings` | 10-K / 10-Q / 8-K / 4 / 13F… with URLs | `/v1/fundamentals/{t}/filings` |
62 62 | `subscribe_filings` | Opens `wss://…/v1/stream`, subscribes to `filings`, returns up to N messages within a bounded time window | websocket |
63 63
64 −**Resources:** `hfmarketdata://status` (live dataset inventory) · `hfmarketdata://limits` (tiers + your headroom).
64 +**Resources:** `hfmarketdata://status` (live dataset inventory) · `hfmarketdata://limits` (rate limits + your headroom).
65 65 **Prompts:** `term-structure-analysis(root, as_of?, compare_to?)` · `compare-contracts(symbol_a, symbol_b, days?)` · `fundamentals-snapshot(ticker, quarters?)`.
66 66
67 67 ### Behaviour every tool shares
@@ -69,7 +69,7 @@ A free account (`https://www.hfmarketdata.io/signup`) gives you an API key and *
69 69 - `HFMD_BASE_URL` (default `https://www.hfmarketdata.io`) and `HFMD_API_KEY` (optional) are the only configuration.
70 70 - `format=json` is always requested; both the v1 envelope `{count,data}` and the v2 envelope `{data,meta}` are understood.
71 71 - Outputs are compact tables `{"columns":[…],"rows":[[…]]}`. The default `limit` is 500 rows (max 5 000); above **200 rows** the tool returns the count, the first/last 15 rows, per-column numeric ranges and a hint to narrow the request — so a careless "all 1-minute bars since 2010" cannot flood the context.
72 −- Rate-limit headroom (`X-RateLimit-Remaining-*`, reset) is appended to every result; a **429** comes back as a clear message with `Retry-After` and the keyless → key upgrade hint.
72 +- Rate-limit headroom (`X-RateLimit-Remaining-*`, reset) is appended to every result; a **429** comes back as a clear message with `Retry-After` and a reminder that a free API key lifts the low keyless limits.
73 73 - Errors are uniform: `HF Market Data error <status> <CODE>: <message> [Docs: …]`, whether the API answered with the v2 `{"error":{code,message,docs}}` envelope or the legacy `{"detail"}`.
74 74 - `subscribe_filings` is bounded by design (`max_messages` ≤ 100, `timeout_seconds` ≤ 120) and closes the socket when it returns; it needs Node ≥ 22 (global `WebSocket`) or Node 20 with `--experimental-websocket`.
75 75 - Read-only: no tool ever writes anything anywhere.
modified mcp/src/client.ts +1 −1
@@ -57,7 +57,7 @@ export class HfmdError extends Error {
57 57 if (this.status === 429) {
58 58 const ra = this.rate?.retryAfter;
59 59 parts.push(ra != null ? `Retry after ${ra}s.` : 'Retry later.');
60 − parts.push('Keyless mode allows 30 requests/hour; set HFMD_API_KEY (free account = 120 req/min) or narrow the query.');
60 + parts.push('Keyless mode has low hourly limits (30 requests/hour); set HFMD_API_KEY (free API key = 120 req/min; higher limits on request to contact@spboucher.ai, also free) or narrow the query.');
61 61 } else if (this.status === 401) {
62 62 parts.push('Check HFMD_API_KEY (format hfmd_live_…) or unset it to use keyless mode.');
63 63 } else if (this.status === 404 && this.code === 'NOT_FOUND') {
modified mcp/src/resources.ts +13 −11
@@ -1,13 +1,14 @@
1 1 /**
2 2 * MCP resources: `hfmarketdata://status` (dataset inventory) and `hfmarketdata://limits`
3 − * (rate-limit tiers + the caller's current headroom when the server exposes /v1/limits).
3 + * (the three access levels — all free — + the caller's current headroom when the server exposes /v1/limits).
4 4 */
5 5 import { HfmdClient, HfmdError } from './client.js';
6 6
7 −export const TIERS = [
8 − { tier: 'keyless (per IP)', window: '1 hour', requests: 30, rows: 100_000, max_rows_per_request: 5_000 },
9 − { tier: 'free (account + API key)', window: '1 minute', requests: 120, rows: 1_000_000, max_rows_per_request: 50_000 },
10 − { tier: 'high_usage (on request: contact@spboucher.ai)', window: '1 minute', requests: 600, rows: 10_000_000, max_rows_per_request: 200_000 },
7 +/** The platform is entirely free; these are rate limits, not a price list. */
8 +export const LIMITS = [
9 + { access: 'keyless (per IP, low hourly limits)', window: '1 hour', requests: 30, rows: 100_000, max_rows_per_request: 5_000 },
10 + { access: 'free API key (free account)', window: '1 minute', requests: 120, rows: 1_000_000, max_rows_per_request: 50_000 },
11 + { access: 'higher limits (granted on request by e-mail to contact@spboucher.ai, also free)', window: '1 minute', requests: 600, rows: 10_000_000, max_rows_per_request: 200_000 },
11 12 ];
12 13
13 14 export interface ResourceDef {
@@ -34,17 +35,18 @@ export const statusResource: ResourceDef = {
34 35 export const limitsResource: ResourceDef = {
35 36 name: 'limits',
36 37 uri: 'hfmarketdata://limits',
37 − title: 'HF Market Data — rate limits & tiers',
38 − description: 'The three tiers (keyless / free / high usage) with their request and row quotas, whether this server runs with an API key, and the live headroom when /v1/limits is available.',
38 + title: 'HF Market Data — rate limits',
39 + description: 'The platform is free. Three access levels (keyless / free API key / higher limits on request) with their request and row quotas, whether this server runs with an API key, and the live headroom when /v1/limits is available.',
39 40 mimeType: 'application/json',
40 41 async read(client) {
41 42 const out: Record<string, unknown> = {
42 − mode: client.keyless ? 'keyless (set HFMD_API_KEY for the free tier: 120 req/min)' : 'api key configured',
43 − tiers: TIERS,
43 + mode: client.keyless ? 'keyless (low hourly limits — set HFMD_API_KEY, a free API key gives 120 req/min)' : 'api key configured',
44 + everything_is_free: true,
45 + limits: LIMITS,
44 46 notes: [
45 − 'Parquet responses count half the rows against the quota; bulk downloads are quota-exempt; 304 responses are free.',
47 + 'Parquet responses count half the rows against the quota; bulk downloads are quota-exempt; 304 responses do not count.',
46 48 'Every response carries X-RateLimit-Limit-Requests / -Remaining-Requests / -Limit-Rows / -Remaining-Rows / -Reset; 429 adds Retry-After.',
47 − 'Create a free account at https://www.hfmarketdata.io/signup — keys look like hfmd_live_….',
49 + 'Create a free account at https://www.hfmarketdata.io/signup — keys look like hfmd_live_…. Higher limits: e-mail contact@spboucher.ai (also free). Details: https://www.hfmarketdata.io/limits',
48 50 ],
49 51 };
50 52 try {
modified mcp/src/server.ts +2 −2
@@ -27,8 +27,8 @@ export function createServer(opts: ServerOptions = {}): { server: McpServer; cli
27 27 'Use search_symbols to resolve symbols, get_bars for prices, the futures tools for contracts/curves/continuous series, and the fundamentals tools for statements, ratios, screens and filings.',
28 28 'Outputs are compact tables ({columns, rows}); results above 200 rows are summarised — narrow the range or lower `limit` to see everything.',
29 29 client.keyless
30 − ? 'Running keyless (30 requests/hour per IP). Set HFMD_API_KEY for 120 requests/minute (free account at https://www.hfmarketdata.io/signup).'
31 − : 'An API key is configured (free tier: 120 requests/minute).',
30 + ? 'Running keyless (low hourly limits: 30 requests/hour per IP). Set HFMD_API_KEY for 120 requests/minute — the API key is free (account at https://www.hfmarketdata.io/signup); higher limits are granted on request by e-mail to contact@spboucher.ai, also free.'
31 + : 'A free API key is configured (120 requests/minute; higher limits on request by e-mail to contact@spboucher.ai, also free).',
32 32 'Intraday timestamps are naive US/Eastern; daily bars are dates. Missing values are null — never invent data.',
33 33 ].join(' '),
34 34 },
modified skills/README.md +3 −2
@@ -25,7 +25,8 @@ unzip -o hfmarketdata-skills.zip -d ~/.claude/skills/
25 25 unzip -o hfmarketdata-skills.zip -d .claude/skills/
26 26
27 27 pip install requests pandas matplotlib # matplotlib only for the charts
28 −export HFMD_API_KEY=hfmd_live_… # optional: free account = 120 req/min (keyless = 30 req/h)
28 +export HFMD_API_KEY=hfmd_live_… # optional: free API key = 120 req/min (keyless mode has low hourly limits)
29 +# Everything is free. Higher limits are granted on request by e-mail to contact@spboucher.ai (also free) — see https://www.hfmarketdata.io/limits
29 30 ```
30 31
31 32 Claude Code lists them under `/skills`; you can also just ask — "backtest a 20/100 MA crossover on SPY since 2015" triggers `hfmd-quick-backtest`.
@@ -56,5 +57,5 @@ The zip is committed so the website can serve it without a build step.
56 57
57 58 - Never invent data: gaps stay `NaN`, and every script prints the row count and the date range it actually received.
58 59 - Intraday timestamps are naive US/Eastern (as delivered by the API); daily bars are dates.
59 −- Respect the quota: keyless is 30 requests/hour — scripts paginate by date only when needed and honour `Retry-After` on 429.
60 +- Respect the quota: keyless mode has low hourly limits (30 requests/hour) — scripts paginate by date only when needed and honour `Retry-After` on 429. A free API key lifts this to 120 req/min.
60 61 - Fundamentals are point-in-time: use `filed_at` (not `period_end`) to decide what was knowable on a given day.
modified skills/_shared/hfmd.py +2 −1
@@ -3,7 +3,8 @@
3 3 Copied verbatim into every skill's `scripts/` folder by `skills/scripts/build_skills.py`
4 4 so each skill stays self-contained. Do not edit the copies — edit `skills/_shared/hfmd.py`.
5 5
6 −Environment: HFMD_API_KEY (optional, free account = 120 req/min; keyless = 30 req/h),
6 +Environment: HFMD_API_KEY (optional; free API key = 120 req/min, keyless mode has low hourly limits = 30 req/h;
7 + higher limits on request by e-mail to contact@spboucher.ai, also free),
7 8 HFMD_BASE_URL (default https://www.hfmarketdata.io).
8 9 """
9 10 from __future__ import annotations
modified skills/hfmd-continuous-futures/scripts/hfmd.py +2 −1
@@ -3,7 +3,8 @@
3 3 Copied verbatim into every skill's `scripts/` folder by `skills/scripts/build_skills.py`
4 4 so each skill stays self-contained. Do not edit the copies — edit `skills/_shared/hfmd.py`.
5 5
6 −Environment: HFMD_API_KEY (optional, free account = 120 req/min; keyless = 30 req/h),
6 +Environment: HFMD_API_KEY (optional; free API key = 120 req/min, keyless mode has low hourly limits = 30 req/h;
7 + higher limits on request by e-mail to contact@spboucher.ai, also free),
7 8 HFMD_BASE_URL (default https://www.hfmarketdata.io).
8 9 """
9 10 from __future__ import annotations
modified skills/hfmd-data-analysis/SKILL.md +1 −1
@@ -52,6 +52,6 @@ python3 scripts/fetch_bars.py --asset stock --ticker AAPL MSFT NVDA --start 2024
52 52
53 53 - Intraday `datetime` is naive **US/Eastern** (exchange time); daily bars are plain dates. Localise before joining with UTC data.
54 54 - Stocks default to split+dividend adjusted prices; say so when quoting historical levels.
55 −- Keyless quota: 30 requests/hour, 5 000 rows/request. Set `HFMD_API_KEY` (free account, 120 req/min, 50 000 rows/request) before pulling intraday history.
55 +- Keyless mode has low hourly limits: 30 requests/hour, 5 000 rows/request. Set `HFMD_API_KEY` (free API key, 120 req/min, 50 000 rows/request) before pulling intraday history; higher limits are granted on request by e-mail to contact@spboucher.ai (also free).
56 56 - `volume` for FX/indices may be 0/absent — do not compute volume statistics on them.
57 57 - Error `TICKER_NOT_FOUND` usually means the symbol exists in another asset class (e.g. `SPY` is `etf`, not `stock`).
modified skills/hfmd-data-analysis/scripts/hfmd.py +2 −1
@@ -3,7 +3,8 @@
3 3 Copied verbatim into every skill's `scripts/` folder by `skills/scripts/build_skills.py`
4 4 so each skill stays self-contained. Do not edit the copies — edit `skills/_shared/hfmd.py`.
5 5
6 −Environment: HFMD_API_KEY (optional, free account = 120 req/min; keyless = 30 req/h),
6 +Environment: HFMD_API_KEY (optional; free API key = 120 req/min, keyless mode has low hourly limits = 30 req/h;
7 + higher limits on request by e-mail to contact@spboucher.ai, also free),
7 8 HFMD_BASE_URL (default https://www.hfmarketdata.io).
8 9 """
9 10 from __future__ import annotations
modified skills/hfmd-fundamentals-screen/scripts/hfmd.py +2 −1
@@ -3,7 +3,8 @@
3 3 Copied verbatim into every skill's `scripts/` folder by `skills/scripts/build_skills.py`
4 4 so each skill stays self-contained. Do not edit the copies — edit `skills/_shared/hfmd.py`.
5 5
6 −Environment: HFMD_API_KEY (optional, free account = 120 req/min; keyless = 30 req/h),
6 +Environment: HFMD_API_KEY (optional; free API key = 120 req/min, keyless mode has low hourly limits = 30 req/h;
7 + higher limits on request by e-mail to contact@spboucher.ai, also free),
7 8 HFMD_BASE_URL (default https://www.hfmarketdata.io).
8 9 """
9 10 from __future__ import annotations
modified skills/hfmd-quick-backtest/SKILL.md +1 −1
@@ -52,5 +52,5 @@ python3 scripts/ma_crossover.py --asset stock --ticker AAPL --fixed 50,200 --sta
52 52
53 53 - For futures use `contin_adj_ratio` (multiplicative back-adjustment): `contin_UNadj` has roll jumps that fake returns; `contin_adj_absolute` can go negative in long histories.
54 54 - Intraday bars are US/Eastern and include only the sessions the vendor covers; annualisation uses bars/year inferred from the median bar spacing — check the printed `periods_per_year`.
55 −- Keyless quota (30 req/h) is enough for daily history; hourly since 2010 needs an API key (`HFMD_API_KEY`).
55 +- Keyless mode (low hourly limits, 30 req/h) is enough for daily history; hourly since 2010 needs a free API key (`HFMD_API_KEY`).
56 56 - A Sharpe above ~1.5 out-of-sample on a plain MA cross is a red flag for a bug or a tiny sample, not a discovery.
modified skills/hfmd-quick-backtest/scripts/hfmd.py +2 −1
@@ -3,7 +3,8 @@
3 3 Copied verbatim into every skill's `scripts/` folder by `skills/scripts/build_skills.py`
4 4 so each skill stays self-contained. Do not edit the copies — edit `skills/_shared/hfmd.py`.
5 5
6 −Environment: HFMD_API_KEY (optional, free account = 120 req/min; keyless = 30 req/h),
6 +Environment: HFMD_API_KEY (optional; free API key = 120 req/min, keyless mode has low hourly limits = 30 req/h;
7 + higher limits on request by e-mail to contact@spboucher.ai, also free),
7 8 HFMD_BASE_URL (default https://www.hfmarketdata.io).
8 9 """
9 10 from __future__ import annotations
modified skills/hfmd-term-structure/scripts/hfmd.py +2 −1
@@ -3,7 +3,8 @@
3 3 Copied verbatim into every skill's `scripts/` folder by `skills/scripts/build_skills.py`
4 4 so each skill stays self-contained. Do not edit the copies — edit `skills/_shared/hfmd.py`.
5 5
6 −Environment: HFMD_API_KEY (optional, free account = 120 req/min; keyless = 30 req/h),
6 +Environment: HFMD_API_KEY (optional; free API key = 120 req/min, keyless mode has low hourly limits = 30 req/h;
7 + higher limits on request by e-mail to contact@spboucher.ai, also free),
7 8 HFMD_BASE_URL (default https://www.hfmarketdata.io).
8 9 """
9 10 from __future__ import annotations
modified skills/scripts/build_skills.py +2 −1
@@ -29,7 +29,8 @@ Unzip into `~/.claude/skills/` (all projects) or `.claude/skills/` (this project
29 29 unzip -o hfmarketdata-skills.zip -d ~/.claude/skills/
30 30
31 31 Requirements: Python 3.10+, `pip install requests pandas` (+ `matplotlib` for charts).
32 −Optional: `export HFMD_API_KEY=hfmd_live_…` (free account → 120 requests/min; keyless → 30/h).
32 +Optional: `export HFMD_API_KEY=hfmd_live_…` (free API key → 120 requests/min; keyless mode has low hourly limits, 30/h).
33 +Everything is free; higher limits are granted on request by e-mail to contact@spboucher.ai (also free). See https://www.hfmarketdata.io/limits
33 34
34 35 Skills: hfmd-data-analysis · hfmd-quick-backtest · hfmd-continuous-futures · hfmd-fundamentals-screen · hfmd-term-structure
35 36 Docs: https://www.hfmarketdata.io/integrations/skills
36 37