Search products

Searches the catalogue. Returns a paginated list of products matching the body.

Use this to find a card by name, browse an expansion, or filter on game-specific attributes like rarity or color. To replicate the full catalogue, use GET /v1/feeds/products instead — the feed is regenerated whenever a game's catalogue updates (typically minutes after a change).

Filter fields:

  • name — free-text search against the product name, ranked by relevance. A print number before or after the name (sephiroth 44) pins that print; an expansion code plus print number (msh-54, msh 54, msh54) pins a single card; an expansion code on its own (msh) surfaces that expansion's products.
  • printNumber — exact print-number match, ignoring case.
  • productIds, expansionId, nameSlug — direct lookups when you already know the identifier. productIds, expansionId, cardmarketId, and tcgplayerId take up to 200 ids per call — split larger sets across several calls.
  • expansionId — one or more expansions, matched as "any of". Pair it with nameSlug to follow a card across a set of expansions.
  • productType, productCategory — restrict to cards or sealed (and a sealed category like booster_box).
  • gameFilters — pick a game (e.g. { "game": "mtg" }), and optionally that game's own attribute filters in the same object.

Marketplace listings:

Send a listings object — even an empty one — and every result gains an availability block: how many listings match, and the cheapest one you can buy, with its listingId ready for POST /v1/cart/items. Filter those listings with deliveryCountry, condition, language, and finish, and set inStock: true to drop products with no match.

deliveryCountry applies the same rule as checkout, so a listing returned here can be added to your cart. Sellers ship within their own country and across Europe and North America; a country outside that set matches nothing.

availability.cheapest.price is what you pay. It sits alongside pricesByFinish, where cardnexus.low is the marketplace floor across every country and every seller — so the two differ whenever the cheapest copy in the world can't reach you.

Two combinations are rejected with 400: listings together with cardmarketId or tcgplayerId, and listings together with sortBy: releaseDate. With listings, results are ordered by relevance and offset + limit cannot exceed 300,000.

Language: send an Accept-Language header (en, fr, it, es, de) to work in another language — your name text is matched in that language where a translation exists (falling back to English), and product and expansion names in the results come back in it where a translation exists. Searching Blizzaroi with Accept-Language: fr finds Abomasnow.

Pagination + sort:

  • limit defaults to 50, max 200. offset defaults to 0.
  • sortBy, sortDirection — sort the results.

Each result has productType set to either card or sealed. Card products carry per-finish prices and per-game attributes; sealed products carry a single price plus EAN/SKU.

This endpoint has its own rate-limit bucket (catalogue-search); paginating through tens of thousands of results will hit it before your account-level limit. The daily feeds are the right tool for bulk catalogue replication.

Authentication is required (any valid API key); no scope.

Headers
  • Accept-Language
    Type: string

    The language to work in — en, fr, it, es, or de, with or without a region. Name searches match in that language where a translation exists, falling back to English. Defaults to English.

Body
required
application/json
  • cardmarketId
    Type: array integer[] 1…200
    min:  
    0
    max:  
    9007199254740991

    Restrict results to products carrying any of these Cardmarket product ids (1–200), returned with full details. Use this to fetch details for ids you already know; to turn a list of ids into products and learn which ones don't match, use POST /v1/products/resolve.

  • expansionId
    Type: array 1…200

    Restrict results to these expansions (1–200). Ids are returned by GET /v1/games/{gameId}/expansions.

  • gameFilters

    Restrict to a single game, and optionally filter on that game's own attributes (rarity, color, …). Pass { "game": "mtg" } for any MTG product, or add filters: { rarity: { op: "or", values: ["mythic"] } } to narrow further. To narrow to expansions, use expansionId.

    Restrict to a single game, and optionally filter on that game's own attributes (rarity, color, …). Pass { "game": "mtg" } for any MTG product, or add filters: { rarity: { op: "or", values: ["mythic"] } } to narrow further. To narrow to expansions, use expansionId.

    • game
      const:  
      sorcery
      required
    • filters
      Type: object
  • limit
    Type: integer
    min:  
    1
    max:  
    200

    Integer numbers.

  • listings
    Type: object

    Search against live marketplace listings. Sending this object — even empty — adds an availability block to every result carrying the cheapest listing you can buy under these filters. Not accepted together with cardmarketId, tcgplayerId, or sortBy: releaseDate.

  • name
    Type: string
    min length:  
    1

    Free-text search. Matches against the product name with relevance ranking — the closer the match, the higher the result. A print number before or after the name pins that print: sephiroth 44 returns the Sephiroth numbered 44 first. An expansion code plus print number pins a single card: msh-54, msh 54, and msh54 all return card 54 of the expansion coded MSH. Send an Accept-Language header to search names in another language.

  • nameSlug
    Type: string
    min length:  
    1

    Exact match against the product's nameSlug, ignoring case — every printing of that card, across expansions. Slugs come back on every product in nameSlug.

  • offset
    Type: integer
    min:  
    0
    max:  
    9007199254740991

    Integer numbers.

  • printNumber
    Type: string
    min length:  
    1

    Return only products with this print number, matched exactly ignoring case — 232, 038, ST02-44. Combine with expansionId to pin a single printing.

  • productCategory
    Type: string

    Restrict to a single sealed-product category (e.g. booster_box, bundle). Only meaningful when filtering on sealed.

  • productIds
    Type: array 1…200

    Restrict results to a specific set of product ids (1–200). Useful for batch lookups when you already know which products you want.

  • productType
    Type: object

    Restrict to one or more product types — { op: "or", values: ["card"] } for cards only.

