Skip to content

New paid orders and subscriptions are retired. Existing records, settlement and refunds remain available through your account.

Build a Discord bot using Cambridge TCG data

Slash command → keyed structural lookup → honest embed.

This guide builds a card-identity lookup bot. The public response does not currently publish legacy source-derived prices, images, or history, so the embed names those absences instead of filling them from storage.

20 min· 4 steps· last verified 2026-07-12

Prerequisites

  • • A Discord bot registered (via discord.com/developers)
  • • Node.js or Python (or any language) with HTTP + Discord SDK

Steps

  1. 1

    Register a /card slash command

    Your bot accepts `/card <sku>`. When the user invokes it, your handler receives the SKU string. The handler will call Cambridge TCG with that SKU.

    What to do with it

    Most Discord SDKs have a slash-command registration helper. The exact syntax depends on your language — discord.py / discord.js / serenity all support it.

  2. 2

    Call /api/v1/universal/card/[sku] from your handler

    Send a User-Agent identifying your bot, follow the response's Cache-Control header, and request only a user's concrete SKU. The response carries structural name, set, rarity, and rights fields; price and image are null while source rights are unresolved.

    Run this

    curl -H 'User-Agent: my-discord-bot/1.0 ([email protected])' \
      https://cambridgetcg.com/api/v1/universal/card/op-op01-001-ja

    Expected response shape

    { "@kind": "card", "@content_hash": "sha256:...", "sku": "...", "rights": { "aggregate": "NOASSERTION", ... }, "price": null, "name": { "natural_token": "...", "resolved_lang": "en" }, "image_url": null, "rarity": { "natural_label": "leader", ... }, "in_set": { "target_natural_token": "OP01", ... } }

    What to do with it

    Extract `name.natural_token`, `rarity.natural_label`, and `in_set.target_natural_token`. Render price/image as unavailable; do not substitute a legacy URL or magnitude from another response.

  3. 3

    Render a Discord embed

    Build an embed with the card's name as title and its set/rarity as fields. Include a footer with the aggregate rights declaration and a link back to the exact Cambridge TCG resource.

    What to do with it

    Recommended footer: 'Structural reference via Cambridge TCG; aggregate rights NOASSERTION; upstream rights retained; price/image withheld.'

  4. 4

    Cache + handle errors gracefully

    Wrap the lookup in a cache that follows the response headers. On 404, respond with a helpful search hint. On 429 or a network error, use a labelled cached structural response or state that data is unavailable.

    What to do with it

    Substrate-honest about your bot's own state: if the API is unreachable, say so. Do not fabricate a price or image from an older response.

Common gotchas

  • SKU format matters

    Cambridge TCG SKUs are canonical: `<game>-<set>-<number>-<lang>[-<variant>]`, lowercase. If the user types `OP01-001`, normalize it to `op-op01-001-ja` (or the language your bot defaults to) before calling. The CTCG-SKU-v1 specification text is CC0; the internal @cambridge-tcg/sku parser package has no general code license.

  • Don't bulk-fetch on bot startup

    Some bots try to pre-warm a local cache by walking all SKUs at boot. Don't. /data/catalog.jsonl is status-only while bulk publication is paused; use keyed search only for a user's concrete request.

    Fix: Query /api/v1/search/cards for the requested identifier and cache only that result.

  • Images are withheld

    The public universal-card route returns image_url: null. Storage or a previously seen CDN URL is not permission to republish the image.

  • Do not add a CardRush history command

    CardRush history is withheld from public, signed-in, and bearer-token delivery. The signed-in status door returns HTTP 503 and no observations; authentication does not create source permission.

Next guide

Handle staleness gracefully →

The platform tells you when it doesn't know.

See also