Every request is a GET with your key in an x-api-key header, and every response is JSON in the YH envelope shape. Create a free key if you don't have one.
export KEY="sk_live_..." # from your dashboard
curl -H "x-api-key: $KEY" "https://api.stockdataapi.com/v6/finance/quote?symbols=AAPL"Missing or wrong keys get 401 {"message": "Invalid API key"}. A suspended or revoked key gets 403. Keys are stored hashed; if you lose one, revoke it and create another.
Every plan gets every endpoint. Each has its own page with parameters, behaviour, code in curl, JavaScript and Python, and an example response.
Every request — quotes, charts, sparks, options, fundamentals, insights, recommendations, screeners, trending and market summary — checks the stored copy's age. A stale symbol is refetched from the source inline and the fresh data is served in that same response; there is no snapshot-then-poll. If the source can't answer in time, you get the stored copy instead — the call degrades, it never errors. Cache misses report what happened in X-Data-Freshness: live, partial (batch calls where some symbols were still fetching at the deadline) or warehouse.
| Data family | Refreshed when older than |
|---|---|
| Quotes | ~1 minute in market hours, 15 minutes closed |
| Intraday bars | ~2 minutes |
| Daily bars, session in progress | ~1 minute, from the live quote |
| Daily bars, completed sessions | ~1 hour |
| Options chains | ~2 minutes |
| Screeners | ~5 minutes |
| Market summary | ~5 minutes |
| Trending | ~15 minutes |
| Fundamentals & insights | ~1 hour |
| News attached to a search | ~1 hour |
The session in progress is the exception to that hourly cadence. A daily chart serves its last candle from the live quote, so it tracks the market rather than whenever the series was last refetched — open, high, low, close and volume all move with it. That candle is served, never stored: a live price is not a settled close, so the stored history stays the settled record and the candle is rebuilt on each response. Futures reach us delayed about ten minutes at the source; equities, indices and crypto do not. For the few sessions each quarter when a futures quote has moved to the next contract but the daily bars have not, the candle is withheld rather than drawn on the wrong contract.
History fills in the same way, on demand. The first call for a symbol pulls its full available history, and a call reaching further back than what is already stored widens it before answering. A narrower window widens the stored series too, behind the response rather than in it, so the depth is already there for whoever asks for more next.
Responses also cache briefly (seconds for quotes) and support ETag/If-None-Match — polling with the ETag answers 304 with headers only. Options chains additionally accept refresh=1, which skips every staleness check and asks the source at call time (budgeted per key — over the budget it quietly serves the normal path). Search works on a rule of its own: it asks the source when we hold fewer matches for your query than you asked for, at most once an hour per query. A ticker we have never seen answers on the first call instead of coming back empty, a query we only partly covered fills in the rest, and both stay answerable from then on — for every other endpoint too. Purely historical windows never refetch: settled data is final.
Paste a key and send a real request from your browser. The key goes straight to the API — it is never sent to this site and never stored.
All keys issued to your account share one allowance, enforced per UTC minute and per UTC day (and per month on plans that set a monthly cap). Adding or rotating a key does not reset or multiply it; legacy keys issued without an account meter independently until migrated. Every authenticated response reports where you stand, and your dashboard shows the same counters live:
| Header | Meaning |
|---|---|
| X-RateLimit-Limit | Your plan's daily request allowance |
| X-RateLimit-Remaining | Requests left today |
| X-RateLimit-Reset | Unix time the daily window resets (00:00 UTC) |
| X-RateLimit-Remaining-Minute | Requests left in the current minute |
| X-RateLimit-Remaining-Month | Requests left this month, on capped plans |
| X-Cache | HIT or MISS — whether the payload came from cache |
| Retry-After | On 429 only: seconds to wait |
Data endpoints keep YH's error semantics: an unknown symbol on /v8/finance/chart is a 404 with a chart.error envelope, while /v6/finance/quote returns 200 with the symbol simply missing from result. 429 means a rate limit — honor Retry-After. Freshness for every data family is reported by GET /status (send your x-api-key).
On /v8/finance/chart and /v11/finance/quoteSummary, every 400 and 404 is that endpoint's envelope — {"chart": {"result": null, "error": {"code": "Bad Request", "description": "…"}}}. Every other error, on every endpoint, is {"message": "…"}.
Ready to make a real call?
Create your free key