Price
One price observation: what it is, where it came from, and when it was seen.
Returned inside a card when you ask for include=prices, and as quotes on GET /v1/cards/{id}/prices, GET /v1/prices/current and GET /v1/sealed/{id}/prices. A card typically carries a dozen rows: one per source, variant, printing and grading combination that has a live observation.
Prices are the part of this API with legal weight, so every row states its own provenance. A number without a source, a basis and a date is not a price — it is a rumour.
A source appears only if it is on the redistribution allow-list and the observation is older than that source’s minimum delay. A source absent from the policy table never leaves the database, which is the safe default: adding an importer without adding its policy means the data lands and stays put.
Fields
| Field | Type | Null | Description |
|---|---|---|---|
source | enum | no | TCGPLAYER, CARDMARKET, CARDTRADER, EBAY, PRICECHARTING, COMMUNITY, PTCG_INDEX — the seven on the allow-list today, listed live by GET /v1/prices/sources. The source names where the price formed and who delivered it; provenance on the same row is the printable form. What each covers and how delayed it is: price methodology. |
variant | enum | no | LOW, MARKET, TREND, AVG_1D, AVG_7D, AVG_30D, MEDIAN_GRADED, INDEX. |
basis | enum | no | SOLD (completed sale), ASKING (listing), GUIDE (published guide value), DERIVED (computed by us). Read it before comparing two rows: a Cardmarket or eBay figure is what someone is asking, a PriceCharting figure is built on sales history. Averaging the two mixes offers with transactions. |
amount | number | no | Decimal, in the currency named by the next field. Not converted — the row is served in the currency it was observed in. |
currency | enum | no | EUR, USD, GBP, JPY. PTCG_INDEX rows are EUR; the marketplace sources are mostly USD, so a single card returns rows in more than one currency. |
locale | string | yes | Language of the printing the price refers to, when the source distinguishes them. |
condition | enum | yes | MINT, NEAR_MINT, EXCELLENT, GOOD, LIGHT_PLAYED, PLAYED, POOR. Null when the source does not grade condition, which is most of them. |
printing | enum | yes | NORMAL, HOLOFOIL, REVERSE_HOLO, FIRST_EDITION, FIRST_EDITION_HOLOFOIL. Null when the source quotes one number for all printings. |
grading | object | yes | { company, score } for graded slabs — PSA, BGS, CGC, SGC, ACE, TAG. Set on the MEDIAN_GRADED rows that name a grader; null on the ungraded ones. |
as_of | date | no | YYYY-MM-DD of the observation, not of the request. |
sample_n | integer | yes | Observations behind the number. Null when the source does not disclose it — which is itself worth surfacing to your users. |
provenance | string | no | Human-readable attribution string. Display it wherever you display the price. |
Example
{
"source": "PTCG_INDEX",
"variant": "INDEX",
"basis": "DERIVED",
"amount": 561.84,
"currency": "EUR",
"locale": "en",
"condition": null,
"printing": "HOLOFOIL",
"grading": null,
"as_of": "2026-08-26",
"sample_n": 2,
"provenance": "pokemontcgapi composite index"
}A graded row
MEDIAN_GRADED is where grading earns its place: the same card in a PSA 10 slab and in a CGC 10 slab are different markets, and collapsing them into one number would be the single most misleading thing this API could do.
{
"source": "PRICECHARTING",
"variant": "MEDIAN_GRADED",
"basis": "GUIDE",
"amount": 20061.40,
"currency": "USD",
"locale": "en",
"condition": null,
"printing": null,
"grading": { "company": "PSA", "score": "10" },
"as_of": "2026-08-24",
"sample_n": null,
"provenance": "PriceCharting"
}Attribution is not optional
The provenance string exists so you can comply without reading a contract: show it next to the number. It is also why the delay exists — aggregating and delaying is what keeps redistribution defensible, and we would rather ship a price that is a day old than a price we cannot serve at all.