Get sales
What copies actually sold for on Cardmarket, day by day.
Realized sales, not asking prices: the average price copies sold for on each day any changed hands, every language and condition together.
Sparse: a day without a sale has no point. The series begins at our first read of the product page; Cardmarket shows about three months back, and each read since adds the new days.
Path parameters
| Parameter | Type | Description |
|---|---|---|
| cardIdrequired | string | A card id. An id retired by a set re-key keeps working and is reported in meta.movedFrom. |
Query parameters
Any other query parameter is a 400 naming it and listing these, so a misspelt one is never silently ignored. api_key is accepted on every endpoint as an alternative to the header.
| Parameter | Type | Description |
|---|---|---|
| days | integer | How many days back from today, 1 to 1,826. Default: |
Response
200 The sales.
| Field | Type | Description |
|---|---|---|
| data | object | The sales. |
| data.cardId | string | The card's current id. |
| data.source | string | Always cardmarket.One of: |
| data.currency | string | Always EUR.One of: |
| data.sales | object[] | Oldest first. |
| data.sales[].day | string | YYYY-MM-DD. |
| data.sales[].avgSell | number | Average sale price that day, EUR. |
| meta | object | The window. |
| meta.days | integer | The window used. |
| meta.count | integer | Days with a sale. |
| meta.note | string | How to read the series. |
| meta.pricesFrom | string | Present when the card is a localized printing served its English printing's prices. One of: Absent unless it applies. |
| meta.englishId | string | The English printing the prices are from. Present with pricesFrom.Absent unless it applies. |
| meta.movedFrom | string | The id you asked for, when it was retired by a set re-key. Absent unless it applies. |
Examples
Real responses from the production API, recorded on 2026-09-24 by the script that also checks every field above against them. Arrays are shown in full.
Last 30 days
curl "https://api.tcggraph.com/v1/prices/pkm_sv3pt5_6/sales?days=30" \
-H "Authorization: Bearer $TCGGRAPH_API_KEY"const response = await fetch("https://api.tcggraph.com/v1/prices/pkm_sv3pt5_6/sales?days=30", {
headers: {
Authorization: `Bearer ${process.env.TCGGRAPH_API_KEY}`,
},
});
const body = await response.json();
if (!response.ok) throw new Error(`${body.error.code}: ${body.error.message}`);import os
import requests
response = requests.get(
"https://api.tcggraph.com/v1/prices/pkm_sv3pt5_6/sales",
params={
"days": "30",
},
headers={"Authorization": f"Bearer {os.environ['TCGGRAPH_API_KEY']}"},
)
body = response.json()
response.raise_for_status(){
"data": {
"cardId": "pkm_sv3pt5_6",
"source": "cardmarket",
"currency": "EUR",
"sales": [
{
"day": "2026-08-25",
"avgSell": 8.31
},
{
"day": "2026-08-26",
"avgSell": 9.62
},
{
"day": "2026-08-27",
"avgSell": 8.82
},
{
"day": "2026-08-28",
"avgSell": 8.01
},
{
"day": "2026-08-29",
"avgSell": 9.5
},
{
"day": "2026-08-30",
"avgSell": 8.4
},
{
"day": "2026-08-31",
"avgSell": 8.18
},
{
"day": "2026-09-01",
"avgSell": 8.59
},
{
"day": "2026-09-02",
"avgSell": 8.5
},
{
"day": "2026-09-03",
"avgSell": 8.98
},
{
"day": "2026-09-04",
"avgSell": 8.88
},
{
"day": "2026-09-05",
"avgSell": 8.08
},
{
"day": "2026-09-06",
"avgSell": 8.24
},
{
"day": "2026-09-07",
"avgSell": 9.31
},
{
"day": "2026-09-08",
"avgSell": 6.99
},
{
"day": "2026-09-09",
"avgSell": 8.16
},
{
"day": "2026-09-10",
"avgSell": 8.67
},
{
"day": "2026-09-11",
"avgSell": 8.29
},
{
"day": "2026-09-12",
"avgSell": 7.49
},
{
"day": "2026-09-13",
"avgSell": 8.95
},
{
"day": "2026-09-14",
"avgSell": 8.07
},
{
"day": "2026-09-15",
"avgSell": 8.25
},
{
"day": "2026-09-16",
"avgSell": 8.63
},
{
"day": "2026-09-17",
"avgSell": 12.17
},
{
"day": "2026-09-18",
"avgSell": 7.03
},
{
"day": "2026-09-19",
"avgSell": 7.69
},
{
"day": "2026-09-20",
"avgSell": 8.86
},
{
"day": "2026-09-21",
"avgSell": 9.78
},
{
"day": "2026-09-22",
"avgSell": 8.46
},
{
"day": "2026-09-23",
"avgSell": 9.54
}
]
},
"meta": {
"days": 30,
"count": 30,
"note": "One point per day copies sold; days without a sale are absent. Every language and condition together."
}
}Errors
Every error has the same body; switch on error.code. Any endpoint can also answer 401, 402, 403 or 429 for reasons of key, plan or rate; those are on Errors.
| Status | Code | When |
|---|---|---|
| 400 | invalid_request | days outside 1 to 1,826 or not a whole number, or a parameter this endpoint does not take. |
| 404 | not_found | No card has that id. |
Too many days
curl "https://api.tcggraph.com/v1/prices/pkm_sv3pt5_6/sales?days=5000" \
-H "Authorization: Bearer $TCGGRAPH_API_KEY"const response = await fetch("https://api.tcggraph.com/v1/prices/pkm_sv3pt5_6/sales?days=5000", {
headers: {
Authorization: `Bearer ${process.env.TCGGRAPH_API_KEY}`,
},
});
const body = await response.json();
if (!response.ok) throw new Error(`${body.error.code}: ${body.error.message}`);import os
import requests
response = requests.get(
"https://api.tcggraph.com/v1/prices/pkm_sv3pt5_6/sales",
params={
"days": "5000",
},
headers={"Authorization": f"Bearer {os.environ['TCGGRAPH_API_KEY']}"},
)
body = response.json()
response.raise_for_status(){
"error": {
"code": "invalid_request",
"message": "`days` must be a whole number from 1 to 1826.",
"details": {
"field": "days",
"got": "5000"
}
}
}