Responses
  • application/json
  • application/json
  • application/json
  • application/json
  • application/json
  • application/json
  • application/json
Request Example for post/products/search
curl https://public-api.cardnexus.com/v1/products/search \
  --request POST \
  --header 'Content-Type: application/json' \
  --header 'Authorization: Bearer YOUR_SECRET_TOKEN' \
  --data '{
  "offset": 0,
  "limit": 50,
  "productIds": [
    1
  ],
  "expansionId": [
    42,
    118
  ],
  "name": "",
  "printNumber": "ST02-44",
  "nameSlug": "",
  "cardmarketId": [
    0
  ],
  "tcgplayerId": [
    0
  ],
  "productType": {
    "op": "and",
    "values": [
      "card"
    ]
  },
  "productCategory": "",
  "gameFilters": {
    "game": "sorcery",
    "filters": {}
  },
  "listings": {
    "deliveryCountry": "GB",
    "inStock": true,
    "condition": [
      "NM"
    ],
    "language": [
      "en",
      "fr"
    ],
    "finish": [
      "Standard"
    ]
  },
  "sortBy": "printNumber",
  "sortDirection": "asc"
}'
{
  "data": [
    {
      "id": 50212,
      "gameId": "mtg",
      "expansionId": 42,
      "game": {
        "id": "mtg",
        "name": "Magic: The Gathering"
      },
      "expansion": {
        "id": 42,
        "name": "Limited Edition Alpha",
        "code": "LEA",
        "symbolUrl": "https://images.cardnexus.com/expansions/mtg/lea/symbol.svg"
      },
      "name": "Black Lotus",
      "nameSlug": "black-lotus",
      "languages": [
        "en"
      ],
      "imageUrl": "https://images.cardnexus.com/products/mtg/lea/black-lotus-front.jpg",
      "externalIds": {
        "cardmarket": [
          {
            "finish": "Standard",
            "id": 5824
          }
        ],
        "tcgplayer": [
          {
            "finish": "Standard",
            "id": 1527
          }
        ],
        "scryfallId": "ff1b8fc5-604a-4449-a73d-861e53642a70",
        "scryfallOracleId": "b7ad39b3-5d10-45a4-99ae-30972ea6ac42"
      },
      "productType": "card",
      "printNumber": "232",
      "rarity": "rare",
      "finishes": [
        "Standard"
      ],
      "pricesByFinish": {
        "Standard": {
          "cardmarket": {
            "currency": "EUR",
            "marketValue": 18250,
            "change7d": -1.2
          },
          "tcgplayer": {
            "currency": "USD",
            "marketValue": 20100,
            "change7d": -0.9
          }
        }
      },
      "attributes": {
        "manaCost": "{0}",
        "colors": [],
        "typeLine": "Artifact"
      }
    }
  ],
  "pagination": {
    "offset": 0,
    "limit": 50,
    "total": 124,
    "hasMore": true
  }
}