Recent sales
GET /v1/products/{productId}/sales returns a product's sales on the CardNexus marketplace completed in the last 30 days, as a cursor-paginated list. The 30-day window is fixed — there are no date parameters.
curl "https://public-api.cardnexus.com/v1/products/50212/sales?condition=NM&limit=50" \
-H "Authorization: Bearer cnk_live_4f2d8c91e5b34a7f9e6c2d1a8b5f7e3c"
{
"data": [
{
"soldAt": "2026-06-08T19:21:44.000Z",
"region": "na",
"price": { "amount": 46.00, "currency": "USD" },
"priceEur": { "amount": 42.30, "currency": "EUR" },
"quantity": 1,
"finish": "Standard",
"condition": "NM",
"language": "en",
"graded": null
},
{
"soldAt": "2026-06-05T08:02:13.000Z",
"region": "eu",
"price": { "amount": 86.00, "currency": "EUR" },
"priceEur": { "amount": 86.00, "currency": "EUR" },
"quantity": 1,
"finish": "Foil",
"condition": null,
"language": "en",
"graded": {
"grade": "9.5",
"gradingService": "PSA",
"certification": "0084712663"
}
}
],
"pagination": { "nextCursor": "MjAyNi0wNi0wNVQwOToxMTowMi4wMDBafDY4NDhh" }
}
What a sale carries
| Field | Type | Description |
|---|---|---|
soldAt |
string | When the order was placed, ISO 8601. |
region |
string | The seller's market region: eu or na. |
price |
object | The per-card price the card was listed at, in the listing's own currency — the price as the seller quoted it. amount is decimal major units. |
priceEur |
object | The same per-card price converted to EUR at the exchange rate of the sale date. Equal to price for EUR listings. |
quantity |
number | How many copies the sale included. |
finish |
string | The card's finish, e.g. Standard, Foil. |
condition |
string? | NM, LP, MP, HP, or DMG. null when the card is graded. |
language |
string | The card's language as a two-letter code, e.g. en, de. |
graded |
object? | grade, gradingService, and certification when the card is graded. null for raw cards. |
Sales carry the market region but no buyer, seller, or order identifiers.
Ordering and pagination
The list is ordered by when the sale completed, newest first. soldAt is when the order was placed — an order completes some days after it's placed, so soldAt can be slightly out of order within a page.
Walk the list by following pagination.nextCursor: pass it back as cursor until it comes back null. limit defaults to 50, maximum 100. A page can hold slightly more entries than limit when one order contained several matching cards.
Filters
Narrow the result with finish, condition, and language — the same vocabulary the current prices breakdowns use. Filters combine with AND.
Rate limit
Requests count against the product-sales limit: 60 requests per hour.
Related
- Current prices — live asking prices and availability
- Price history — daily Cardmarket and TCGplayer prices
- Pagination — how cursors work