For developers
How to reach TradeAlmanac data programmatically: key, endpoints, response shape.
Updated: 2 September 2026
There are two ways to get the data programmatically, and they do not replace one another. The endpoints the site itself uses are open and need no key — they are described in the interactive documentation. A separate machine contract lives at /api/public/v1 and requires a key: it has a stable format, a predictable response shape and a daily quota.
The key
A key is issued in your account to anyone signed in — no subscription is involved. The secret is shown once, at creation: only its fingerprint is stored, and the string cannot be recovered. Lost it — revoke the key and create another. The terms on which the data may be used are set out in a separate document.
- The key is read-only: any method other than GET is rejected.
- The key opens no operational areas — it carries no permissions at all, rather than being merely unlisted.
- Exceeding a limit answers 429 with a Retry-After header, not with silence.
Plans and limits
There is one plan and it is free. There is no paid tier today — not “coming soon”, but none: quoting a price that has never been set would be collecting sign-ups for something that does not exist.
- Price — Free. A key is issued to anyone signed in.
- Rate — 60 requests per minute per key, sliding window.
- Daily quota — 1000 requests per day per key. The day is a calendar day in UTC.
- Keys per account — up to 10 at a time, revocable at any moment.
- Page size — up to 200 records per request; beyond that, follow the cursor.
- Refusal on a limit — 429 with a Retry-After header carrying the seconds to wait.
The remaining daily quota is visible in your account and can be queried programmatically. The counter the account reads and the counter the refusal is based on are the same one: showing one number while enforcing another would be simpler to build and dishonest to the reader.
Request
curl -H "Authorization: Bearer afk_…" \
"https://tradealmanac.com/api/public/v1/screener?sector=oil-gas÷nd_yield_min=0.08&limit=20"curl -H "Authorization: Bearer afk_…" \
"https://tradealmanac.com/api/public/v1/dividends?from=2026-09-01&to=2026-12-31&limit=50"The key travels in the Authorization header. Yield is given as a fraction, not a percentage: 0.08 means 8 %, the same convention as the screener on the site. Results are paginated: limit is capped at 200 and the next page is taken by the cursor from the response — never by an offset, because a deep offset costs the database everything it skipped.
Response
{
"data": [ … ],
"disclaimer": "…",
"source": "tradealmanac",
"delay_minutes": 15
}One envelope is what makes this a contract rather than a set of unrelated answers: you write one parser. A missing value is absent from the response; it is never substituted with a zero.
What is provided
- afgi and afgi/history — our own sentiment index and its history.
- dividends — the payout calendar, dividends/{ticker} — payouts with their announcement status.
- screener — screening over already computed fundamental metrics.
These are the platform's own calculations. The interface serves no exchange market data: no quotes, no candles and no instrument catalogue — neither for the Russian market nor for global ones. The promise is about the data, not the transport: there is no streaming price feed in the contract either.
Compatibility
curl -H "Authorization: Bearer afk_…" "https://tradealmanac.com/api/public/v1/meta"The /meta endpoint answers, machine-readably, both “what is here” and “what will not appear here”. The contract field is the version of the promise, and it lives separately from the product version: releases are frequent, the promise changes rarely. A breaking change gets a new prefix rather than a quiet edit to /v1.
curl -H "Authorization: Bearer afk_…" "https://tradealmanac.com/api/public/v1/versions"You can pin an edition: send its date in the X-API-Version header and the server answers with the same one. An unknown date is REFUSED with a 400 and the list of known editions rather than silently replaced by the current one: a client that believes it pinned is worse off than one that knows it did not. Pinning promises that an address answering on that date keeps answering; it does not promise to reproduce older behaviour — there are no differences between editions today.
curl "https://tradealmanac.com/api/public/v1/openapi.json"From that description a client is generated rather than transcribed from this page. It carries the machine contract and nothing else — which is not the same as the site's interactive documentation: that one has its own, wider surface. Reading the description needs no key — otherwise you could only choose your tooling after signing up.
Ready-made clients
The Python and TypeScript clients are generated from the same OpenAPI description the contract serves, so they cannot drift from the server. The client version equals the contract date: 2026.9.6 is the client for the contract published on 6 September 2026. Neither has dependencies.
pip install tradealmanac
from tradealmanac import TradeAlmanac
api = TradeAlmanac("afk_…")
print(api.dividends_by_ticker("SBER"))
print(api.screener(sector="oil-gas", dividend_yield_min=0.08, limit=20))npm install tradealmanac
import { TradeAlmanac } from "tradealmanac";
const api = new TradeAlmanac("afk_…");
const dividends = await api.dividendsByTicker("SBER");Webhooks: events come to you
Polling on a schedule is not always necessary. A watchlist rule can post its trigger to your address: in the account you set the address and the body shape — our format, a Telegram bot, a MAX bot, Slack, or a flat row for a spreadsheet. The address must be https and must resolve to the public internet; the body is signed with a key shown to you once.
POST /ваш-адрес HTTP/1.1
Content-Type: application/json; charset=utf-8
X-TradeAlmanac-Event: alert.triggered
X-TradeAlmanac-Delivery: 0f2c…
X-TradeAlmanac-Timestamp: 1788700000
X-TradeAlmanac-Signature: sha256=9f86d081…The signature covers «timestamp.body», not the body alone: an intercepted request cannot be replayed a day later, because the timestamp inside the signature will no longer match. Verify both the signature and the freshness of the timestamp.
import hmac, hashlib, time
def verify(secret: str, body: bytes, signature: str, timestamp: str) -> bool:
if abs(int(time.time()) - int(timestamp)) > 300:
return False # старое сообщение: повтор перехваченного
payload = timestamp.encode() + b"." + body
expected = "sha256=" + hmac.new(secret.encode(), payload, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, signature)Spreadsheets: Google Sheets and Excel
A subscription link serves a screen, a portfolio or a calendar without signing in — by token. That is enough for a spreadsheet to refresh itself, with no code and no marketplace add-on. Links are created in the account, under «Data links».
=IMPORTDATA("https://tradealmanac.com/api/v1/public/feeds/ВАШ_ТОКЕН.csv"; ";")let
Источник = Csv.Document(
Web.Contents("https://tradealmanac.com/api/v1/public/feeds/ВАШ_ТОКЕН.csv"),
[Delimiter=";", Encoding=65001, QuoteStyle=QuoteStyle.Csv]
),
Заголовки = Table.PromoteHeaders(Источник, [PromoteAllScalars=true])
in
ЗаголовкиRefresh frequency is capped per token at sixty requests an hour. Google Sheets refreshes IMPORTDATA roughly once an hour on its own; Excel refreshes on demand or on the schedule you set.
AI agents: the MCP server
The same data is available to agent environments — Claude Desktop, Cursor, Claude Code — through an MCP server. It is a wrapper over this very contract: your key, your quota, no extra load. Installation, ready-made configs and scenarios are on the «Connecting AI agents» page.
pip install tradealmanac-mcp
TRADEALMANAC_API_KEY=afk_… tradealmanac-mcp --checkQuestions about access and requests for higher limits go through contacts.