Help us shape the future of Go! Take the 2026 Go Developer Survey

tcgplayer

package module
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 13, 2026 License: MIT Imports: 15 Imported by: 2

README

go-tcgplayer

A small, practical Go client for the TCGplayer API (catalog & pricing). It handles OAuth2 client-credentials, automatic token refresh, rate limiting, and resilient HTTP via retryablehttp.

This repo also includes a tiny CLI to dump category groups and products.


Features

  • Easy auth - fetches access_token using client-credentials and refreshes it before expiry.
  • Rate limiting - token-bucket guard around every request (defaults suitable for TCGplayer).
  • Resilient HTTP - built on hashicorp/go-retryablehttp.
  • Thread-safe - safe to use from multiple goroutines.
  • Tiny surface area - helpers for common catalog & pricing flows, plus a low-level Get for anything not wrapped yet.

Install

go get github.com/mtgban/go-tcgplayer

Quick start

package main

import (
    "context"
    "fmt"

    "github.com/mtgban/go-tcgplayer"
)

func main() {
    c, err := tcgplayer.NewClient("<PUBLIC_KEY>", "<PRIVATE_KEY>")
    if err != nil {
        // <handle err>
    }

    rows, err := c.GetMarketPricesByProducts(context.TODO(), []int{12345, 67890})
    if err != nil {
        // <handle err>
    }
    fmt.Println("retrieved rows:", len(rows))
}

Authentication

NewClient(publicKey, privateKey) wires a custom http.RoundTripper that:

  1. waits on a rate limiter,
  2. ensures a valid bearer token (refreshing if missing/near expiry),
  3. sets Authorization: Bearer <token> on each request.

Tokens are fetched from TCGplayer's /token endpoint using grant_type=client_credentials. Token acquisition is synchronized so bursts don't stampede the token endpoint.


Catalog helpers

  • Categories

    • GetCategoriesDetails(ctx context.Context, ids []int) ([]Category, error)
    • TotalCategories(ctx context.Context) (int, error)
  • Groups

    • ListAllCategoryGroups(ctx context.Context, category, offset int) ([]Group, error)
    • TotalGroups(ctx context.Context, category int) (int, error)
  • Products

    • GetProductsDetails(ctx context.Context, ids []int, includeSkus bool) ([]Product, error)
    • ListAllProducts(ctx context.Context, category int, productTypes []string, includeSkus bool, offset int) ([]Product, error)
    • ListProductSKUs(ctx context.Context, productId int) ([]SKU, error)
  • Category metadata (decodes the ids referenced by SKUs)

    • ListCategoryPrintings(ctx context.Context, category int) ([]Printing, error)
    • ListCategoryConditions(ctx context.Context, category int) ([]Condition, error)
    • ListCategoryLanguages(ctx context.Context, category int) ([]Language, error)
    • ListCategoryRarities(ctx context.Context, category int) ([]Rarity, error)
Product type filters
  • AllProductTypes - everything (Cards + sealed)
  • ProductTypesSingles - only Cards
  • ProductTypesSealed - sealed products (boxes, packs, etc.)

Pricing helpers

  • GetMarketPricesByProducts(ctx, productIds []int) ([]ProductPriceSet, error)
  • GetMarketPricesBySKUs(ctx, skuIds []int) ([]SKUPriceSet, error)

Each returns rows with the latest market pricing for the given IDs.


Pagination & limits

  • Offset + limit paging. Use MaxItemsInResponse (100) as the page size and iterate offsets: 0, 100, 200, ....
  • Batched IDs. Endpoints accept up to MaxIdsInRequest (250) IDs at a time. The client checks this and errors early if you exceed it.

Error handling

Low-level Get() returns a BaseResponse envelope. High-level helpers decode BaseResponse.Results into typed slices.

  • On malformed JSON, you get a Go error (with the raw body snippet).
  • On non-2xx responses, the call returns an error: composed from the envelope's API errors when present, otherwise from the HTTP status and raw body.

CLI

A simple CLI is included to dump category metadata and all products for a given category. It demonstrates offsets, batching, and concurrency.

# Build
go build ./cmd/tcgdumper

# Run
TCGPLAYER_PUBLIC_KEY=... TCGPLAYER_PRIVATE_KEY=... ./tcgdumper -category 3 -thread 8 > pokemon.json

