curl --request GET \
--url https://data-api.compute-index.com/v2/llm/token/prices/history \
--header 'Authorization: Bearer <token>'import requests
url = "https://data-api.compute-index.com/v2/llm/token/prices/history"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://data-api.compute-index.com/v2/llm/token/prices/history', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://data-api.compute-index.com/v2/llm/token/prices/history",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://data-api.compute-index.com/v2/llm/token/prices/history"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://data-api.compute-index.com/v2/llm/token/prices/history")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://data-api.compute-index.com/v2/llm/token/prices/history")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"data": [
{
"canonical_model_id": "anthropic/claude-opus-4-8",
"lab": "anthropic",
"modality": "text",
"is_open_weight": true,
"context_length": 200000,
"tokenizer": "<string>",
"metric": "output_text_token",
"price_type": "list",
"source": "litellm",
"source_model_id": "<string>",
"provider": "<string>",
"region": "global",
"qualifiers": {},
"price_per_mtok": 75,
"raw_price": 123,
"raw_price_unit": "USD/token",
"is_price_outlier": true,
"valid_from": "<string>",
"valid_to": "<string>",
"extracted_at": "<string>",
"base_product_key": "<string>",
"product_key": "<string>"
}
],
"meta": {
"page_size": 100,
"returned": 100,
"has_more": true,
"next": {
"path": "/v2/gpu/rental/prices/history",
"query_params": {
"page_size": "100",
"page_token": "eyJkIjoicHJpY2VzIiwiZSI6Imhpc3RvcnkiLC4uLg.qgLm5w"
},
"url": "https://data-api.compute-index.com/v2/gpu/rental/prices/history?page_token=eyJkIjoicHJpY2VzIiwiZSI6Imhpc3RvcnksLi4u.qgLm5w&page_size=100"
},
"sort": {
"by": "valid_from",
"order": "desc"
},
"window": {
"start": "2026-06-01T00:00:00+00:00",
"end": "2026-07-01T00:00:00+00:00",
"clamped": true,
"history_starts_at": "<string>"
}
}
}{
"status": 401,
"title": "Unauthorized",
"detail": "Missing or invalid bearer token.",
"code": "unauthenticated",
"request_id": "01JQ2X8N4T6V9WZ0ABCD"
}{
"status": 403,
"title": "Forbidden",
"detail": "The token does not carry the scopes this endpoint requires.",
"code": "insufficient_entitlement",
"request_id": "01JQ2X8N4T6V9WZ0ABCD"
}{
"status": 404,
"title": "Not Found",
"detail": "No such resource, or none you are entitled to see.",
"code": "not_found",
"request_id": "01JQ2X8N4T6V9WZ0ABCD"
}{
"status": 422,
"title": "Unprocessable Content",
"detail": "A parameter failed validation.",
"code": "validation_failed",
"request_id": "01JQ2X8N4T6V9WZ0ABCD"
}{
"status": 429,
"title": "Too Many Requests",
"detail": "Rate limit exceeded; see the X-RateLimit-* headers.",
"code": "rate_limited",
"request_id": "01JQ2X8N4T6V9WZ0ABCD"
}Token Prices: History
LLM inference prices per model, in USD per 1M tokens.
Returns the records that changed inside the range, so asking for yesterday gives you yesterday’s changes rather than everything still in force.
start is included and end is not, so consecutive ranges join up without returning anything twice. A plain date for end means the end of that day, so start=2026-06-01&end=2026-06-01 is that whole day.
Omitting start gives you the most recent 90 days.
curl --request GET \
--url https://data-api.compute-index.com/v2/llm/token/prices/history \
--header 'Authorization: Bearer <token>'import requests
url = "https://data-api.compute-index.com/v2/llm/token/prices/history"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://data-api.compute-index.com/v2/llm/token/prices/history', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://data-api.compute-index.com/v2/llm/token/prices/history",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://data-api.compute-index.com/v2/llm/token/prices/history"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://data-api.compute-index.com/v2/llm/token/prices/history")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://data-api.compute-index.com/v2/llm/token/prices/history")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"data": [
{
"canonical_model_id": "anthropic/claude-opus-4-8",
"lab": "anthropic",
"modality": "text",
"is_open_weight": true,
"context_length": 200000,
"tokenizer": "<string>",
"metric": "output_text_token",
"price_type": "list",
"source": "litellm",
"source_model_id": "<string>",
"provider": "<string>",
"region": "global",
"qualifiers": {},
"price_per_mtok": 75,
"raw_price": 123,
"raw_price_unit": "USD/token",
"is_price_outlier": true,
"valid_from": "<string>",
"valid_to": "<string>",
"extracted_at": "<string>",
"base_product_key": "<string>",
"product_key": "<string>"
}
],
"meta": {
"page_size": 100,
"returned": 100,
"has_more": true,
"next": {
"path": "/v2/gpu/rental/prices/history",
"query_params": {
"page_size": "100",
"page_token": "eyJkIjoicHJpY2VzIiwiZSI6Imhpc3RvcnkiLC4uLg.qgLm5w"
},
"url": "https://data-api.compute-index.com/v2/gpu/rental/prices/history?page_token=eyJkIjoicHJpY2VzIiwiZSI6Imhpc3RvcnksLi4u.qgLm5w&page_size=100"
},
"sort": {
"by": "valid_from",
"order": "desc"
},
"window": {
"start": "2026-06-01T00:00:00+00:00",
"end": "2026-07-01T00:00:00+00:00",
"clamped": true,
"history_starts_at": "<string>"
}
}
}{
"status": 401,
"title": "Unauthorized",
"detail": "Missing or invalid bearer token.",
"code": "unauthenticated",
"request_id": "01JQ2X8N4T6V9WZ0ABCD"
}{
"status": 403,
"title": "Forbidden",
"detail": "The token does not carry the scopes this endpoint requires.",
"code": "insufficient_entitlement",
"request_id": "01JQ2X8N4T6V9WZ0ABCD"
}{
"status": 404,
"title": "Not Found",
"detail": "No such resource, or none you are entitled to see.",
"code": "not_found",
"request_id": "01JQ2X8N4T6V9WZ0ABCD"
}{
"status": 422,
"title": "Unprocessable Content",
"detail": "A parameter failed validation.",
"code": "validation_failed",
"request_id": "01JQ2X8N4T6V9WZ0ABCD"
}{
"status": 429,
"title": "Too Many Requests",
"detail": "Rate limit exceeded; see the X-RateLimit-* headers.",
"code": "rate_limited",
"request_id": "01JQ2X8N4T6V9WZ0ABCD"
}/metadata as
history_starts_at.meta.next until it is null, and send nothing alongside it — the
link already carries your filters, dates and ordering. See
Paging.Example
curl -H "Authorization: Bearer $TOKEN" \
"https://data-api.compute-index.com/v2/llm/token/prices/history?start=2026-06-01&end=2026-07-01&canonical_model_id=anthropic/claude-opus-4-8"
Authorizations
Bearer authentication header of the form Bearer <token>, where <token> is your auth token.
Query Parameters
Window start, inclusive (ISO 8601 datetime, or a bare date = start of that day UTC). Default: end minus 90 days.
Window end, exclusive (ISO 8601 datetime, or a bare date = that whole day, i.e. the bound becomes the following midnight UTC). Default: now. Consecutive windows tile with no overlap: start=2026-06-01&end=2026-06-07 then start=2026-06-08&end=2026-06-14.
Canonical model id, exact match — <lab>/<family> as resolved from the model catalog. Comma-separated list accepted (max 20). Values are listed by this data type's /metadata.
"anthropic/claude-opus-4-8"
Identity hash: every observation of one priced thing over time, across price changes. Obtain it from a previous response — it is the natural anchor for history drill-down.
Snapshot identity hash: one exact observation (identity + time + price).
Model creator, exact match (lower-case). Comma-separated list accepted (max 20). A refinement, not an anchor: pair it with a model id, or list models from /metadata.
"anthropic"
What is priced, exact match. Comma-separated list accepted (max 20). Example: input_text_token,output_text_token
"output_text_token"
Aggregator the price was read from, exact match. Comma-separated list accepted. One of openrouter, litellm, models_dev, artificial_analysis.
Kind of price, exact match: list (a provider's published catalogue), marketplace (a marketplace's own rate), measured (observed by a third-party evaluator). Comma-separated list accepted.
Serving host, exact match (lower-case). Comma-separated list accepted. Null on rows from a marketplace or a measurement rather than a named host.
Model modality, exact match. Comma-separated list accepted. Example: text,multimodal
Only rows priced at >= this many USD/1M tokens (inclusive).
x >= 0Only rows priced at <= this many USD/1M tokens (inclusive).
x >= 0Drop rows flagged is_price_outlier (>20x the cross-source median for the same model, metric and unit — in practice a source unit error). Default false: the data is served as recorded, with the flag on every row.
Sort field. One of: canonical_model_id, metric, price_per_mtok, source, valid_from. Default: valid_from.
Sort direction: asc or desc. Default: desc.
Rows per page (max 1000).
1 <= x <= 1000Opaque token token from a previous response's meta.next. It carries the whole request — filters, ordering, window and position — so supply it alone; the only parameter that may accompany it is page_size. Do not construct or parse these; the format is not part of the contract.