ISTERAPI
Contents

Ister /v1#

Composite regional GPU price indices: each series' official print, once a day at its index's close, in the index's hub (Europe's: 16:30 Europe/London; see Indices). REST and JSON, every route also as CSV. Machine-readable: /v1/openapi.json (OpenAPI 3.1). A key comes from the sign-up page; AI assistants read the same routes through the MCP server.

Quick start#

With a key in ISTER_KEY, one call gives the latest print of every series your tier reads:

curl -H "Authorization: Bearer $ISTER_KEY" "https://api.isterindex.com/v1/series"

The answer is JSON: data, the series, and meta, your tier and the dates it reads. Add format=csv for CSV.

Keys#

Send your key in the header: Authorization: Bearer ister_live_…. Tools that can't set a header (Google Sheets) may put it in the query string as api_key=; anyone who sees that URL can use the key, so give such a tool a key of its own and revoke it alone if it leaks. A key lasts 365 days. A rotated key keeps working 7 days beside its new one. A revoked key is refused from the next call. A call with no key reads Europe's H100 series only (EU), for the 7 days up to the print before the latest: the day's figure, and every other series and index, are for key holders.

Indices#

One index per region, each with its hub and close. Name one with index=; with none, the answer is Europe's.

CodeIndexCloseCurrencyStatus
EUEurope16:30 Europe/LondonEUR Published
NANorth America16:30 America/New_YorkUSD Dry run: read behind the login, not yet on keys
ASAsia-Pacific16:30 Asia/SingaporeUSD Dry run: read behind the login, not yet on keys

An index's figures reach keys when it leaves its dry run. Planned, not yet calculated: Latin America (SA, hub São Paulo, BRL; its close to be set), the Middle East (ME, hub Dubai, 16:30, AED at the UAE central bank's USD peg) and Africa (AF, 16:30 Africa/Johannesburg, ZAR).

Tiers#

TierRoutesIndicesGPUsHistoryAs first printedCalls
anonymousseries, history, records Europe (EU)H100The 7 days up to the print before the latest No 60 an hour
freeseries, history, records Every published indexH100, B200The latest print and 7 days before it No 120 an hour
paidseries, history, records Every published indexEvery GPUAll of it, from the first print (27 Oct 2026) Yes 1200 an hour

History before your tier's first date is left out of /v1/history, and meta.readable_from says from when; an Index Record named by an earlier date is a 403. A series or index outside your tier is a 403 too; with none named, an answer gives only your tier's series. print_change on /v1/series is worked within your tier's dates as well: a change from further back, and since, are null. Every tier gets the same fields of an Index Record. The index names no provider: no route here gives a provider's name or price.

GET /series#

The latest print of each series, with its changes. Tiers: anonymous, free, paid. Returns a list of Series, with Meta.

ParameterInWhat
indexqueryIndex code (EU, NA, AS…); Europe when none is named; see Indices in /v1/docs. Tiers: anonymous EU; free every published index; paid every published index
gpuqueryGPU model, e.g. H100. Tiers: anonymous H100; free H100, B200; paid every GPU
typequerySeries type: OD, T12 or SP
formatqueryjson (default) or csv
curl -H "Authorization: Bearer $ISTER_KEY" "https://api.isterindex.com/v1/series"

GET /history#

Prints per series and date, oldest first. Tiers: anonymous, free, paid. Returns a list of History, with Meta.

ParameterInWhat
indexqueryIndex code (EU, NA, AS…); Europe when none is named; see Indices in /v1/docs. Tiers: anonymous EU; free every published index; paid every published index
gpuqueryGPU model, e.g. H100. Tiers: anonymous H100; free H100, B200; paid every GPU
typequerySeries type: OD, T12 or SP
fromqueryFirst date, YYYY-MM-DD
toqueryLast date, YYYY-MM-DD
viewquerycurrent (default): as restated; first_printed: each print as it first came out (tiers: paid)
formatqueryjson (default) or csv
curl -H "Authorization: Bearer $ISTER_KEY" "https://api.isterindex.com/v1/history"

GET /records/{date}#

One Index Record: the day's print of every series with its disclosure; latest for the last one. As CSV, one row per series. Tiers: anonymous, free, paid. Returns one Index Record, with Meta.

ParameterInWhat
datepathYYYY-MM-DD or latest
indexqueryIndex code (EU, NA, AS…); Europe when none is named; see Indices in /v1/docs. Tiers: anonymous EU; free every published index; paid every published index
formatqueryjson (default) or csv
curl -H "Authorization: Bearer $ISTER_KEY" "https://api.isterindex.com/v1/records/latest"

Fields#

The fields of each answer. A field not listed here is never sent.

Series#