Flags:

  • -category (int, required) - Category ID to dump
  • -thread (int, default 8) - worker concurrency for paging products
  • -pub / -pri (string) - TCGplayer public/private keys; fall back to the TCGPLAYER_PUBLIC_KEY / TCGPLAYER_PRIVATE_KEY environment variables
  • -p / -pretty - indent the JSON output (default is a single line)

License

MIT

Documentation

Index

Constants

View Source
const (
	MaxItemsInResponse = 100
	MaxIDsInRequest    = 250
)
View Source
const (
	CategoryMagic = iota + 1
	CategoryYuGiOh
	CategoryPokemon
	CategoryAxisAllies

	CategoryDDMiniatures
	CategoryEpic
	CategoryHeroclix
	CategoryMonsterpocalypse
	CategoryRedakai
	CategoryStarWarsMiniatures
	CategoryWorldOfWarcraftMiniatures
	CategoryWoW
	CategorySupplies
	CategoryOrganizersStores
	CategoryChronoClashSystem
	CategoryForceOfWill
	CategoryDiceMasters
	CategoryFutureCardBuddyFight
	CategoryWeissSchwarz

	CategoryTCGplayer
	CategoryDragonBallZ
	CategoryFinalFantasy
	CategoryUniVersus
	CategoryStarWarsDestiny
	CategoryDragonBallSuper
	CategoryDragoborne
	CategoryFunko
	CategoryMetaX
	CategoryCardSleeves
	CategoryDeckBoxes
	CategoryCardStorageTins
	CategoryLifeCounters
	CategoryPlaymats
	CategoryZombieWorldOrder
	CategoryTheCasterChronicles
	CategoryMyLittlePony
	CategoryWarhammerBooks
	CategoryWarhammerBigBoxGames
	CategoryWarhammerBoxSets
	CategoryWarhammerClampacks
	CategoryCitadelPaints
	CategoryCitadelTools
	CategoryWarhammerGameAccessories
	CategoryBooks
	CategoryExodus
	CategoryLightseekers
	CategoryProtectivePages
	CategoryStorageAlbums
	CategoryCollectibleStorage
	CategorySupplyBundles
	CategoryMunchkin
	CategoryWarhammerAgeOfSigmarChampions
	CategoryArchitect
	CategoryBulkLots
	CategoryTransformers
	CategoryBakugan
	CategoryKeyForge
	CategoryCardfightVanguard
	CategoryArgentSaga
	CategoryFleshAndBlood
	CategoryDigimon
	CategoryAlternateSouls
	CategoryGateRuler
	CategoryMetaZoo
	CategoryWIXOSS
	CategoryOnePiece
	CategoryMarvelComics
	CategoryDCComics
	CategoryLorcana
	CategoryBattleSpiritsSaga
	CategoryShadowverseEvolve
	CategoryGrandArchive
	CategoryAkora
	CategoryKryptik
	CategorySorceryContestedRealm
	CategoryAlphaClash
	CategoryStarWarsUnlimited
	CategoryDragonBallSuperFusionWorld
	CategoryUnionArena
	CategoryTCGplayerSupplies
	CategoryElestrals
	CategoryNeopetsBattledome
	CategoryPokemonJapan
	CategoryGundam
	CategoryHololive
	CategoryGodzilla
	CategoryRiftbound
	CategoryCookieRunBraverse
)

All active categories on the platform

Variables

View Source
var (
	TCGAPITokenURL = "https://api.tcgplayer.com/token"

	TCGAPICatalogCategoriesURL = "https://api.tcgplayer.com/" + tcgApiVersion + "/catalog/categories"
	TCGAPICatalogProductsURL   = "https://api.tcgplayer.com/" + tcgApiVersion + "/catalog/products"
	TCGAPICatalogGroupsURL     = "https://api.tcgplayer.com/" + tcgApiVersion + "/catalog/groups"

	TCGAPIPricingProductURL = "https://api.tcgplayer.com/" + tcgApiVersion + "/pricing/product"
	TCGAPIPricingSkuURL     = "https://api.tcgplayer.com/" + tcgApiVersion + "/pricing/sku"
)

Endpoint URLs, overridable for testing

