BinderDex API
Get product
Proposed GET /v1/products/{product_id}
GET/v1/products/{product_id}
Requires catalog:read. Retrieve one opaque BinderDex product ID after manually verifying the full card identity: game, set, collector number, and printing, then select an observed variant and condition price lane; or verify exact sealed package details.
Proposed access: send an X-API-Key header from a server-side integration. Keys are unavailable during preview.
Response shape
| Field | Type | Required | Description |
|---|---|---|---|
data | Product | Yes | A verified raw-card or sealed-product identity. All fields are required; uncertain identities have no invented null fallback. |
data (option 1).id | string | Yes | Opaque immutable BinderDex public product ID. Never parse it; slugs and upstream IDs are aliases, not identity. Demo IDs and mappings are synthetic. pattern: ^bdp_[a-z0-9_]{3,64}$ |
data (option 1).kind | string | Yes | "card" const: card |
data (option 1).name | string | Yes | minLength: 1 · maxLength: 200 |
data (option 1).game | string | Yes | ["pokemon","one_piece"] enum: ["pokemon","one_piece"] |
data (option 1).language | string | Yes | "en" const: en |
data (option 1).market | string | Yes | "US" const: US |
data (option 1).identifiers | array<Identifier> | Yes | — |
data (option 1).identifiers[].namespace | string | Yes | minLength: 1 · maxLength: 100 |
data (option 1).identifiers[].value | string | Yes | minLength: 1 · maxLength: 200 |
data (option 1).catalog_updated_at | string | Yes | format: date-time · pattern: ^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{1,3})?Z$ |
data (option 1).set | CardSet | Yes | additionalProperties: false |
data (option 1).set.id | string | Yes | Opaque set identifier within the preview catalog. pattern: ^set_[a-z0-9_]{3,64}$ |
data (option 1).set.name | string | Yes | minLength: 1 · maxLength: 200 |
data (option 1).collector_number | string | Yes | Verified collector number within the identified set. It is not sufficient card identity by itself. minLength: 1 · maxLength: 100 |
data (option 1).printing | string | Yes | Verified exact art or edition/printing. A collector number alone does not identify a card printing. minLength: 1 · maxLength: 100 |
data (option 1).price_options | array<PriceOption> | Yes | Observed eligible variant and condition lanes. These are not coverage or price-availability promises. Ungraded is a distinct condition and is never converted to near_mint. minItems: 0 · uniqueItems: true |
data (option 1).price_options[].variant | string | Yes | minLength: 1 · maxLength: 100 |
data (option 1).price_options[].condition | string | Yes | ["near_mint","lightly_played","moderately_played","heavily_played","damaged","ungraded"] enum: ["near_mint","lightly_played","moderately_played","heavily_played","damaged","ungraded"] |
data (option 2).id | string | Yes | Opaque immutable BinderDex public product ID. Never parse it; slugs and upstream IDs are aliases, not identity. Demo IDs and mappings are synthetic. pattern: ^bdp_[a-z0-9_]{3,64}$ |
data (option 2).kind | string | Yes | "sealed" const: sealed |
data (option 2).name | string | Yes | minLength: 1 · maxLength: 200 |
data (option 2).game | string | Yes | ["pokemon","one_piece"] enum: ["pokemon","one_piece"] |
data (option 2).language | string | Yes | "en" const: en |
data (option 2).market | string | Yes | "US" const: US |
data (option 2).identifiers | array<Identifier> | Yes | — |
data (option 2).identifiers[].namespace | string | Yes | minLength: 1 · maxLength: 100 |
data (option 2).identifiers[].value | string | Yes | minLength: 1 · maxLength: 200 |
data (option 2).catalog_updated_at | string | Yes | format: date-time · pattern: ^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{1,3})?Z$ |
data (option 2).package_type | string | Yes | ["booster_bundle","elite_trainer_box","booster_box","booster_case"] enum: ["booster_bundle","elite_trainer_box","booster_box","booster_case"] |
data (option 2).units_per_package | integer | Yes | minimum: 1 |
data (option 2).unit_kind | string | Yes | ["booster_pack","booster_box"] enum: ["booster_pack","booster_box"] |
data (option 2).edition | string | Yes | pokemon_center is proposed only for Pokémon sealed products. ["standard","pokemon_center"] enum: ["standard","pokemon_center"] |
data (option 2).condition | string | Yes | "factory_sealed" const: factory_sealed |
meta | Meta | Yes | Freshness is evaluated at snapshot_at, which stays original on a batch replay. Other metadata is generated per response. Proposed commercial semantics: successful data calls may consume one request unit, including empty or missing data; replays and errors consume zero. additionalProperties: false |
meta.request_id | string | Yes | pattern: ^req_[a-zA-Z0-9_-]+$ |
meta.snapshot_at | string | Yes | format: date-time · pattern: ^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{1,3})?Z$ |
meta.billable_units | integer | Yes | [0,1] enum: [0,1] |
meta.idempotent_replay | boolean | Yes | — |
Response headers
| Header | Type | Preview meaning |
|---|---|---|
X-Request-Id | string | Request correlation identifier; safe to send to support. |
X-Request-Credits-Remaining | integer | Organization credits remaining after this request. Present only after successful key authentication. |
X-Request-Credits-Charged | integer | 0 or 1 for this response; internal cache hits count, idempotent batch replays do not. |
Cache-Control | string | private, no-store; key-specific metadata must never enter a shared HTTP cache. Server-side data caching is separate. |
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
product_id | path | string | Yes | pattern: ^bdp_[a-z0-9_]{3,64}$ |
Synthetic example
{
"data": {
"id": "bdp_demo_pikachu_en",
"kind": "card",
"name": "Pikachu — Demo Full Art",
"game": "pokemon",
"language": "en",
"market": "US",
"set": {
"id": "set_demo_paldea_en",
"name": "Demo Paldea Collection"
},
"collector_number": "198/193",
"printing": "Demo Full Art",
"price_options": [
{
"variant": "normal",
"condition": "near_mint"
},
{
"variant": "normal",
"condition": "lightly_played"
}
],
"identifiers": [
{
"namespace": "tcgplayer_product",
"value": "900003"
}
],
"catalog_updated_at": "2026-09-06T11:00:00Z"
},
"meta": {
"request_id": "req_example",
"snapshot_at": "2026-09-06T12:00:00Z",
"billable_units": 1,
"idempotent_replay": false
}
}Nested definitions
These are the exact reusable shapes referenced by this operation. Constraints are derived from the preview contract.
ProductResponseSchema definition
| Field | Type | Required | Description |
|---|---|---|---|
data | Product | Yes | A verified raw-card or sealed-product identity. All fields are required; uncertain identities have no invented null fallback. |
data (option 1).id | string | Yes | Opaque immutable BinderDex public product ID. Never parse it; slugs and upstream IDs are aliases, not identity. Demo IDs and mappings are synthetic. pattern: ^bdp_[a-z0-9_]{3,64}$ |
data (option 1).kind | string | Yes | "card" const: card |
data (option 1).name | string | Yes | minLength: 1 · maxLength: 200 |
data (option 1).game | string | Yes | ["pokemon","one_piece"] enum: ["pokemon","one_piece"] |
data (option 1).language | string | Yes | "en" const: en |
data (option 1).market | string | Yes | "US" const: US |
data (option 1).identifiers | array<Identifier> | Yes | — |
data (option 1).identifiers[].namespace | string | Yes | minLength: 1 · maxLength: 100 |
data (option 1).identifiers[].value | string | Yes | minLength: 1 · maxLength: 200 |
data (option 1).catalog_updated_at | string | Yes | format: date-time · pattern: ^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{1,3})?Z$ |
data (option 1).set | CardSet | Yes | additionalProperties: false |
data (option 1).set.id | string | Yes | Opaque set identifier within the preview catalog. pattern: ^set_[a-z0-9_]{3,64}$ |
data (option 1).set.name | string | Yes | minLength: 1 · maxLength: 200 |
data (option 1).collector_number | string | Yes | Verified collector number within the identified set. It is not sufficient card identity by itself. minLength: 1 · maxLength: 100 |
data (option 1).printing | string | Yes | Verified exact art or edition/printing. A collector number alone does not identify a card printing. minLength: 1 · maxLength: 100 |
data (option 1).price_options | array<PriceOption> | Yes | Observed eligible variant and condition lanes. These are not coverage or price-availability promises. Ungraded is a distinct condition and is never converted to near_mint. minItems: 0 · uniqueItems: true |
data (option 1).price_options[].variant | string | Yes | minLength: 1 · maxLength: 100 |
data (option 1).price_options[].condition | string | Yes | ["near_mint","lightly_played","moderately_played","heavily_played","damaged","ungraded"] enum: ["near_mint","lightly_played","moderately_played","heavily_played","damaged","ungraded"] |
data (option 2).id | string | Yes | Opaque immutable BinderDex public product ID. Never parse it; slugs and upstream IDs are aliases, not identity. Demo IDs and mappings are synthetic. pattern: ^bdp_[a-z0-9_]{3,64}$ |
data (option 2).kind | string | Yes | "sealed" const: sealed |
data (option 2).name | string | Yes | minLength: 1 · maxLength: 200 |
data (option 2).game | string | Yes | ["pokemon","one_piece"] enum: ["pokemon","one_piece"] |
data (option 2).language | string | Yes | "en" const: en |
data (option 2).market | string | Yes | "US" const: US |
data (option 2).identifiers | array<Identifier> | Yes | — |
data (option 2).identifiers[].namespace | string | Yes | minLength: 1 · maxLength: 100 |
data (option 2).identifiers[].value | string | Yes | minLength: 1 · maxLength: 200 |
data (option 2).catalog_updated_at | string | Yes | format: date-time · pattern: ^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{1,3})?Z$ |
data (option 2).package_type | string | Yes | ["booster_bundle","elite_trainer_box","booster_box","booster_case"] enum: ["booster_bundle","elite_trainer_box","booster_box","booster_case"] |
data (option 2).units_per_package | integer | Yes | minimum: 1 |
data (option 2).unit_kind | string | Yes | ["booster_pack","booster_box"] enum: ["booster_pack","booster_box"] |
data (option 2).edition | string | Yes | pokemon_center is proposed only for Pokémon sealed products. ["standard","pokemon_center"] enum: ["standard","pokemon_center"] |
data (option 2).condition | string | Yes | "factory_sealed" const: factory_sealed |
meta | Meta | Yes | Freshness is evaluated at snapshot_at, which stays original on a batch replay. Other metadata is generated per response. Proposed commercial semantics: successful data calls may consume one request unit, including empty or missing data; replays and errors consume zero. additionalProperties: false |
meta.request_id | string | Yes | pattern: ^req_[a-zA-Z0-9_-]+$ |
meta.snapshot_at | string | Yes | format: date-time · pattern: ^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{1,3})?Z$ |
meta.billable_units | integer | Yes | [0,1] enum: [0,1] |
meta.idempotent_replay | boolean | Yes | — |
Full canonical schema JSON
{
"type": "object",
"properties": {
"data": {
"$ref": "#/components/schemas/Product"
},
"meta": {
"$ref": "#/components/schemas/Meta"
}
},
"required": [
"data",
"meta"
],
"additionalProperties": false
}ProductA verified raw-card or sealed-product identity. All fields are required; uncertain identities have no invented null fallback.
| Field | Type | Required | Description |
|---|---|---|---|
option 1.id | string | Yes | Opaque immutable BinderDex public product ID. Never parse it; slugs and upstream IDs are aliases, not identity. Demo IDs and mappings are synthetic. pattern: ^bdp_[a-z0-9_]{3,64}$ |
option 1.kind | string | Yes | "card" const: card |
option 1.name | string | Yes | minLength: 1 · maxLength: 200 |
option 1.game | string | Yes | ["pokemon","one_piece"] enum: ["pokemon","one_piece"] |
option 1.language | string | Yes | "en" const: en |
option 1.market | string | Yes | "US" const: US |
option 1.identifiers | array<Identifier> | Yes | — |
option 1.identifiers[].namespace | string | Yes | minLength: 1 · maxLength: 100 |
option 1.identifiers[].value | string | Yes | minLength: 1 · maxLength: 200 |
option 1.catalog_updated_at | string | Yes | format: date-time · pattern: ^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{1,3})?Z$ |
option 1.set | CardSet | Yes | additionalProperties: false |
option 1.set.id | string | Yes | Opaque set identifier within the preview catalog. pattern: ^set_[a-z0-9_]{3,64}$ |
option 1.set.name | string | Yes | minLength: 1 · maxLength: 200 |
option 1.collector_number | string | Yes | Verified collector number within the identified set. It is not sufficient card identity by itself. minLength: 1 · maxLength: 100 |
option 1.printing | string | Yes | Verified exact art or edition/printing. A collector number alone does not identify a card printing. minLength: 1 · maxLength: 100 |
option 1.price_options | array<PriceOption> | Yes | Observed eligible variant and condition lanes. These are not coverage or price-availability promises. Ungraded is a distinct condition and is never converted to near_mint. minItems: 0 · uniqueItems: true |
option 1.price_options[].variant | string | Yes | minLength: 1 · maxLength: 100 |
option 1.price_options[].condition | string | Yes | ["near_mint","lightly_played","moderately_played","heavily_played","damaged","ungraded"] enum: ["near_mint","lightly_played","moderately_played","heavily_played","damaged","ungraded"] |
option 2.id | string | Yes | Opaque immutable BinderDex public product ID. Never parse it; slugs and upstream IDs are aliases, not identity. Demo IDs and mappings are synthetic. pattern: ^bdp_[a-z0-9_]{3,64}$ |
option 2.kind | string | Yes | "sealed" const: sealed |
option 2.name | string | Yes | minLength: 1 · maxLength: 200 |
option 2.game | string | Yes | ["pokemon","one_piece"] enum: ["pokemon","one_piece"] |
option 2.language | string | Yes | "en" const: en |
option 2.market | string | Yes | "US" const: US |
option 2.identifiers | array<Identifier> | Yes | — |
option 2.identifiers[].namespace | string | Yes | minLength: 1 · maxLength: 100 |
option 2.identifiers[].value | string | Yes | minLength: 1 · maxLength: 200 |
option 2.catalog_updated_at | string | Yes | format: date-time · pattern: ^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{1,3})?Z$ |
option 2.package_type | string | Yes | ["booster_bundle","elite_trainer_box","booster_box","booster_case"] enum: ["booster_bundle","elite_trainer_box","booster_box","booster_case"] |
option 2.units_per_package | integer | Yes | minimum: 1 |
option 2.unit_kind | string | Yes | ["booster_pack","booster_box"] enum: ["booster_pack","booster_box"] |
option 2.edition | string | Yes | pokemon_center is proposed only for Pokémon sealed products. ["standard","pokemon_center"] enum: ["standard","pokemon_center"] |
option 2.condition | string | Yes | "factory_sealed" const: factory_sealed |
Full canonical schema JSON
{
"oneOf": [
{
"$ref": "#/components/schemas/CardProduct"
},
{
"$ref": "#/components/schemas/SealedProduct"
}
],
"discriminator": {
"propertyName": "kind",
"mapping": {
"card": "#/components/schemas/CardProduct",
"sealed": "#/components/schemas/SealedProduct"
}
},
"description": "A verified raw-card or sealed-product identity. All fields are required; uncertain identities have no invented null fallback."
}CardProductVerified raw-card identity. Separate IDs are required for different prints, art, or releases. A card identity has no condition: variant and condition belong to an explicit price selection.
| Field | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Opaque immutable BinderDex public product ID. Never parse it; slugs and upstream IDs are aliases, not identity. Demo IDs and mappings are synthetic. pattern: ^bdp_[a-z0-9_]{3,64}$ |
kind | string | Yes | "card" const: card |
name | string | Yes | minLength: 1 · maxLength: 200 |
game | string | Yes | ["pokemon","one_piece"] enum: ["pokemon","one_piece"] |
language | string | Yes | "en" const: en |
market | string | Yes | "US" const: US |
identifiers | array<Identifier> | Yes | — |
identifiers[].namespace | string | Yes | minLength: 1 · maxLength: 100 |
identifiers[].value | string | Yes | minLength: 1 · maxLength: 200 |
catalog_updated_at | string | Yes | format: date-time · pattern: ^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{1,3})?Z$ |
set | CardSet | Yes | additionalProperties: false |
set.id | string | Yes | Opaque set identifier within the preview catalog. pattern: ^set_[a-z0-9_]{3,64}$ |
set.name | string | Yes | minLength: 1 · maxLength: 200 |
collector_number | string | Yes | Verified collector number within the identified set. It is not sufficient card identity by itself. minLength: 1 · maxLength: 100 |
printing | string | Yes | Verified exact art or edition/printing. A collector number alone does not identify a card printing. minLength: 1 · maxLength: 100 |
price_options | array<PriceOption> | Yes | Observed eligible variant and condition lanes. These are not coverage or price-availability promises. Ungraded is a distinct condition and is never converted to near_mint. minItems: 0 · uniqueItems: true |
price_options[].variant | string | Yes | minLength: 1 · maxLength: 100 |
price_options[].condition | string | Yes | ["near_mint","lightly_played","moderately_played","heavily_played","damaged","ungraded"] enum: ["near_mint","lightly_played","moderately_played","heavily_played","damaged","ungraded"] |
Full canonical schema JSON
{
"type": "object",
"properties": {
"id": {
"type": "string",
"pattern": "^bdp_[a-z0-9_]{3,64}$",
"description": "Opaque immutable BinderDex public product ID. Never parse it; slugs and upstream IDs are aliases, not identity. Demo IDs and mappings are synthetic."
},
"kind": {
"type": "string",
"const": "card"
},
"name": {
"type": "string",
"minLength": 1,
"maxLength": 200
},
"game": {
"type": "string",
"enum": [
"pokemon",
"one_piece"
]
},
"language": {
"type": "string",
"const": "en"
},
"market": {
"type": "string",
"const": "US"
},
"identifiers": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Identifier"
}
},
"catalog_updated_at": {
"type": "string",
"format": "date-time",
"pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:\\.\\d{1,3})?Z$"
},
"set": {
"$ref": "#/components/schemas/CardSet"
},
"collector_number": {
"type": "string",
"minLength": 1,
"maxLength": 100,
"description": "Verified collector number within the identified set. It is not sufficient card identity by itself."
},
"printing": {
"type": "string",
"minLength": 1,
"maxLength": 100,
"description": "Verified exact art or edition/printing. A collector number alone does not identify a card printing."
},
"price_options": {
"type": "array",
"minItems": 0,
"items": {
"$ref": "#/components/schemas/PriceOption"
},
"description": "Observed eligible variant and condition lanes. These are not coverage or price-availability promises. Ungraded is a distinct condition and is never converted to near_mint.",
"uniqueItems": true
}
},
"required": [
"id",
"kind",
"name",
"game",
"language",
"market",
"identifiers",
"catalog_updated_at",
"set",
"collector_number",
"printing",
"price_options"
],
"additionalProperties": false,
"description": "Verified raw-card identity. Separate IDs are required for different prints, art, or releases. A card identity has no condition: variant and condition belong to an explicit price selection."
}SealedProductVerified sealed-product identity. Sealed products may belong to either supported game; pokemon_center edition is limited to Pokémon.
| Field | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Opaque immutable BinderDex public product ID. Never parse it; slugs and upstream IDs are aliases, not identity. Demo IDs and mappings are synthetic. pattern: ^bdp_[a-z0-9_]{3,64}$ |
kind | string | Yes | "sealed" const: sealed |
name | string | Yes | minLength: 1 · maxLength: 200 |
game | string | Yes | ["pokemon","one_piece"] enum: ["pokemon","one_piece"] |
language | string | Yes | "en" const: en |
market | string | Yes | "US" const: US |
identifiers | array<Identifier> | Yes | — |
identifiers[].namespace | string | Yes | minLength: 1 · maxLength: 100 |
identifiers[].value | string | Yes | minLength: 1 · maxLength: 200 |
catalog_updated_at | string | Yes | format: date-time · pattern: ^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{1,3})?Z$ |
package_type | string | Yes | ["booster_bundle","elite_trainer_box","booster_box","booster_case"] enum: ["booster_bundle","elite_trainer_box","booster_box","booster_case"] |
units_per_package | integer | Yes | minimum: 1 |
unit_kind | string | Yes | ["booster_pack","booster_box"] enum: ["booster_pack","booster_box"] |
edition | string | Yes | pokemon_center is proposed only for Pokémon sealed products. ["standard","pokemon_center"] enum: ["standard","pokemon_center"] |
condition | string | Yes | "factory_sealed" const: factory_sealed |
Full canonical schema JSON
{
"type": "object",
"properties": {
"id": {
"type": "string",
"pattern": "^bdp_[a-z0-9_]{3,64}$",
"description": "Opaque immutable BinderDex public product ID. Never parse it; slugs and upstream IDs are aliases, not identity. Demo IDs and mappings are synthetic."
},
"kind": {
"type": "string",
"const": "sealed"
},
"name": {
"type": "string",
"minLength": 1,
"maxLength": 200
},
"game": {
"type": "string",
"enum": [
"pokemon",
"one_piece"
]
},
"language": {
"type": "string",
"const": "en"
},
"market": {
"type": "string",
"const": "US"
},
"identifiers": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Identifier"
}
},
"catalog_updated_at": {
"type": "string",
"format": "date-time",
"pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:\\.\\d{1,3})?Z$"
},
"package_type": {
"type": "string",
"enum": [
"booster_bundle",
"elite_trainer_box",
"booster_box",
"booster_case"
]
},
"units_per_package": {
"type": "integer",
"minimum": 1
},
"unit_kind": {
"type": "string",
"enum": [
"booster_pack",
"booster_box"
]
},
"edition": {
"type": "string",
"enum": [
"standard",
"pokemon_center"
],
"description": "pokemon_center is proposed only for Pokémon sealed products."
},
"condition": {
"type": "string",
"const": "factory_sealed"
}
},
"required": [
"id",
"kind",
"name",
"game",
"language",
"market",
"identifiers",
"catalog_updated_at",
"package_type",
"units_per_package",
"unit_kind",
"edition",
"condition"
],
"additionalProperties": false,
"allOf": [
{
"if": {
"properties": {
"game": {
"const": "one_piece"
}
}
},
"then": {
"properties": {
"edition": {
"const": "standard"
}
}
}
}
],
"description": "Verified sealed-product identity. Sealed products may belong to either supported game; pokemon_center edition is limited to Pokémon."
}CardSetSchema definition
| Field | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Opaque set identifier within the preview catalog. pattern: ^set_[a-z0-9_]{3,64}$ |
name | string | Yes | minLength: 1 · maxLength: 200 |
Full canonical schema JSON
{
"type": "object",
"properties": {
"id": {
"type": "string",
"pattern": "^set_[a-z0-9_]{3,64}$",
"description": "Opaque set identifier within the preview catalog."
},
"name": {
"type": "string",
"minLength": 1,
"maxLength": 200
}
},
"required": [
"id",
"name"
],
"additionalProperties": false
}PriceOptionObserved eligible raw-card price lane. It describes an available identity lane, not a promise of coverage or a price.
| Field | Type | Required | Description |
|---|---|---|---|
variant | string | Yes | minLength: 1 · maxLength: 100 |
condition | string | Yes | ["near_mint","lightly_played","moderately_played","heavily_played","damaged","ungraded"] enum: ["near_mint","lightly_played","moderately_played","heavily_played","damaged","ungraded"] |
Full canonical schema JSON
{
"type": "object",
"properties": {
"variant": {
"type": "string",
"minLength": 1,
"maxLength": 100
},
"condition": {
"type": "string",
"enum": [
"near_mint",
"lightly_played",
"moderately_played",
"heavily_played",
"damaged",
"ungraded"
]
}
},
"required": [
"variant",
"condition"
],
"additionalProperties": false,
"description": "Observed eligible raw-card price lane. It describes an available identity lane, not a promise of coverage or a price."
}IdentifierVerified external or catalog alias. A tcgplayer_product alias uses a numeric value. Aliases help matching but never replace the opaque BinderDex product ID.
| Field | Type | Required | Description |
|---|---|---|---|
namespace | string | Yes | minLength: 1 · maxLength: 100 |
value | string | Yes | minLength: 1 · maxLength: 200 |
Full canonical schema JSON
{
"type": "object",
"properties": {
"namespace": {
"type": "string",
"minLength": 1,
"maxLength": 100
},
"value": {
"type": "string",
"minLength": 1,
"maxLength": 200
}
},
"required": [
"namespace",
"value"
],
"additionalProperties": false,
"description": "Verified external or catalog alias. A tcgplayer_product alias uses a numeric value. Aliases help matching but never replace the opaque BinderDex product ID.",
"allOf": [
{
"if": {
"properties": {
"namespace": {
"const": "tcgplayer_product"
}
}
},
"then": {
"properties": {
"value": {
"pattern": "^[0-9]+$"
}
}
}
}
]
}MetaFreshness is evaluated at snapshot_at, which stays original on a batch replay. Other metadata is generated per response. Proposed commercial semantics: successful data calls may consume one request unit, including empty or missing data; replays and errors consume zero.
| Field | Type | Required | Description |
|---|---|---|---|
request_id | string | Yes | pattern: ^req_[a-zA-Z0-9_-]+$ |
snapshot_at | string | Yes | format: date-time · pattern: ^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{1,3})?Z$ |
billable_units | integer | Yes | [0,1] enum: [0,1] |
idempotent_replay | boolean | Yes | — |
Full canonical schema JSON
{
"type": "object",
"properties": {
"request_id": {
"type": "string",
"pattern": "^req_[a-zA-Z0-9_-]+$"
},
"snapshot_at": {
"type": "string",
"format": "date-time",
"pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:\\.\\d{1,3})?Z$"
},
"billable_units": {
"type": "integer",
"enum": [
0,
1
]
},
"idempotent_replay": {
"type": "boolean"
}
},
"required": [
"request_id",
"snapshot_at",
"billable_units",
"idempotent_replay"
],
"additionalProperties": false,
"description": "Freshness is evaluated at snapshot_at, which stays original on a batch replay. Other metadata is generated per response. Proposed commercial semantics: successful data calls may consume one request unit, including empty or missing data; replays and errors consume zero."
}Possible errors
Every error below uses the Error envelope with a request ID. Retry only when the response’s proposed semantics identify a temporary condition; see errors and versioning for the detailed guidance.
400 synthetic error example
Invalid or unknown parameter/body, duplicated query parameter, malformed or expired cursor.
X-Request-Id — Request correlation identifier; safe to send to support. X-Request-Credits-Remaining — Organization credits remaining after this request. Present only after successful key authentication. X-Request-Credits-Charged — 0 or 1 for this response; internal cache hits count, idempotent batch replays do not. Cache-Control — private, no-store; key-specific metadata must never enter a shared HTTP cache. Server-side data caching is separate.
{
"error": {
"code": "invalid_request",
"message": "Synthetic example: Invalid or unknown parameter/body, duplicated query parameter, malformed or expired cursor.",
"request_id": "req_example",
"retry_after_seconds": null
}
}401 synthetic error example
Missing, invalid, expired or revoked API key.
X-Request-Id — Request correlation identifier; safe to send to support. X-Request-Credits-Remaining — Organization credits remaining after this request. Present only after successful key authentication. X-Request-Credits-Charged — 0 or 1 for this response; internal cache hits count, idempotent batch replays do not. Cache-Control — private, no-store; key-specific metadata must never enter a shared HTTP cache. Server-side data caching is separate.
{
"error": {
"code": "invalid_api_key",
"message": "Synthetic example: Missing, invalid, expired or revoked API key.",
"request_id": "req_example",
"retry_after_seconds": null
}
}403 synthetic error example
Authenticated key lacks endpoint scope or entitlement.
X-Request-Id — Request correlation identifier; safe to send to support. X-Request-Credits-Remaining — Organization credits remaining after this request. Present only after successful key authentication. X-Request-Credits-Charged — 0 or 1 for this response; internal cache hits count, idempotent batch replays do not. Cache-Control — private, no-store; key-specific metadata must never enter a shared HTTP cache. Server-side data caching is separate.
{
"error": {
"code": "insufficient_scope",
"message": "Synthetic example: Authenticated key lacks endpoint scope or entitlement.",
"request_id": "req_example",
"retry_after_seconds": null
}
}404 synthetic error example
Unknown product or route; outside allowed catalog is indistinguishable from unknown.
X-Request-Id — Request correlation identifier; safe to send to support. X-Request-Credits-Remaining — Organization credits remaining after this request. Present only after successful key authentication. X-Request-Credits-Charged — 0 or 1 for this response; internal cache hits count, idempotent batch replays do not. Cache-Control — private, no-store; key-specific metadata must never enter a shared HTTP cache. Server-side data caching is separate.
{
"error": {
"code": "not_found",
"message": "Synthetic example: Unknown product or route; outside allowed catalog is indistinguishable from unknown.",
"request_id": "req_example",
"retry_after_seconds": null
}
}429 synthetic error example
rate_limit_exceeded or quota_exceeded; distinct codes and Retry-After.
X-Request-Id — Request correlation identifier; safe to send to support. X-Request-Credits-Remaining — Organization credits remaining after this request. Present only after successful key authentication. X-Request-Credits-Charged — 0 or 1 for this response; internal cache hits count, idempotent batch replays do not. Cache-Control — private, no-store; key-specific metadata must never enter a shared HTTP cache. Server-side data caching is separate. Retry-After — Whole seconds until retry.
{
"error": {
"code": "rate_limit_exceeded",
"message": "Synthetic example: rate_limit_exceeded or quota_exceeded; distinct codes and Retry-After.",
"request_id": "req_example",
"retry_after_seconds": 60
}
}500 synthetic error example
Unexpected internal failure; no sensitive details and zero credits.
X-Request-Id — Request correlation identifier; safe to send to support. X-Request-Credits-Remaining — Organization credits remaining after this request. Present only after successful key authentication. X-Request-Credits-Charged — 0 or 1 for this response; internal cache hits count, idempotent batch replays do not. Cache-Control — private, no-store; key-specific metadata must never enter a shared HTTP cache. Server-side data caching is separate.
{
"error": {
"code": "internal_error",
"message": "Synthetic example: Unexpected internal failure; no sensitive details and zero credits.",
"request_id": "req_example",
"retry_after_seconds": null
}
}503 synthetic error example
temporarily_unavailable: metering, key state, or serving dependency unavailable; fail closed and charge zero.
X-Request-Id — Request correlation identifier; safe to send to support. X-Request-Credits-Remaining — Organization credits remaining after this request. Present only after successful key authentication. X-Request-Credits-Charged — 0 or 1 for this response; internal cache hits count, idempotent batch replays do not. Cache-Control — private, no-store; key-specific metadata must never enter a shared HTTP cache. Server-side data caching is separate. Retry-After — Whole seconds until retry.
{
"error": {
"code": "temporarily_unavailable",
"message": "Synthetic example: temporarily_unavailable: metering, key state, or serving dependency unavailable; fail closed and charge zero.",
"request_id": "req_example",
"retry_after_seconds": 30
}
}