What does "delayed" actually mean on a live quote?
/real-time/{ticker} is the endpoint you reach for when the question is "what is it trading at now". The word in its own OpenAPI summary is "delayed", and understanding why is more useful than any field in the response.
The number, measured
One live call requested four symbols together. The timestamps that came back:
AAPL.US— 1785263280SPY.US— 1785263280EURUSD.FOREX— 1785264180BTC-USD.CC— 1785264180
The two US equities are stamped exactly 900 seconds — fifteen minutes — earlier than the FX and crypto rows in the same response, and the FX and crypto stamps were within seconds of the moment the request was made.
That gap is not latency, congestion, or a slow server. It is a licence.
Why the delay exists
Exchanges own their price data and sell it. Real-time access is a per-user, per-exchange, contractually reported entitlement, priced accordingly. Delayed data — traditionally fifteen or twenty minutes for equities, varying by exchange — is licensed on far cheaper terms, because by the time you see it, it can no longer be traded on.
So the delay is a commercial boundary drawn through the data, and every vendor sits on one side of it or the other for each exchange. /us-quote-delayed states it in the endpoint description: fifteen-minute delayed quotes for US equities.
FX and crypto behave differently because there is no single exchange to license them. Spot FX is over-the-counter, as the foreign-exchange courses explain, and crypto trades on venues with their own rules. The practical result is the one measured above: currency and crypto quotes arrive essentially current, equity quotes arrive a quarter of an hour behind.
Reading the response
A single-symbol call returns one object; adding symbols returns an array. The fields:
code, timestamp, gmtoffset, open, high, low, close, volume, previousClose, change, change_p
Two names actively mislead:
closeis not a close. During a session it is the last traded price. The name is a convenience so the object matches the shape of an EOD row.previousCloseis the genuine article — the prior session's official close — and it is the base for the other two fields.
Check the arithmetic on a real row. Apple came back with close 339.89, previousClose 336.91, change 2.98, change_p 0.8845:
- 339.89 − 336.91 = 2.98, which is exactly what
changereports. - 2.98 ÷ 336.91 = 0.008845, and
change_preports 0.8845.
So change_p is already expressed in percent, not as a fraction. Multiplying it by 100 again is a common and very visible bug.
One more field worth reading honestly: volume for EURUSD.FOREX came back as 0. Not missing, not an error — spot FX has no consolidated volume to report, because there is no central tape. A zero there is information about market structure, not a data gap. The same object, for a currency pair:
What a delayed quote can and cannot support
It can tell you roughly where an instrument is, populate a dashboard, drive an alert with a fifteen-minute tolerance, or fill a "last price" column. It cannot tell you what you would transact at, it cannot be used to time anything inside its own delay window, and it will disagree with a broker's screen — correctly.
And when the market is shut, close simply stops moving. A quote that has not changed for eighteen hours is not broken; the next lesson but two is about telling those two situations apart.
This is where stale-and-missing becomes concrete: the timestamp is the field that tells you whether to believe the price, and it is the one people skip.
Try it now
- A quote is only interesting while the market is open, so this one is printed, not cached:
/real-time/AAPL.US?s=EURUSD.FOREX, called at 14:46:06 UTC on Monday 28 September 2026, trimmed to three fields per row. Subtract the twotimestampvalues. Then subtract each from the moment of the call. You have just measured the licence boundary.
[{"code": "AAPL.US", "timestamp": 1790605800, "close": 340.78},
{"code": "EURUSD.FOREX", "timestamp": 1790606760, "close": 1.135976433754}]
- Verify
changeandchange_pfromcloseandpreviousCloseby hand. If your recomputation disagrees, you have found either a rounding convention or a bug, and both are worth knowing. - Here is the same endpoint for a European symbol while European markets are closed:
/real-time/VOW3.XETRA, refreshed at 04:45 UTC, more than two hours before Xetra opens. Converttimestamp, say which session it belongs to, and whatcloseis a close of. CompareclosewithpreviousCloseand explainchange.