View Source
var AllProductTypes = []string{
	"Cards",
	"Booster Box",
	"Booster Pack",
	"Sealed Products",
	"Intro Pack",
	"Fat Pack",
	"Box Sets",
	"Precon/Event Decks",
	"Magic Deck Pack",
	"Magic Booster Box Case",
	"All 5 Intro Packs",
	"Intro Pack Display",
	"3x Magic Booster Packs",
	"Booster Battle Pack",
}

List of all possible product types

View Source
var ProductTypesSealed = AllProductTypes[1:]

List of all product types containing Sealed Products

View Source
var ProductTypesSingles = []string{AllProductTypes[0]}

List of all product types containing Singles

Functions

This section is empty.

Types

type APIError added in v0.1.0

type APIError struct {
	StatusCode int
	Messages   []string
}

APIError is a request the API answered with an error envelope, keeping the http status the message arrived under

func (*APIError) Error added in v0.1.0

func (e *APIError) Error() string

type BaseResponse

type BaseResponse struct {
	TotalItems int             `json:"totalItems"`
	Success    bool            `json:"success"`
	Errors     []string        `json:"errors"`
	Results    json.RawMessage `json:"results"`
}

type CatalogDump added in v0.1.0

type CatalogDump struct {
	Category   Category    `json:"category"`
	Conditions []Condition `json:"conditions"`
	Languages  []Language  `json:"languages"`
	Printings  []Printing  `json:"printings"`
	Rarities   []Rarity    `json:"rarities"`
	Groups     []Group     `json:"groups"`
	Products   []Product   `json:"products"`
}

CatalogDump is the envelope cmd/tcgdumper writes for a category. Naming it here keeps the program that writes a dump and the programs that read one on a single definition of the format, rather than each carrying its own.

func (*CatalogDump) PrintingNames added in v0.1.0

func (d *CatalogDump) PrintingNames() map[int][]string

PrintingNames maps each product to the distinct printing names its skus carry, ordered as the dump lists the category's printings. A printing the dump does not list for a product is one that product is not sold in.

type Category

type Category struct {
	CategoryID        int    `json:"categoryId"`
	Name              string `json:"name"`
	ModifiedOn        string `json:"modifiedOn"`
	DisplayName       string `json:"displayName"`
	SeoCategoryName   string `json:"seoCategoryName"`
	SealedLabel       string `json:"sealedLabel"`
	NonSealedLabel    string `json:"nonSealedLabel"`
	ConditionGuideURL string `json:"conditionGuideUrl"`
	IsScannable       bool   `json:"isScannable"`
	Popularity        int    `json:"popularity"`
}

type Client

type Client struct {
	// contains filtered or unexported fields
}

func NewClient

func NewClient(publicKey, privateKey string) (*Client, error)

func (*Client) Get

func (tcg *Client) Get(ctx context.Context, link string) (*BaseResponse, error)

Perform an authenticated GET request and partially parse the response

func (*Client) GetCategoriesDetails

func (tcg *Client) GetCategoriesDetails(ctx context.Context, categoryIDs []int) ([]Category, error)

func (*Client) GetMarketPricesByProducts

func (tcg *Client) GetMarketPricesByProducts(ctx context.Context, productIDs []int) ([]ProductPriceSet, error)

func (*Client) GetMarketPricesBySKUs

func (tcg *Client) GetMarketPricesBySKUs(ctx context.Context, skuIDs []int) ([]SKUPriceSet, error)

func (*Client) GetProductsDetails

func (tcg *Client) GetProductsDetails(ctx context.Context, productIDs []int, includeSkus bool) ([]Product, error)

func (*Client) ListAllCategoryGroups

func (tcg *Client) ListAllCategoryGroups(ctx context.Context, category, offset int) ([]Group, error)

func (*Client) ListAllProducts

func (tcg *Client) ListAllProducts(ctx context.Context, category int, productTypes []string, includeSkus bool, offset int) ([]Product, error)

func (*Client) ListCategoryConditions added in v0.0.3

func (tcg *Client) ListCategoryConditions(ctx context.Context, category int) ([]Condition, error)

func (*Client) ListCategoryLanguages added in v0.0.3

func (tcg *Client) ListCategoryLanguages(ctx context.Context, category int) ([]Language, error)

func (*Client) ListCategoryPrintings

func (tcg *Client) ListCategoryPrintings(ctx context.Context, category int) ([]Printing, error)

