openapi: 3.0.3
info:
  title: Pokemon TCG API
  description: |
    A powerful and comprehensive API for accessing Pokemon Trading Card Game data.
    Get real-time prices, card information, product details, inventory management, and market trends.
    Prices from Cardmarket with country-specific pricing (DE, FR, ES, IT).
    
    **Authentication:** Pass your RapidAPI key in the `x-rapidapi-key` header.
    
    **Inventory API:** Requires separate Inventory API Key. Get yours at https://www.tcggo.com/api-key
  version: 1.0.0
  contact:
    name: TCGGO
    url: https://www.tcggo.com
servers:
  - url: https://pokemon-tcg-api.p.rapidapi.com
tags:
  - name: Cards
    description: Pokemon cards with pricing data
  - name: Products
    description: "Sealed products (booster boxes, ETBs, etc.)"
  - name: Episodes
    description: Expansions/sets
  - name: Artists
    description: Card artists
  - name: History Prices
    description: Historical pricing data
  - name: eBay Sold Prices
    description: "Graded card prices from eBay sold listings (PSA, BGS, CGC, SGC, ACE, TAG)"
  - name: Inventory
    description: Manage your card collection inventory
  - name: Health
    description: API health status
  - name: Deprecated
    description: Legacy endpoints kept for backward compatibility. Use the newer endpoints instead.