FieldTypeWhat
codestringSeries code: GPU and type (H100.T12); with an index named, index first (EU.H100.T12)
indexstringIndex code (EU, NA, AS…): see Indices in /v1/docs
gpustringGPU model
typestringSeries type: OD on-demand, T12 12-month term, SP spot
datestring (date)Assessment date
statestringprinted, held or suspended
calcstring or nullmedian or trimmed_average
value_eurnumber or nullValue in EUR per GPU-hour; absent when suspended
value_usdnumber or nullValue in USD per GPU-hour, at the ECB rate of the day
nintegerNumber of providers in the value
hub_currencystring or nullThe currency of the hub whose close the index is based on (GBP for Europe, London); null before it was given
value_hubnumber or nullValue in the hub currency per GPU-hour, at the ECB rate of the day; null with no rate for it
countriesarrayISO 3166 countries the providers deliver from
flagsarrayFlags the method shows publicly (Thin, Interpolated, Held, Suspended, Not updated today, All providers in one country)
input_levelsobjectShare of the value from each input level (2 firm offers, 3 indicative quotes)
vat_not_statedintegerRows whose VAT treatment the provider does not state
form_factor_not_statedintegerRows whose form factor the provider does not state
form_factorsobjectShare of the value from each form factor
last_calculatedstring or null (date)For a held series, the date it was last calculated
switch_noticestring or nullNotice that the calculation changes if the provider count stays
both_valuesobjectNear a change of calculation, the value by each
v02_value_eurnumber or nullThe value under method v0.2, beside it while both were shown
print_changeobjectPercentage change from the print 1 day, 1 week, 3, 6 and 12 months back, and since the history starts; null with no print that far back. A tier that reads part of the history works them within it: null from further back, and since always null

History#

FieldTypeWhat
seriesstringSeries code
indexstringIndex code (EU, NA, AS…): see Indices in /v1/docs
datestring (date)Assessment date
kindstringAlways print for outside callers
statestringprinted, held or suspended
value_eurnumber or nullValue in EUR per GPU-hour; absent when suspended
value_usdnumber or nullValue in USD per GPU-hour, at the ECB rate of the day
hub_currencystring or nullThe currency of the hub whose close the index is based on (GBP for Europe, London); null before it was given
value_hubnumber or nullValue in the hub currency per GPU-hour, at the ECB rate of the day; null with no rate for it
nintegerNumber of providers in the value
flagsarrayFlags the method shows publicly (Thin, Interpolated, Held, Suspended, Not updated today, All providers in one country)

Index Record#

FieldTypeWhat
indexstringIndex code (EU, NA, AS…): see Indices in /v1/docs
assessment_datestring (date)Assessment date
next_assessmentstring or null (date)Next assessment date, under a weekly method
methodology_versionstringMethod version the print was made under
fxobjectECB euro reference rates used, with their date
rulesobjectThe method's publication rules in force
typesobjectSeries types and their names
seriesobject
notestring or nullA note on the print, such as a restatement

Meta#

FieldTypeWhat
audiencestringThe tier the answer is shaped for: anonymous, free or paid
as_ofstring (date)Date the answer is as of
method_versionstringMethod version of the answer
history_startstring (date)First date of the index's history
readable_fromstring (date)First date your tier reads
closeobjectThe index's close: the local time in its hub its prices are as of (EU 16:30 Europe/London; NA 16:30 America/New_York; AS 16:30 Asia/Singapore)
fixing_timestring (date-time)The close on as_of, with its offset from UTC
viewstringcurrent or first_printed
next_cursorstring or nullPass back as cursor for the next page; null at the end

Errors#

RFC 9457 problem details, as application/problem+json: type, title, status, detail, and code, one of:

StatuscodeWhen
400bad_parameterA parameter is unknown or has a bad value
401key_requiredNo key was sent. The answer has WWW-Authenticate: Bearer
401invalid_keyThe key is mistyped, not known, revoked or expired
403not_in_your_accessThe route, date, index or GPU is not in your tier
404not_foundNo such route, or no print on that date
429rate_limitedToo many calls this hour. Retry-After gives the seconds to wait
503unavailableThe data can't be read right now; try again later

As restated, or as first printed#

A print can be restated (method §10). /v1/history gives each date's print as it stands now; view=first_printed gives it as it first came out, which is what a contract settled on that day saw. The tiers table above says which tiers read it; on the others it is a 403.

Caching#

Every answer has an ETag. Send it back as If-None-Match and an unchanged answer is a 304 with no body. Latest figures may be kept 60 seconds, a past print an hour. Answers to a key are private: no shared cache may keep them.

Versions and retirement#

The version is in the path. Within /v1 changes only add: a new route, field or parameter. Anything that would break a caller goes in /v2. Before a route, field or version is retired, its answers carry Deprecation (RFC 9745), the date it was deprecated, and Sunset (RFC 8594), the date it stops, with a Link to the notice, at least 6 months apart.

From your tools#

The same routes from a terminal, Python, Excel or Google Sheets.

curl#

curl -H "Authorization: Bearer $ISTER_KEY" "https://api.isterindex.com/v1/series"

Python#

import io, os, pandas as pd, requests

r = requests.get("https://api.isterindex.com/v1/history", params={"gpu": "H100", "type": "T12", "format": "csv"},
                 headers={"Authorization": f"Bearer {os.environ['ISTER_KEY']}"}, timeout=30)
r.raise_for_status()
history = pd.read_csv(io.StringIO(r.text), parse_dates=["date"])
print(history.tail())

Excel (Power Query)#

Data > Get Data > From Other Sources > Blank Query, then Advanced Editor:

let
    Source = Csv.Document(Web.Contents("https://api.isterindex.com/v1/history", [Query = [format = "csv", gpu = "H100"], ApiKeyName = "api_key"])),
    Table = Table.PromoteHeaders(Source)
in
    Table

When Excel asks for credentials, choose Web API and paste the key. Excel keeps it in its credential store, not in the workbook, and sends it as api_key=.

Google Sheets#

=IMPORTDATA("https://api.isterindex.com/v1/history?format=csv&gpu=H100&api_key=ister_live_…")

Anyone who can see the sheet can see the key: give the sheet its own key.

Terms#

Use of the data is under the terms you accept when you get a key. Quote a number with "Source: Ister".