func (*Client) ListCategoryRarities added in v0.0.3

func (tcg *Client) ListCategoryRarities(ctx context.Context, category int) ([]Rarity, error)

func (*Client) ListProductSKUs

func (tcg *Client) ListProductSKUs(ctx context.Context, productId int) ([]SKU, error)

func (*Client) TotalCategories

func (tcg *Client) TotalCategories(ctx context.Context) (int, error)

func (*Client) TotalGroups

func (tcg *Client) TotalGroups(ctx context.Context, category int) (int, error)

func (*Client) TotalProducts

func (tcg *Client) TotalProducts(ctx context.Context, category int, productTypes []string) (int, error)

type Condition added in v0.0.3

type Condition struct {
	ConditionID  int    `json:"conditionId"`
	Name         string `json:"name"`
	Abbreviation string `json:"abbreviation"`
	DisplayOrder int    `json:"displayOrder"`
}

type Group

type Group struct {
	GroupID      int    `json:"groupId"`
	Name         string `json:"name"`
	Abbreviation string `json:"abbreviation"`
	Supplemental bool   `json:"supplemental"`
	PublishedOn  string `json:"publishedOn"`
	ModifiedOn   string `json:"modifiedOn"`
	CategoryID   int    `json:"categoryId"`
}

func (Group) ReleaseDate added in v0.1.0

func (g Group) ReleaseDate() string

ReleaseDate is the group's publish date without the time of day.

type Language added in v0.0.3

type Language struct {
	LanguageID   int    `json:"languageId"`
	Name         string `json:"name"`
	Abbreviation string `json:"abbr"`
}

type Printing

type Printing struct {
	PrintingID   int    `json:"printingId"`
	Name         string `json:"name"`
	DisplayOrder int    `json:"displayOrder"`
	ModifiedOn   string `json:"modifiedOn"`
}

type Product

type Product struct {
	ProductID  int    `json:"productId"`
	Name       string `json:"name"`
	CleanName  string `json:"cleanName"`
	ImageURL   string `json:"imageUrl"`
	GroupID    int    `json:"groupId"`
	URL        string `json:"url"`
	ModifiedOn string `json:"modifiedOn"`

	// Never returned by the API, which does not report the product type a
	// product is filed under; tcgdumper stamps the type it fetched the
	// product by, so it is present in catalog dumps only
	ProductType string `json:"productType,omitempty"`

	// Only available for catalog API calls
	Skus []SKU `json:"skus,omitempty"`
	// Only available for catalog API calls
	ExtendedData []struct {
		Name        string `json:"name"`
		DisplayName string `json:"displayName"`
		Value       string `json:"value"`
	} `json:"extendedData,omitempty"`
}

func (Product) Extended added in v0.1.0

func (p Product) Extended(name string) string

Extended reads the extendedData entry a product carries under name, or "" when it carries none. The catalog files a card's collector number, rarity and the rest there rather than as fields of their own.

type ProductPriceSet

type ProductPriceSet struct {
	ProductID      int     `json:"productId"`
	LowPrice       float64 `json:"lowPrice"`
	MarketPrice    float64 `json:"marketPrice"`
	MidPrice       float64 `json:"midPrice"`
	DirectLowPrice float64 `json:"directLowPrice"`
	SubTypeName    string  `json:"subTypeName"`
}

type Rarity added in v0.0.3

type Rarity struct {
	RarityID    int    `json:"rarityId"`
	DisplayText string `json:"displayText"`
	DbValue     string `json:"dbValue"`
}

type SKU

type SKU struct {
	SKUID       int `json:"skuId"`
	ProductID   int `json:"productId"`
	LanguageID  int `json:"languageId"`
	PrintingID  int `json:"printingId"`
	ConditionID int `json:"conditionId"`
}

type SKUPriceSet

type SKUPriceSet struct {
	SKUID              int     `json:"skuId"`
	LowPrice           float64 `json:"lowPrice"`
	LowestShipping     float64 `json:"lowestShipping"`
	LowestListingPrice float64 `json:"lowestListingPrice"`
	MarketPrice        float64 `json:"marketPrice"`
	DirectLowPrice     float64 `json:"directLowPrice"`
}

Directories

Path Synopsis
cmd
tcgdumper command

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL