The contract
How the data behaves
- One set of scores per trading day. They’re published before the market opens, usually by 9:00 a.m. Eastern. Until the new day is out (early in the morning, on a market holiday, or on the rare late day), a call returns the latest published day. If the new day isn’t out by 9:30 a.m. Eastern, use the latest day and check again later.
- Check
date. The top-leveldatetells you which trading day you got. Compare it with today’s date in US Eastern time. - A day’s scores never change. Cache each answer by
(symbol, date)and don’t ask again that day. A repeat call returns the same values. - Batch. Ask for up to 50 symbols in one call instead of one call per symbol. When you split a long list into several calls, pass the first answer’s
dateto the rest, so every batch is the same day. - Some symbols aren’t scored. Funds, ETFs, unknown tickers and other non-equities come back under
not_scoredwith areason, not as an error, and don’t count. A symbol that can’t be a ticker (anything but letters, digits,.and-, up to 10 characters, starting with a letter) fails the whole call withinvalid_input. - Compare within a day. A score is a position among that day’s scored stocks. Don’t compare one day’s score with another day’s.
- Show the notice. When you show a score to a person, show this line with it: “Published score, the same for everyone. Not personal investment advice.” Full entries carry it as
notice.
How the plan counts
- A stock counts once per day, Pacific time (midnight to midnight in Los Angeles), whichever day’s score you get. Asking for it again that day, including after the new scores come out, is free. So checking early in the morning wastes nothing.
- The allowance resets when the plan renews each month.
scores_left_wordsin each answer says, in words, how much is left until then: “plenty left”, “running low” or “none left until your plan renews”. Slow down when it says running low. - There’s also a daily limit. It resets at midnight Pacific time.
- At the limit, the whole call is refused with
limit_reachedand nothing in it counts.resets_atsays when: the next midnight Pacific for the daily limit, or the plan’s renewal for the monthly one (null if not known). Stocks you’ve already seen that day still come back if you ask for only those.
Response schema
Top level:
Each entry (
detail=full):
With
detail=short, an entry has only symbol, name, date, score, band, top_pct and summary. detail defaults to full for 1 to 10 symbols (after duplicates are dropped) and short for more.
date may be any of the last 21 trading days, the latest included. A day with no published scores, such as today before they’re out, a weekend or a holiday, returns invalid_date.
Errors
Every error is{"error": {"type", "message", "request_id", ...}}.
Retry only
rate_limited, model_unavailable and server_error, and honour the Retry-After header. There’s no fixed request rate to stay under; calling one batch at a time is plenty. A response that isn’t JSON (for example a gateway error) is a temporary error: retry it like server_error.