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

tcgplayer

package module
v0.0.1 Latest Latest
Warning

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

Go to latest
Published: Sep 20, 2025 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 GetRequest for anything not wrapped yet.

Install

go get github.com/mtgban/go-tcgplayer

Quick start

package main

import (
    "context"
    "fmt"
    "time"

    "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, category int) (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)
  • Printings

    • ListCategoryPrintings(ctx context.Context, category int) ([]Printing, 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, if the envelope contains API errors, the call returns an error composed from those messages. Otherwise you receive the BaseResponse and can inspect Success/Errors.

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 -o tcg-dump ./cmd/tcg-dump

# Run (flags may vary if you moved the CLI)
TCGPLAYER_PUBLIC_KEY=... TCGPLAYER_PRIVATE_KEY=... ./tcg-dump -category 3 -threads 8 > pokemon.json

Common flags:

  • -category (int, required) — Category ID to dump
  • -threads (int) — worker concurrency for paging products

License

MIT

Documentation

Index

Constants

View Source
const (
	MaxItemsInResponse = 100
	MaxIdsInRequest    = 250
)
View Source
const (
	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"
)
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
)

All active categories on the platform

Variables

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:len(AllProductTypes)]

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 BaseResponse

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

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) ListCategoryPrintings

func (tcg *Client) ListCategoryPrintings(ctx context.Context, category int) ([]Printing, 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, category int) (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 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"`
}

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"`

	// 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"`
}

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 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