components:
  schemas:
    Paging:
      type: object
      properties:
        current: { type: integer, example: 1 }
        total: { type: integer, example: 10 }
        per_page: { type: integer, example: 20 }
    CardPrices:
      type: object
      properties:
        cardmarket:
          type: object
          properties:
            currency: { type: string, example: "EUR" }
            lowest_near_mint: { type: number, example: 184.58 }
            lowest_near_mint_EU_only: { type: number, example: 189.99 }
            lowest_near_mint_DE: { type: number, example: 169.99 }
            lowest_near_mint_DE_EU_only: { type: number, example: 175.00 }
            lowest_near_mint_FR: { type: number, example: 159.00 }
            lowest_near_mint_FR_EU_only: { type: number, example: 165.50 }
            lowest_near_mint_ES: { type: number, example: 134.95 }
            lowest_near_mint_ES_EU_only: { type: number, example: 139.95 }
            lowest_near_mint_IT: { type: number, example: 235.00 }
            lowest_near_mint_IT_EU_only: { type: number, example: 239.00 }
            graded:
              type: object
              description: "Cardmarket graded lowest prices grouped by company"
              properties:
                psa:
                  type: object
                  properties:
                    psa10: { type: number, example: 450.00 }
                    psa9: { type: number, example: 180.00 }
                    psa8: { type: number, example: 95.00 }
                bgs:
                  type: object
                  properties:
                    bgs10black: { type: number, example: 800.00 }
                    bgs10pristine: { type: number, example: 650.00 }
                    bgs10: { type: number, example: 500.00 }
                    bgs9: { type: number, example: 200.00 }
                    bgs8: { type: number, example: 100.00 }
                cgc:
                  type: object
                  properties:
                    cgc10: { type: number, example: 350.00 }
                    cgc9: { type: number, example: 150.00 }
                    cgc8: { type: number, example: 80.00 }
        ebay:
          type: object
          nullable: true
          description: "eBay sold graded prices (median from recent sold listings)"
          properties:
            currency: { type: string, example: "USD" }
            graded:
              type: object
              description: "Grouped by grading company (psa, bgs, cgc, sgc, ace, tag). Each company contains grade keys (10, 9, 8, 7) with median_price and sample_size."
              additionalProperties:
                type: object
                additionalProperties:
                  type: object
                  properties:
                    median_price: { type: number, example: 2941.00 }
                    sample_size: { type: integer, example: 5 }
              example:
                psa:
                  "10": { median_price: 2941.00, sample_size: 5 }
                  "9": { median_price: 1200.00, sample_size: 4 }
                bgs:
                  "10": { median_price: 3500.00, sample_size: 3 }
                  "9": { median_price: 1400.00, sample_size: 5 }
    Card:
      type: object
      properties:
        id: { type: integer, example: 3852 }
        name: { type: string, example: "Giratina VSTAR" }
        name_numbered: { type: string, example: "Giratina VSTAR GG69" }
        slug: { type: string, example: "giratina-vstar" }
        type: { type: string, example: "singles" }
        card_number: { type: string, example: "GG69" }
        hp: { type: integer, example: 280 }
        rarity: { type: string, example: "Rare Secret" }
        supertype: { type: string, example: "Pokemon" }
        tcgid: { type: string, example: "swsh12pt5gg-GG69" }
        cardmarket_id: { type: integer, example: 691949 }
        tcgplayer_id: { type: integer, nullable: true, example: 478100 }
        flavor_text: { type: string, nullable: true }
        abilities: { type: array, nullable: true }
        attacks: { type: array, nullable: true }
        prices: { $ref: '#/components/schemas/CardPrices' }
        episode:
          type: object
          properties:
            id: { type: integer, example: 21 }
            name: { type: string, example: "Crown Zenith" }
            slug: { type: string, example: "crown-zenith" }
            released_at: { type: string, example: "2023-01-20" }
            logo: { type: string, example: "https://images.tcggo.com/tcggo/storage/3641/crown-zenith-logo.png" }
            code: { type: string, example: "CRZ" }
        artist:
          type: object
          nullable: true
          properties:
            id: { type: integer, example: 434 }
            name: { type: string, example: "AKIRA EGAWA" }
            slug: { type: string, example: "akira-egawa" }
        image: { type: string, example: "https://images.tcggo.com/tcggo/storage/3871/giratina-vstar-crz-gg69-crown-zenith-pokemon.png" }
        tcggo_url: { type: string, example: "https://www.tcggo.com/pokemon/crown-zenith/giratina-vstar-gg69" }
        links:
          type: object
          properties:
            cardmarket: { type: string, example: "https://www.tcggo.com/external/cm/3852" }
            tcgplayer: { type: string, example: "https://www.tcggo.com/external/tcgplayer/3852" }
    Episode:
      type: object
      properties:
        id: { type: integer, example: 21 }
        name: { type: string, example: "Crown Zenith" }
        slug: { type: string, example: "crown-zenith" }
        released_at: { type: string, format: date, example: "2023-01-20" }
        logo: { type: string, example: "https://images.tcggo.com/tcggo/storage/123/crown-zenith-logo.png" }
        code: { type: string, example: "CRZ" }
        cards_total: { type: integer, example: 230 }
        cards_printed_total: { type: integer, example: 197 }
        prices:
          type: object
          properties:
            cardmarket:
              type: object
              properties:
                total: { type: number, example: 1250.50 }
                currency: { type: string, example: "EUR" }
            tcgplayer:
              type: object
              properties:
                total: { type: number, example: 1450.00 }
                currency: { type: string, example: "EUR" }
        game:
          type: object
          properties:
            name: { type: string, example: "Pokemon" }
            slug: { type: string, example: "pokemon" }
        series:
          type: object
          nullable: true
          properties:
            id: { type: integer, example: 5 }
            name: { type: string, example: "Sword & Shield" }
            slug: { type: string, example: "sword-shield" }
    Product:
      type: object
      properties:
        id: { type: integer, example: 20039 }
        name: { type: string, example: "Crown Zenith Elite Trainer Box" }
        slug: { type: string, example: "crown-zenith-elite-trainer-box" }
        cardmarket_id: { type: integer, example: 846733 }
        tcgplayer_id: { type: integer, nullable: true }
        prices:
          type: object
          properties:
            cardmarket:
              type: object
              properties:
                currency: { type: string, example: "EUR" }
                lowest: { type: number, example: 89.99 }
                lowest_EU_only: { type: number, example: 92.00 }
                lowest_DE: { type: number, example: 85.00 }
                lowest_DE_EU_only: { type: number, example: 87.50 }
                lowest_FR: { type: number, example: 92.50 }
                lowest_FR_EU_only: { type: number, example: 94.00 }
                lowest_ES: { type: number, example: 88.00 }
                lowest_ES_EU_only: { type: number, example: 90.00 }
                lowest_IT: { type: number, example: 90.00 }
                lowest_IT_EU_only: { type: number, example: 91.00 }
        episode:
          type: object
          properties:
            id: { type: integer, example: 21 }
            name: { type: string, example: "Crown Zenith" }
            slug: { type: string, example: "crown-zenith" }
            released_at: { type: string, format: date, example: "2023-01-20" }
            logo: { type: string, example: "https://images.tcggo.com/tcggo/storage/123/crown-zenith-logo.png" }
            code: { type: string, example: "CRZ" }
        image: { type: string, example: "https://images.tcggo.com/tcggo/storage/123/product.png" }
        tcggo_url: { type: string, example: "https://www.tcggo.com/pokemon/product/crown-zenith-elite-trainer-box" }
        links:
          type: object
          properties:
            cardmarket: { type: string, example: "https://www.tcggo.com/external/cm/20039" }
    Artist:
      type: object
      properties:
        id: { type: integer, example: 375 }
        name: { type: string, example: "Mitsuhiro Arita" }
        slug: { type: string, example: "mitsuhiro-arita" }
        cards_count: { type: integer, example: 850, description: "Number of cards illustrated by this artist" }
    HistoryPrice:
      type: object
      properties:
        date: { type: string, format: date, example: "2024-01-15" }
        cm_low: { type: number, example: 45.50, description: "Cardmarket lowest price" }
        tcg_player_market: { type: number, nullable: true, example: 52.00, description: "TCGPlayer market price" }
    EbaySoldPrice:
      type: object
      properties:
        company: { type: string, description: "Grading company (PSA, BGS, CGC, SGC, ACE, TAG)" }
        grade: { type: string, example: "10", description: "Grade value (e.g. 10, 9, 9.5)" }
        median_price: { type: number, example: 2941.00, description: "Median price in USD from last sold offers" }
        sample_size: { type: integer, example: 5, description: "Number of offers used to compute the median" }
    EbaySoldOffer:
      type: object
      properties:
        ebay_item_id: { type: string, example: "325987654321" }
        title: { type: string, example: "Giratina VSTAR GG69 Crown Zenith PSA 10 GEM MINT Pokemon Card" }
        price: { type: number, example: 3100.00, description: "Sold price in original currency" }
        currency: { type: string, example: "USD" }
        company: { type: string, description: "Grading company" }
        grade: { type: string, example: "10" }
        image_url: { type: string, nullable: true, example: "https://i.ebayimg.com/images/g/example/s-l1600.jpg" }
        url: { type: string, example: "https://www.ebay.com/itm/325987654321" }
        ended_at: { type: string, format: date-time, nullable: true, example: "2026-04-20T14:30:00+00:00" }
