limit on Massive's aggregates endpoint is a scan budget, not a page size, and that is why a request for 1-hour bars with limit=50 comes back with one bar rather than fifty. The unit being counted is the base unit of the request, which is one minute for anything minute-based no matter what multiplier and timespan you asked for.
Applies to
- Plans: every plan. The cap is not a tier limit.
- Endpoints: /v2/aggs/ticker/{ticker}/range/{multiplier}/{timespan}/{from}/{to}.
- Asset classes: stocks, options, indices, forex and crypto.
How to see the difference
Two fields in the response tell you what happened. queryCount is how many base units were scanned and resultsCount is how many bars came back:
curl -X GET "https://api.massive.com/v2/aggs/ticker/AAPL/range/1/hour/2026-09-04/2026-09-04?limit=50&apiKey=YOUR_API_KEY"
Response
{ "ticker": "AAPL", "queryCount": 50, "resultsCount": 1, "adjusted": true, "status": "OK" }
Fifty minutes of scanning covers part of one hour, so one bar is all there was to return. Raise the limit and the same range yields the full session:
curl -X GET "https://api.massive.com/v2/aggs/ticker/AAPL/range/1/hour/2026-09-03/2026-09-05?limit=5000&apiKey=YOUR_API_KEY"
Response
{ "ticker": "AAPL", "queryCount": 1677, "resultsCount": 32, "status": "OK" }
How to size the limit
Work out the base units your range contains, then set the limit at or above it:
| You asked for | Base units in one trading day |
|---|---|
| Any minute-based bar, whatever the multiplier | About 960, the minutes from 04:00 to 20:00 Eastern |
| Any hour-based bar | The same 960, because hours are rolled up from minutes |
| Daily bars | 1 |
So one day of any minute-based request needs a limit near 1,000, and a month needs about 20,000. Beyond that, the 50,000 ceiling is roughly two and a half months of minutes, which is why we recommend keeping minute and hour requests to a month per call and paging with next_url rather than raising the limit.
Why a short limit fails silently
A short limit fails silently because a window that was not fully scanned produces no bar rather than a partial one, and the response is still "status": "OK". The clearest case is a large multiplier: a request for 330-minute bars with limit=20 scans 20 minutes, never completes a 330-minute window, and returns an empty results array with no error. Raise the limit to 330 and one bar appears.
That is why queryCount is worth logging. If resultsCount is smaller than the number of bars you expected and queryCount equals your limit, the limit is the cause.
If you see an error
An empty results array with HTTP 200 on a range you know has trading is usually the limit. Compare queryCount with your limit: if they match, you were cut off.
Bars missing from the middle or end of a long range is the same cause. Page with next_url instead of raising the limit past 50,000, which does nothing.
Gaps of single minutes are not this. Minutes with no eligible trade produce no bar at all, and that is normal even on a busy ticker.

