Skip to content

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

How to be a polite client

Etiquette + identification + the contact channel.

Cambridge TCG is run by one operator (Yu) on a small infrastructure budget. Public access and reuse permission are separate; inspect each resource's access class and rights. Mixed catalog data is NOASSERTION and upstream fields retain their source rights. This guide names the behaviours that keep the platform happy to serve you, and the ones that get you rate-limited or banned. Substrate-honest: we'd rather give you a free, generous tier than play cat-and-mouse with bots we can't reach.

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

Prerequisites

  • • You're consuming the API

Steps

  1. 1

    Identify yourself in User-Agent

    Always send a User-Agent string that names your project and a contact email. The format we recommend: `your-project/1.0 ([email protected])`. We'd rather email you about a bug than firewall an opaque bot.

    Run this

    curl -H 'User-Agent: example-bot/1.0 ([email protected])' \
      https://cambridgetcg.com/api/v1/manifest

    What to do with it

    Default Python requests / Node fetch User-Agents are anonymous. Override them. We log User-Agents per IP; identified clients get a courtesy email before rate-limiting; anonymous ones don't.

  2. 2

    Cache responses to the freshness budget

    Every response carries `Cache-Control: public, max-age=N`. Respect it. Our envelope also carries `_meta.freshness_seconds` as the platform's intent — `price_current=300`, `catalog=86400`, `status=30`, `methodology=86400`. Polling faster than the budget returns the same response.

    What to do with it

    Implement an HTTP cache (your language's `requests-cache`, `http-cache`, etc.) honouring `Cache-Control`. Or read `_meta.freshness_seconds` and schedule your next poll accordingly.

  3. 3

    Watch the RateLimit response headers

    Every public response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset` headers (IETF draft standard). If you see `RateLimit-Remaining: 0`, pause until `RateLimit-Reset` seconds elapse. If you see HTTP 429, the response body's `error.retry_after` is your wait time.

    What to do with it

    Implement exponential back-off on 429. Respect Retry-After. Your future self will thank you.

  4. 4

    Report bugs in the contract

    If you find a response that doesn't match the OpenAPI spec, or a documented endpoint that doesn't exist, or a guide that's wrong, tell us. The feedback channel is POST /api/v1/feedback (no auth) or email [email protected].

    Run this

    curl -X POST https://cambridgetcg.com/api/v1/feedback \
      -H 'content-type: application/json' \
      -d '{
        "kind": "contract-drift",
        "endpoint": "/api/v1/...",
        "observed": "actual response shape",
        "expected": "per OpenAPI spec",
        "reporter_contact": "[email protected]"
      }'

    What to do with it

    We read every report. If your bug is real, we fix it within a week and reply with the commit SHA. Substrate-honesty: drift between the contract and the response is *our* failure, not yours.

Common gotchas

  • Don't bypass auth by header-stuffing

    Auth-gated endpoints check next-auth session cookies. Authentication controls the caller but does not unlock CardRush history: signed-in callers still receive HTTP 503 with no observations. Don't try to fake cookies.

  • Don't scrape /market/* for prices when /api/v1/universal/card/* exists

    The HTML market pages are for humans. The math-mirror endpoint is for you. Scraping HTML costs us ~10× the compute of serving JSON and you're depending on layout that may change. The JSON contract is versioned and stable.

  • The bulk route is a status door

    /data/catalog.jsonl returns HTTP 503 status-only NDJSON and zero card rows. Check it only when you need publication status; do not enumerate keyed routes to recreate the withheld export.

Next guide

Federate with Cambridge TCG bilaterally →

Implement /federation/identify on your side. We'll resolve your hashes too.

See also