paths:
  # ==================== CARDS ====================
  /cards:
    get:
      summary: List Cards
      operationId: List Cards
      description: |
        Get a paginated list of Pokemon cards with powerful filtering options.
        
        **Quick Examples:**
        - Find by CardMarket ID: `/cards?cardmarket_id=362170`
        - Find by PokemonTCG ID: `/cards?tcgid=sv3-223`
        - Find by card number: `/cards?card_number=125` or `/cards?card_number=gg12`
        - **Powerful combo**: `/cards?name=Charizard&card_number=125`
      tags: [Cards]
      parameters:
        - name: search
          in: query
          description: "Search by name or card number (partial match)"
          schema: { type: string }
        - name: name
          in: query
          description: Filter by card name only. Great for combining with card_number
          schema: { type: string }
        - name: ids
          in: query
          description: "Batch filter by internal IDs (comma-separated, up to 20). Example: 24008,24009,24010"
          schema: { type: string }
        - name: tcgids
          in: query
          description: "Batch filter by PokemonTCG IDs (comma-separated, up to 20). Example: sv3-199,sv3-200"
          schema: { type: string }
        - name: cardmarket_ids
          in: query
          description: "Batch filter by CardMarket IDs (comma-separated, up to 20). Example: 362170,362171"
          schema: { type: string }
        - name: tcgid
          in: query
          description: "Exact match by PokemonTCG ID. Example: sv3-223"
          schema: { type: string }
        - name: cardmarket_id
          in: query
          description: "Exact match by CardMarket ID. Example: 362170"
          schema: { type: integer }
        - name: tcgplayer_id
          in: query
          description: "Exact match by TCGPlayer ID. Example: 632494"
          schema: { type: integer }
        - name: tcgplayer_ids
          in: query
          description: "Batch filter by TCGPlayer IDs (comma-separated, up to 20). Example: 632494,632495"
          schema: { type: string }
        - name: card_number
          in: query
          description: "Filter by card number (string|integer, e.g. 125, gg12, OP09-119)"
          schema: { type: string }
        - name: episode_id
          in: query
          description: Filter by expansion ID
          schema: { type: integer }
        - name: artist_id
          in: query
          description: Filter by artist ID
          schema: { type: integer }
        - name: sort
          in: query
          description: Sort order
          schema:
            type: string
            enum: [relevance, price_highest, price_lowest, card_number_highest, card_number_lowest, last_added, episode_newest, episode_oldest]
            default: relevance
        - name: per_page
          in: query
          description: "Items per page (up to 100 when filtering by episode_id)"
          schema: { type: integer, default: 20, maximum: 100 }
        - name: page
          in: query
          schema: { type: integer, default: 1 }
      responses:
        '200':
          description: List of cards
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items: { $ref: '#/components/schemas/Card' }
                  paging: { $ref: '#/components/schemas/Paging' }
                  results: { type: integer }
  /cards/{cardId}:
    get:
      summary: Get Card Detail
      operationId: Get Card Detail
      description: |
        Get detailed information for a specific card including abilities, attacks, and flavor text.
        
        **Response includes:** name, hp, rarity, supertype, tcgid, card_number, flavor_text, abilities, attacks, prices, episode, artist, and external links.
      tags: [Cards]
      parameters:
        - name: cardId
          in: path
          required: true
          description: "Card ID (e.g., 3852 for Giratina VSTAR GG69 from Crown Zenith)"
          schema: { type: integer }
          example: 3852
      responses:
        '200':
          description: Card details
          content:
            application/json:
              schema:
                type: object
                properties:
                  data: { $ref: '#/components/schemas/Card' }
  /episodes/{episodeId}/cards:
    get:
      summary: List Cards by Expansion
      operationId: List Cards by Expansion
      description: Get all cards from a specific expansion/episode.
      tags: [Cards, Episodes]
      parameters:
        - name: episodeId
          in: path
          required: true
          description: "Episode/Expansion ID (e.g., 21 for Crown Zenith)"
          schema: { type: integer }
          example: 21
        - name: sort
          in: query
          schema:
            type: string
            enum: [card_number_highest, card_number_lowest, price_highest, price_lowest, last_added]
            default: card_number_lowest
        - name: per_page
          in: query
          description: "Items per page (up to 100)"
          schema: { type: integer, default: 20, maximum: 100 }
        - name: page
          in: query
          schema: { type: integer, default: 1 }
      responses:
        '200':
          description: Cards in expansion
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items: { $ref: '#/components/schemas/Card' }
                  paging: { $ref: '#/components/schemas/Paging' }
                  results: { type: integer }
  # ==================== PRODUCTS ====================
  /products:
    get:
      summary: List Products
      operationId: List Products
      description: |
        Get a paginated list of sealed products (booster boxes, ETBs, bundles, etc).
        
        **Quick Example:** Find by CardMarket ID: `/products?cardmarket_id=357063`
      tags: [Products]
      parameters:
        - name: search
          in: query
          description: "Search by name (partial match). Example: evolving skies booster"
          schema: { type: string }
        - name: ids
          in: query
          description: "Batch filter by internal IDs (comma-separated, up to 20). Example: 20039,20040,20041"
          schema: { type: string }
        - name: cardmarket_ids
          in: query
          description: "Batch filter by CardMarket IDs (comma-separated, up to 20). Example: 846733,846734"
          schema: { type: string }
        - name: cardmarket_id
          in: query
          description: Exact match by CardMarket ID
          schema: { type: integer }
        - name: tcgplayer_id
          in: query
          description: "Exact match by TCGPlayer ID. Example: 632494"
          schema: { type: integer }
        - name: tcgplayer_ids
          in: query
          description: "Batch filter by TCGPlayer IDs (comma-separated, up to 20). Example: 632494,632495"
          schema: { type: string }
        - name: episode_id
          in: query
          description: Filter by expansion ID
          schema: { type: integer }
        - name: sort
          in: query
          schema:
            type: string
            enum: [relevance, price_highest, price_lowest, last_added, episode_newest, episode_oldest]
            default: relevance
        - name: page
          in: query
          schema: { type: integer, default: 1 }
      responses:
        '200':
          description: List of products
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items: { $ref: '#/components/schemas/Product' }
                  paging: { $ref: '#/components/schemas/Paging' }
                  results: { type: integer }
  /products/{productId}:
    get:
      summary: Get Product Detail
      operationId: Get Product Detail
      description: Get detailed information for a specific product.
      tags: [Products]
      parameters:
        - name: productId
          in: path
          required: true
          description: "Product ID (e.g., 20039 for Crown Zenith Elite Trainer Box)"
          schema: { type: integer }
          example: 20039
      responses:
        '200':
          description: Product details
          content:
            application/json:
              schema:
                type: object
                properties:
                  data: { $ref: '#/components/schemas/Product' }
  /episodes/{episodeId}/products:
    get:
      summary: List Products by Expansion
      operationId: List Products by Expansion
      description: Get all sealed products from a specific expansion/episode.
      tags: [Products, Episodes]
      parameters:
        - name: episodeId
          in: path
          required: true
          description: "Episode/Expansion ID (e.g., 21 for Crown Zenith)"
          schema: { type: integer }
          example: 21
        - name: sort
          in: query
          description: Sort order
          schema:
            type: string
            enum: [relevance, price_highest, price_lowest, last_added, episode_newest, episode_oldest]
            default: relevance
        - name: page
          in: query
          schema: { type: integer, default: 1 }
      responses:
        '200':
          description: Products in expansion
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items: { $ref: '#/components/schemas/Product' }
                  paging: { $ref: '#/components/schemas/Paging' }
                  results: { type: integer }
  # ==================== EPISODES ====================
  /episodes:
    get:
      summary: List Episodes (Expansions)
      operationId: List Episodes
      description: Get all Pokemon TCG expansions/sets.
      tags: [Episodes]
      parameters:
        - name: search
          in: query
          description: "Search by name (partial match). Example: Paldea Evolved"
          schema: { type: string }
        - name: page
          in: query
          schema: { type: integer, default: 1 }
      responses:
        '200':
          description: List of episodes
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items: { $ref: '#/components/schemas/Episode' }
                  paging: { $ref: '#/components/schemas/Paging' }
                  results: { type: integer }
  /episodes/{episodeId}:
    get:
      summary: Get Episode Detail
      operationId: Get Episode Detail
      description: Get detailed information for a specific expansion.
      tags: [Episodes]
      parameters:
        - name: episodeId
          in: path
          required: true
          description: "Episode/Expansion ID (e.g., 21 for Crown Zenith)"
          schema: { type: integer }
          example: 21
      responses:
        '200':
          description: Episode details
          content:
            application/json:
              schema:
                type: object
                properties:
                  data: { $ref: '#/components/schemas/Episode' }
  # ==================== ARTISTS ====================
  /artists:
    get:
      summary: List Artists
      operationId: List Artists
      description: Get all card artists.
      tags: [Artists]
      parameters:
        - name: search
          in: query
          description: "Search by name (partial match). Example: arita"
          schema: { type: string }
        - name: page
          in: query
          schema: { type: integer, default: 1 }
      responses:
        '200':
          description: List of artists
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items: { $ref: '#/components/schemas/Artist' }
                  paging: { $ref: '#/components/schemas/Paging' }
                  results: { type: integer }
  /artists/{artistId}:
    get:
      summary: Get Artist Detail
      operationId: Get Artist Detail
      description: Get artist information.
      tags: [Artists]
      parameters:
        - name: artistId
          in: path
          required: true
          description: "Artist ID (e.g., 375 for Mitsuhiro Arita)"
          schema: { type: integer }
          example: 375
      responses:
        '200':
          description: Artist details
          content:
            application/json:
              schema:
                type: object
                properties:
                  data: { $ref: '#/components/schemas/Artist' }
  /artists/{artistId}/cards:
    get:
      summary: List Cards by Artist
      operationId: List Cards by Artist
      description: Get all cards by a specific artist.
      tags: [Artists]
      parameters:
        - name: artistId
          in: path
          required: true
          description: "Artist ID (e.g., 375 for Mitsuhiro Arita)"
          schema: { type: integer }
          example: 375
        - name: sort
          in: query
          description: Sort order
          schema:
            type: string
            enum: [price_highest, price_lowest, card_number_highest, card_number_lowest, last_added, episode_newest, episode_oldest]
        - name: page
          in: query
          schema: { type: integer, default: 1 }
      responses:
        '200':
          description: Artist's cards
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items: { $ref: '#/components/schemas/Card' }
                  paging: { $ref: '#/components/schemas/Paging' }
                  results: { type: integer }
  # ==================== HISTORY PRICES ====================
  /history-prices:
    get:
      summary: Get Historical Prices
      operationId: Get Historical Prices
      description: |
        Get historical prices for a card or product by ID, Cardmarket ID, or TCG ID.
        Returns daily price data with Cardmarket Low and TCG Player Market prices.
        By default Cardmarket history includes EN/DE/FR/ES/IT (`cm_low`, `cm_low_de`, `cm_low_fr`, `cm_low_es`, `cm_low_it`).
        Use `lang` (`en|de|fr|es|it`) to return a single Cardmarket language as `cm_low`.
      tags: [History Prices]
      parameters:
        - name: id
          in: query
          description: "Internal item ID. Example: 24008"
          schema: { type: integer }
        - name: cardmarket_id
          in: query
          description: "Cardmarket product ID. Example: 362170"
          schema: { type: integer }
        - name: tcgid
          in: query
          description: "Pokemon TCG ID. Example: sv3-199"
          schema: { type: string }
        - name: date_from
          in: query
          description: "Start date (YYYY-MM-DD). Example: 2024-01-01"
          schema: { type: string, format: date }
        - name: date_to
          in: query
          description: "End date (YYYY-MM-DD). Example: 2024-12-31"
          schema: { type: string, format: date }
        - name: sort
          in: query
          description: Sort order for dates
          schema:
            type: string
            enum: [asc, desc]
            default: desc
        - name: lang
          in: query
          description: "Optional Cardmarket language filter. Supported: en, de, fr, es, it. When set, `cm_low` contains only selected language."
          schema:
            type: string
            enum: [en, de, fr, es, it]
        - name: page
          in: query
          schema: { type: integer, default: 1 }
      responses:
        '200':
          description: Price history grouped by date
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    description: "Price history grouped by date"
                  paging: { $ref: '#/components/schemas/Paging' }
                  results: { type: integer }
  # ==================== EBAY SOLD PRICES ====================
  /ebay-sold-prices:
    get:
      summary: Get eBay Sold Graded Prices (Median)
      operationId: Get eBay Sold Prices
      description: |
        Get median graded prices from recent eBay sold listings for a card.
        Each entry represents a grading company + grade combination (e.g. PSA 10, BGS 9)
        with the median price computed from the last sold offers.

        Identify the card using one of: `id`, `cardmarket_id`, or `tcgid`.
      tags: [eBay Sold Prices]
      parameters:
        - name: id
          in: query
          description: "Internal item ID"
          schema: { type: integer, example: 7291 }
        - name: cardmarket_id
          in: query
          description: "Cardmarket product ID"
          schema: { type: integer }
        - name: tcgid
          in: query
          description: "Pokemon TCG ID"
          schema: { type: string }
        - name: company
          in: query
          description: "Filter by grading company: PSA, BGS, CGC, SGC, ACE, TAG (optional)"
          schema: { type: string }
        - name: grade
          in: query
          description: "Filter by grade (optional)"
          schema: { type: string }
      responses:
        '200':
          description: Graded price medians
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items: { $ref: '#/components/schemas/EbaySoldPrice' }
                  item_id: { type: integer, example: 7291 }
                  results: { type: integer, example: 9 }
  /ebay-sold-offers:
    get:
      summary: List eBay Sold Offers
      operationId: List eBay Sold Offers
      description: |
        Get a paginated list of individual eBay sold listings (graded cards) for a card.
        Sorted by ended_at date (newest first). Optionally filter by grading company and/or grade.

        Identify the card using one of: `id`, `cardmarket_id`, or `tcgid`.
      tags: [eBay Sold Prices]
      parameters:
        - name: id
          in: query
          description: "Internal item ID"
          schema: { type: integer, example: 7291 }
        - name: cardmarket_id
          in: query
          description: "Cardmarket product ID"
          schema: { type: integer }
        - name: tcgid
          in: query
          description: "Pokemon TCG ID"
          schema: { type: string }
        - name: company
          in: query
          description: "Filter by grading company: PSA, BGS, CGC, SGC, ACE, TAG (optional)"
          schema: { type: string }
        - name: grade
          in: query
          description: "Filter by grade (optional)"
          schema: { type: string }
        - name: per_page
          in: query
          description: "Items per page (max 100)"
          schema: { type: integer, default: 20, maximum: 100 }
        - name: page
          in: query
          schema: { type: integer, default: 1 }
      responses:
        '200':
          description: Paginated list of eBay sold offers
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items: { $ref: '#/components/schemas/EbaySoldOffer' }
                  paging: { $ref: '#/components/schemas/Paging' }
                  results: { type: integer }
  # ==================== INVENTORY ====================
  /inventories:
    get:
      summary: List Inventories
      operationId: List Inventories
      description: |
        Get a paginated list of your inventories with financial summary.
        
        **Authentication:** Requires Inventory API Key (pass in `rapidapi_tcggo_key` parameter)
      tags: [Inventory]
      parameters:
        - name: rapidapi_tcggo_key
          in: query
          required: true
          description: "Your Inventory API Key from https://www.tcggo.com/api-key"
          schema: { type: string }
        - name: page
          in: query
          schema: { type: integer, default: 1 }
      responses:
        '200':
          description: List of inventories
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id: { type: integer }
                        name: { type: string }
                        is_public: { type: boolean }
                        is_primary: { type: boolean }
                        total_items: { type: integer }
                        total_value: { type: number }
                        actual_value: { type: number }
                        profit_loss: { type: number }
                        profit_loss_percentage: { type: number }
                  paging: { $ref: '#/components/schemas/Paging' }
                  results: { type: integer }
  /inventories/{id}:
    get:
      summary: Get Inventory Detail
      operationId: Get Inventory Detail
      description: Get detailed information for a specific inventory with paginated items.
      tags: [Inventory]
      parameters:
        - name: id
          in: path
          required: true
          schema: { type: integer }
        - name: rapidapi_tcggo_key
          in: query
          required: true
          schema: { type: string }
        - name: page
          in: query
          schema: { type: integer, default: 1 }
      responses:
        '200':
          description: Inventory details with items
  /inventories/{id}/stats:
    get:
      summary: Get Inventory Stats
      operationId: Get Inventory Stats
      description: Get comprehensive statistics and chart data for the inventory.
      tags: [Inventory]
      parameters:
        - name: id
          in: path
          required: true
          schema: { type: integer }
        - name: rapidapi_tcggo_key
          in: query
          required: true
          schema: { type: string }
        - name: days
          in: query
          description: Number of days for chart data
          schema: { type: integer, default: 30 }
      responses:
        '200':
          description: Inventory statistics
  /inventories/{id}/items:
    post:
      summary: Add Item to Inventory
      operationId: Add Item to Inventory
      description: Add a card or product to your inventory.
      tags: [Inventory]
      parameters:
        - name: id
          in: path
          required: true
          schema: { type: integer }
        - name: rapidapi_tcggo_key
          in: query
          required: true
          schema: { type: string }
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [item_id]
              properties:
                item_id: { type: integer, description: "Card or product ID", example: 24008 }
                count: { type: integer, description: "Quantity (default 1)", example: 2 }
                price: { type: number, description: "Purchase price per unit", example: 12.50 }
                language: { type: string, description: "Language: en, de, fr, es, it", example: "en" }
      responses:
        '200':
          description: Item added
          content:
            application/json:
              schema:
                type: object
                properties:
                  message: { type: string, example: "Item added successfully" }
  /inventories/{inventoryId}/items/{itemId}:
    put:
      summary: Update Inventory Item
      operationId: Update Inventory Item
      description: Update quantity, price, or language of an inventory item.
      tags: [Inventory]
      parameters:
        - name: inventoryId
          in: path
          required: true
          schema: { type: integer }
        - name: itemId
          in: path
          required: true
          description: "Inventory item entry ID (not card ID)"
          schema: { type: integer }
        - name: rapidapi_tcggo_key
          in: query
          required: true
          schema: { type: string }
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [count, language]
              properties:
                count: { type: integer, example: 5 }
                price: { type: number, example: 20.00 }
                language: { type: string, example: "en" }
      responses:
        '200':
          description: Item updated
    delete:
      summary: Remove Item from Inventory
      operationId: Remove Item from Inventory
      description: Remove an item entry from the inventory.
      tags: [Inventory]
      parameters:
        - name: inventoryId
          in: path
          required: true
          schema: { type: integer }
        - name: itemId
          in: path
          required: true
          schema: { type: integer }
        - name: rapidapi_tcggo_key
          in: query
          required: true
          schema: { type: string }
      responses:
        '200':
          description: Item removed
  # ==================== DEPRECATED ====================
  /cards/search:
    get:
      summary: Search Cards (Deprecated)
      operationId: Search Cards
      deprecated: true
      description: |
        **Deprecated:** Use `/cards?search=query` instead.
        
        Search for cards by name.
      tags: [Deprecated]
      parameters:
        - name: ids
          in: query
          description: "Batch filter by internal IDs (comma-separated, up to 20). Example: 24008,24009,24010"
          schema: { type: string }
        - name: tcgids
          in: query
          description: "Batch filter by PokemonTCG IDs (comma-separated, up to 20). Example: sv3-199,sv3-200"
          schema: { type: string }
        - name: cardmarket_ids
          in: query
          description: "Batch filter by CardMarket IDs (comma-separated, up to 20). Example: 362170,362171"
          schema: { type: string }
        - name: tcgplayer_ids
          in: query
          description: "Batch filter by TCGPlayer IDs (comma-separated, up to 20). Example: 632494,632495"
          schema: { type: string }
        - name: search
          in: query
          required: true
          description: Search query
          schema: { type: string }
          example: giratina
        - name: sort
          in: query
          description: Sort order
          schema:
            type: string
            enum: [relevance, price_highest, price_lowest, card_number_highest, card_number_lowest, last_added, episode_newest, episode_oldest]
            default: relevance
        - name: page
          in: query
          schema: { type: integer, default: 1 }
      responses:
        '200':
          description: Search results
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items: { $ref: '#/components/schemas/Card' }
                  paging: { $ref: '#/components/schemas/Paging' }
  /cards/{cardId}/history-prices:
    get:
      summary: Card History Prices (Deprecated)
      operationId: Card History Prices
      deprecated: true
      description: |
        **Deprecated:** Use `/history-prices?id={cardId}` instead.
        
        Get historical prices for a specific card.
      tags: [Deprecated]
      parameters:
        - name: cardId
          in: path
          required: true
          schema: { type: integer }
        - name: page
          in: query
          schema: { type: integer, default: 1 }
        - name: lang
          in: query
          description: "Optional Cardmarket language filter. Supported: en, de, fr, es, it. When set, `cm_low` contains only selected language."
          schema:
            type: string
            enum: [en, de, fr, es, it]
      responses:
        '200':
          description: Price history
          content:
            application/json:
              schema:
                type: object
                properties:
                  data: { type: object }
                  paging: { $ref: '#/components/schemas/Paging' }
  /products/{productId}/history-prices:
    get:
      summary: Product History Prices (Deprecated)
      operationId: Product History Prices
      deprecated: true
      description: |
        **Deprecated:** Use `/history-prices?id={productId}` instead.
        
        Get historical prices for a specific product.
      tags: [Deprecated]
      parameters:
        - name: productId
          in: path
          required: true
          schema: { type: integer }
        - name: page
          in: query
          schema: { type: integer, default: 1 }
        - name: lang
          in: query
          description: "Optional Cardmarket language filter. Supported: en, de, fr, es, it. When set, `cm_low` contains only selected language."
          schema:
            type: string
            enum: [en, de, fr, es, it]
      responses:
        '200':
          description: Price history
          content:
            application/json:
              schema:
                type: object
                properties:
                  data: { type: object }
                  paging: { $ref: '#/components/schemas/Paging' }
  /products/search:
    get:
      summary: Search Products (Deprecated)
      operationId: Search Products
      deprecated: true
      description: |
        **Deprecated:** Use `/products?search=query` instead.
        
        Search for products by name.
      tags: [Deprecated]
      parameters:
        - name: ids
          in: query
          description: "Batch filter by internal IDs (comma-separated, up to 20). Example: 20039,20040,20041"
          schema: { type: string }
        - name: cardmarket_ids
          in: query
          description: "Batch filter by CardMarket IDs (comma-separated, up to 20). Example: 846733,846734"
          schema: { type: string }
        - name: tcgplayer_ids
          in: query
          description: "Batch filter by TCGPlayer IDs (comma-separated, up to 20). Example: 632494,632495"
          schema: { type: string }
        - name: search
          in: query
          required: true
          description: Search query
          schema: { type: string }
          example: elite trainer box
        - name: sort
          in: query
          description: Sort order
          schema:
            type: string
            enum: [relevance, price_highest, price_lowest, last_added, episode_newest, episode_oldest]
            default: relevance
        - name: page
          in: query
          schema: { type: integer, default: 1 }
      responses:
        '200':
          description: Search results
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items: { $ref: '#/components/schemas/Product' }
                  paging: { $ref: '#/components/schemas/Paging' }
  /episodes/search:
    get:
      summary: Search Episodes (Deprecated)
      operationId: Search Episodes
      deprecated: true
      description: |
        **Deprecated:** Use `/episodes?search=query` instead.
        
        Search for episodes/expansions by name.
      tags: [Deprecated]
      parameters:
        - name: search
          in: query
          required: true
          description: Search query
          schema: { type: string }
          example: crown zenith
        - name: page
          in: query
          schema: { type: integer, default: 1 }
      responses:
        '200':
          description: Search results
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items: { $ref: '#/components/schemas/Episode' }
                  paging: { $ref: '#/components/schemas/Paging' }
  /artists/search:
    get:
      summary: Search Artists (Deprecated)
      operationId: Search Artists
      deprecated: true
      description: |
        **Deprecated:** Use `/artists?search=query` instead.
        
        Search for artists by name.
      tags: [Deprecated]
      parameters:
        - name: search
          in: query
          required: true
          description: Search query
          schema: { type: string }
          example: arita
        - name: page
          in: query
          schema: { type: integer, default: 1 }
      responses:
        '200':
          description: Search results
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items: { $ref: '#/components/schemas/Artist' }
                  paging: { $ref: '#/components/schemas/Paging' }
  # ==================== HEALTH ====================
  /healthcheck:
    get:
      summary: Health Check
      operationId: Health Check
      description: Check API availability.
      tags: [Health]
      responses:
        '200':
          description: API is healthy
          content:
            application/json:
              schema:
                type: object
                properties:
                  status: { type: string, example: ok }
                  timestamp: { type: string, format: date-time }
