{"data":{"@kind":"guide","slug":"respect-our-limits","title":"How to be a polite client","subtitle":"Etiquette + identification + the contact channel.","intro":"Cambridge TCG is run by one operator (Yu) on a small infrastructure budget. The data is CC0; the compute isn't. 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.","audiences":["agent","scraper","mirror","aggregator"],"prerequisites":["You're consuming the API"],"estimated_minutes":6,"step_count":4,"steps":[{"step_number":1,"title":"Identify yourself in User-Agent","instruction":"Always send a User-Agent string that names your project and a contact email. The format we recommend: `your-project/1.0 (contact@yourdomain.example)`. We'd rather email you about a bug than firewall an opaque bot.","curl":"curl -H 'User-Agent: example-bot/1.0 (admin@example.com)' \\\n  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."},{"step_number":2,"title":"Cache responses to the freshness budget","instruction":"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."},{"step_number":3,"title":"Watch the RateLimit response headers","instruction":"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.","links":[{"label":"Rate limit policy","href":"/api/v1/rate-limits"}]},{"step_number":4,"title":"Report bugs in the contract","instruction":"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 contact@cambridgetcg.com.","curl":"curl -X POST https://cambridgetcg.com/api/v1/feedback \\\n  -H 'content-type: application/json' \\\n  -d '{\n    \"kind\": \"contract-drift\",\n    \"endpoint\": \"/api/v1/...\",\n    \"observed\": \"actual response shape\",\n    \"expected\": \"per OpenAPI spec\",\n    \"reporter_contact\": \"admin@yourdomain.example\"\n  }'","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."}],"gotchas":[{"title":"Don't bypass auth by header-stuffing","description":"Auth-gated endpoints (`/api/v1/cards/[sku]/cardrush-history`, `/api/v1/webhooks/subscriptions`) check next-auth session cookies. Don't try to fake them. We log unauthorized attempts."},{"title":"Don't scrape /market/* for prices when /api/v1/universal/card/* exists","description":"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."},{"title":"Don't poll the bulk catalog more than once every 6 hours","description":"It's 6 MB streamed. Pulling it every minute is rude. The freshness budget is 24 hours; cron at 04:00 UTC is what we recommend."}],"next_guide":{"slug":"federate-bilateral","title":"Federate with Cambridge TCG bilaterally","url":"/api/v1/guides/federate-bilateral","html_url":"/agents/guides/federate-bilateral"},"see_also":[{"label":"Rate limits policy","href":"/api/v1/rate-limits"},{"label":"Feedback endpoint","href":"/api/v1/feedback"}],"last_verified":"2026-05-14","feedback":{"kind":"guide-feedback","endpoint":"/api/v1/feedback","body_template":{"kind":"guide-feedback","guide_slug":"respect-our-limits","step_number":"<which step had the issue, or null for whole-guide feedback>","observation":"<what you observed>","expected":"<what you expected>","reporter_contact":"<your email>"}},"html_sibling":"/agents/guides/respect-our-limits"},"_meta":{"spec_version":"1","endpoint":"/api/v1/guides/[slug]","retrieved_at":"2026-05-13T18:56:02.380Z","as_of":"2026-05-13T18:56:02.381Z","sources":["ctcg-derived"],"freshness_seconds":86400,"license":"CC0-1.0","request_id":"req_ba876de7-657","deprecation":null,"next_link":null,"self_reference":{"this_endpoint":"/api/v1/guides/[slug]","contains_self":true},"source_license":["CC0-1.0"]}}