Advanced Search
1. Calling the Manifest, Or Not All Advanced Searches Are Created Equal | 2. Constructing A Search Call | 3. Processing Our Results
Now, obviously your application is caching the data pulled from /catalog endpoints. You're not? Huh. (adds "Harass Devs to write a Catalog caching tips article" to task list) Well, if you had the data cached, I imagine your custom search algorithm would shake the pillars of heaven. But since you haven't set up your caching, why not leverage the TCGplayer.com Advanced Search Engines? They may not shake the pillars of heaven, but they are shiny & chrome.
1. Calling the Manifest, Or Not All Advanced Searches Are Created Equal
Each Category has different parameters within Advanced Search. With the wide variety of games & collectibles in the TCGplayer catalog, filters applicable across all categories would be of little use for precision searching.
The Advanced Search page for each Category at TCGplayer.com can vary wildly.
Witness the robust options for Magic:The Gathering. On the other hand, Supplies offers lean options due to the nature of the category.
For an API Application, these options are readily available via the GET /catalog/categories/{categoryId}/search/manifest endpoint!
Endpoint: GET /catalog/categories/{categoryId}/search/manifest
Permissions Required:
Parameters: categoryId(required)
Headers: Authorization|{bearerToken}Returns the advanced search parameters for the designated category. These parameters are for use with POST /catalog/categories/{categoryId}/search endpoint.
Let's see this endpoint in action, shall we? Let's say we would like to do some gaming historic recreation and need to search for a Final Fantasy TCG card. So, we pull up the Final Fantasy manifest. The categoryId will be required and then the call can be made. This response will be quite extensive, so I'll see you on the other side.
Final Fantasy TCG categoryId = 24
GET https://api.tcgplayer.com/v1.39.0/catalog/categories/24/search/manifest
Header: Authorization|{bearerToken}
{
"success": true,
"errors": [],
"results": [
{
"sorting": [
{
"text": "A-Z",
"value": "ProductName ASC"
},
{
"text": "Price: High to Low",
"value": "MinPrice DESC"
},
{
"text": "Price: Low to High",
"value": "MinPrice ASC"
},
{
"text": "Relevance",
"value": "Relevance"
},
{
"text": "Best Selling",
"value": "Sales DESC"
}
],
"filters": [
{
"name": "ProductName",
"displayName": "Name",
"inputType": "Text",
"items": []
},
{
"name": "Description",
"displayName": "Description",
"inputType": "Text",
"items": []
},
{
"name": "SetName",
"displayName": "Set",
"inputType": "SingleValue",
"items": [
{
"text": "Any",
"value": ""
},
{
"text": "FF: Promo Cards",
"value": "FF: Promo Cards"
},
{
"text": "Opus I",
"value": "Opus I"
},
{
"text": "Opus II",
"value": "Opus II"
},
{
"text": "Opus III",
"value": "Opus III"
},
{
"text": "Opus IV",
"value": "Opus IV"
}
]
},
{
"name": "Rarity",
"displayName": "Rarity",
"inputType": "MultipleValues",
"items": [
{
"text": "Rare",
"value": "Rare"
},
{
"text": "Common",
"value": "Common"
},
{
"text": "Legend",
"value": "Legend"
},
{
"text": "Hero",
"value": "Hero"
},
{
"text": "Starter",
"value": "Starter"
},
{
"text": "Promo",
"value": "Promo"
},
{
"text": "None",
"value": "None"
}
]
},
{
"name": "CardType",
"displayName": "Card Type",
"inputType": "SingleValue",
"items": [
{
"text": "Any",
"value": ""
},
{
"text": "Backup",
"value": "Backup"
},
{
"text": "Forward",
"value": "Forward"
},
{
"text": "Summon",
"value": "Summon"
}
]
},
{
"name": "Element",
"displayName": "Element",
"inputType": "SingleValue",
"items": [
{
"text": "Any",
"value": ""
},
{
"text": "Dark",
"value": "Dark"
},
{
"text": "Earth",
"value": "Earth"
},
{
"text": "Fire",
"value": "Fire"
},
{
"text": "Ice",
"value": "Ice"
},
{
"text": "Light",
"value": "Light"
},
{
"text": "Lightning",
"value": "Lightning"
},
{
"text": "Water",
"value": "Water"
},
{
"text": "Wind",
"value": "Wind"
}
]
},
{
"name": "Cost",
"displayName": "Cost",
"inputType": "SingleValue",
"items": [
{
"text": "Any",
"value": ""
},
{
"text": "1",
"value": "1"
},
{
"text": "2",
"value": "2"
},
{
"text": "3",
"value": "3"
},
{
"text": "4",
"value": "4"
},
{
"text": "5",
"value": "5"
},
{
"text": "6",
"value": "6"
},
{
"text": "7",
"value": "7"
},
{
"text": "8",
"value": "8"
},
{
"text": "9",
"value": "9"
}
]
},
{
"name": "Job",
"displayName": "Job",
"inputType": "Text",
"items": []
},
{
"name": "Category",
"displayName": "Category",
"inputType": "SingleValue",
"items": [
{
"text": "Any",
"value": ""
},
{
"text": "DFF",
"value": "DFF"
},
{
"text": "DFF-I",
"value": "DFF-I"
},
{
"text": "DFF-II",
"value": "DFF-II"
},
{
"text": "DFF-III",
"value": "DFF-III"
},
{
"text": "DFF-IV",
"value": "DFF-IV"
},
{
"text": "DFF-IX",
"value": "DFF-IX"
},
{
"text": "DFF-V",
"value": "DFF-V"
},
{
"text": "DFF-VI",
"value": "DFF-VI"
},
{
"text": "DFF-VII",
"value": "DFF-VII"
},
{
"text": "DFF-VIII",
"value": "DFF-VIII"
},
{
"text": "DFF-X",
"value": "DFF-X"
},
{
"text": "DFF-XI",
"value": "DFF-XI"
},
{
"text": "DFF-XII",
"value": "DFF-XII"
},
{
"text": "DFF - XIII",
"value": "DFF - XIII"
},
{
"text": "DFF-XIV",
"value": "DFF-XIV"
},
{
"text": "FFT",
"value": "FFT"
},
{
"text": "II",
"value": "II"
},
{
"text": "III",
"value": "III"
},
{
"text": "IV",
"value": "IV"
},
{
"text": "IX",
"value": "IX"
},
{
"text": "LOV - IV",
"value": "LOV - IV"
},
{
"text": "LOV - IX",
"value": "LOV - IX"
},
{
"text": "VII",
"value": "VII"
},
{
"text": "V",
"value": "V"
},
{
"text": "VIII",
"value": "VIII"
},
{
"text": "Type-0",
"value": "Type-0"
},
{
"text": "WOFF",
"value": "WOFF"
},
{
"text": "X",
"value": "X"
},
{
"text": "XII",
"value": "XII"
},
{
"text": "XIII",
"value": "XIII"
},
{
"text": "XIV",
"value": "XIV"
}
]
},
{
"name": "Price",
"displayName": "Price",
"inputType": "Price",
"items": []
}
]
}
]
}
- The JSON response opens with the standard TCGPlayer.com API envelope: success, errors, & results.
- Next up are the various sort options available for search results
- The remainder of the response consists of the various filters that can be applied to searching this category. For Final Fantasy TCG, we have Name, Description, Set, Rarity, Cardtype, Element, Cost, Job, Category, & Price.
Dishing on the Details
A TCGPlayer.com User with a discerning eye may notice that even within a specific category, different product attributes are utilized in search parameters, search results, and product details. Due to the variety of products in the TCGPlayer catalog, there are no steadfast rules. Instead, the designation of these attributes is handled manually by the TCGPlayer Product Team.
The controls they utilize were recently updated in 2017, allowing code-less entry of new categories and including a robust data import system. The project was labeled "Dynamic Product Lines".
2. Constructing A Search Call
Our recreation is so close, I can smell it. We have our manifest. Now... which filters shall we search to summon the sufficient symbiote to our supremely sharpened Shun santoku?
- Name: Aerith Designated inputType:Text, this field will take a string input.
- Rarity: Rare, Legend, Hero, Promo Designated inputType:MultipleValues, this field has an established list of inputs, but the filter can receive multiple values from the list as input. Here we are avoiding using a common or starter card for our recreation. We're sparing no expense.
- Category: VII Designated inputType:SingleValue, this field has an established list of inputs. The filter is limited to one value only.
- sorting: Price: High to Low
- limit & offset: default values of 10 & 0, respectively
We have our search parameters. Now to grab our other tool from the box:
Endpoint: POST /catalog/categories/{categoryId}/search
Permissions Required:
Parameters: categoryId(required)
Headers: Authorization|{bearerToken} ; **Content-Type|application/jsonBody:
{
"sort": "string"
"limit": integer
"offset": integer
"filters": [ { "name": "", "values": [ "" ] } ]
}Returns a JSON list of productIds that match the search parameters provided in the API call's body. Parameters for a given category are designated by GET /catalog/categories/{categoryId}/search/manifest
We shall format our parameters to that of the endpoints. Our formatted call and the corresponding response are all as follows:
POST https://api.tcgplayer.com/v1.39.0/catalog/categories/24/search
Header: Authorization|{bearerToken} ; Content-Type|application/json
POST https://api.tcgplayer.com/v1.39.0/catalog/categories/24/search
Header: Authorization|{bearerToken} ; Content-Type|application/json
Body:
{
"sort": "MinPrice DESC",
"limit": 10,
"offset": 0,
"filters": [
{
"name": "ProductName",
"values": [ "Aerith"]
},
{
"name": "Rarity",
"values": [ "Rare", "Legend", "Hero", "Promo" ]
},
{
"name": "Category",
"values": [ "VII"]
}
]
}
{
"totalItems": 2,
"success": true,
"errors": [],
"results": [
137942,
132438
]
}
3. Processing Our Results
That result is JSON, right? Makes this article seem all Sound & Fury signifying nothing. However, we're not done yet. Those productIds have a wealth of knowledge attached to them within the catalog. If we had that caching set up, we could pull them up no problem. Instead, let's just leverage another TCGPlayer.com API Endpoint!
Endpoint: /catalog/products/{productIds}
Permissions Required:
Parameters: productIds(required); getExtendedFields
Headers: Authorization|{bearerToken}Detailed Product information will be returned for all Products as designated by the input comma separated values (CSV) list. Set getExtendedFields to "true" for additional product information as designated by its category.
GET https://api.tcgplayer.com/v1.39.0/catalog/products/137942,132438?getExtendedFields=true
Header: Authorization|{bearerToken}
“I always rip out the last page of a book, then it doesn't have to end. I hate endings.” - The Doctor
We have our product details!
Updated 9 months ago