Skip to main content
Everything on this page is true of every data type.

The four endpoints

Current values, one row per thing. This is the endpoint for “what is the price today”.
The same shape as /latest, rewound to a date you choose. at takes a date or a full timestamp; a plain date means the end of that day, so at=2026-06-01 gives you the position at the close of 1 June.If nothing was published on that exact date — a weekend, a holiday, a gap in a vendor’s feed — you get the most recent value before it, rather than an empty response.
Everything that changed between two dates. See How history works below, which is the one behaviour worth reading properly if you are coming from v1.If you leave start out, you get a sensible recent window for that data type — 30 days for rental prices and indices, and 90 days for everything else. Each /history endpoint states its own default.
The values that data type accepts as filters, what it covers, and how far back you can read (history_starts_at). It is quick, and it is the right first call for any type — it tells you what a query will accept before you write one.
Aggregated Transactions has only /history and /metadata. A settled deal is an event that happened on a date, so there is no “current value” to ask for. The other two endpoints return 404 on that type.

What a response looks like

Every response that returns rows has the same two parts:
data is what you asked for. meta describes the request it answers — the sort that was applied, the date range that was used, and whether there is more to fetch. If you sent no sort parameters, meta.sort tells you which order you got rather than leaving you to guess. Fields with no value come back as null rather than being left out, so a key you expect is always there. null means not published — which is not the same as zero.

Paging

Responses come back a page at a time. To get the next page, call what the response gives you. meta.next gives you that call in two forms. Both describe the same request, so pick whichever fits your HTTP client:
path is not a third option on its own. The page_token lives in query_params, and the token is what carries your filters, window, ordering and your position in the walk. Call path by itself and you get the first page back again — unfiltered, and on every iteration, so a paging loop never terminates. On a data type that requires an anchor filter you get a 400 instead.Always send path and query_params together.
Mid-walk, meta.next looks like this:
Both loops below walk the same result set:
When meta.next is null you have everything. meta.has_more says the same thing as a boolean.
Send nothing alongside the next link except page_size. It already carries your filters, dates and sort order, so adding a parameter returns an error rather than being quietly ignored. To change a filter, start again without it.
page_size defaults to 100 and goes up to 1000. There is no page number and no total count — has_more answers the question a paging loop actually asks.

Date ranges

start is included and end is not. Consecutive ranges therefore join up without overlapping, so you can pull a year of data month by month and never see the same row twice. Plain dates behave as you would expect: ?start=2026-06-01&end=2026-06-01 is that whole day. All times are UTC.

How history works

/history returns records that changed inside your date range.
This is the one thing that behaves differently from v1. v1’s /history returned everything still in force during the window, so a price set months ago and never changed came back every time. In v2 it does not — you get the changes.
Which endpoint you want depends on the question:
  • Charting a series over time, or syncing changes since you last looked? /history.
  • What was the price on a particular day? /as-of — that is exactly what it answers.

Consistent names

The same thing is spelled the same way on every data type, so once you have learned a name you know it everywhere. Where a concept genuinely differs, so does the name — hardware listings take country, not region, because a country is not a cloud region. Each type sorts on its own set of fields, always with a sensible default, and the order applied is always reported back in meta.sort. Filters that take a list accept up to 20 values.