API Overview
The power of Sleeved, at your fingertips.
Base URL
All API endpoints are prefixed with:
https://api.sleeved.gg/v1Supported Games
The API currently supports four games:
| Game | Slug |
|---|---|
| Digimon Card Game | digimon |
| Gundam Card Game | gundam |
| Grand Archive TCG | grand-archive |
| Chrono Core TCG | chrono-core |
Use these slugs in path parameters wherever a :slug is shown in an endpoint.
Authentication
Most endpoints require an API key passed in the X-API-Key request header. The Get Deck endpoint is the exception — it is unauthenticated so that Tabletop Simulator and similar tools can fetch deck data directly. See Authentication for details on key format and error handling.
Response Format
Success
All successful JSON responses wrap the payload in a data field:
{
"data": { ... }
}Errors
Error responses use an error field with a human-readable message:
{
"error": "Invalid API key"
}Common HTTP status codes:
| Status | Meaning |
|---|---|
200 | Request succeeded |
400 | Bad request — invalid parameters |
401 | Authentication failed |
404 | Resource not found |
429 | Rate limit exceeded |
Text Exports
The Get Deck endpoint supports different export formats via the format query parameter:
format=json(default) — Structured output for all use-casesformat=text— For importing to platforms or simulators like Untap.in, Limitless TCG, DCGO, etc.format=ga-tts— Grand Archive only; enriched card data for Tabletop Simulator
Content Negotiation Convention
Sleeved uses the ?format= query parameter to select representations on resources that can return non-JSON formats. The API does not honor the HTTP Accept header for content negotiation. This is a deliberate convention: query-parameter selection is curl-friendly, easy to share in bug reports and integration code, and unambiguous to debug from a browser address bar.
Two related rules to be aware of:
- JSON responses always wrap the payload in
{ data: ... }. Non-JSON responses (e.g.text/plainfromformat=text) return raw content with no envelope —data:does not appear in the body. - Future endpoints with multi-format outputs will follow this same
?format=convention rather than addingAccept-header negotiation. If a new endpoint needstext,csv, or another format, it will expose them via?format=for consistency.
Versioning
All routes are prefixed with /v1/. Breaking changes will be introduced under a new version prefix; the current version will continue to be served during any transition period. See API Contract Guarantees for the full versioning, deprecation, and breaking-change policy — including the 6-month deprecation window, RFC 8594 Deprecation/Sunset headers, and the per-endpoint /v2 coexistence model.
Browsing and Bulk-Fetching Public Decks
Two endpoints work together to let a partner enumerate and mirror a game's public decks without one request per deck:
- List public decks (
GET /decks/public) returns paginated summaries —id,gameId,createdAt,updatedAt— for every public deck in a game. No deck name, owner identity, card contents, or engagement counters. Requires thedecks:browse:publicscope. - Get deck details (
POST /decks/details) takes up to 50 ids from step 1 and returns a minimal per-deck object —id,gameId,name,cards(each{cardId, quantity, zoneId}) — plusunresolved. Still no owner identity or timestamps. Requires thedecks:read:publicscope. - For a single deck by id (outside a listing/bulk flow), use Get deck directly. This is the only one of the three that returns the full deck shape, including
ownerDisplayName.
Match bulk-detail results by id, never by array position. POST /decks/details returns decks in unspecified order. Build a lookup keyed on each entry's id field before consuming the response.
name is untrusted, user-authored text — escape on render. Both POST /decks/details and GET /decks/:deckId return name (the listing endpoint, GET /decks/public, still does not). name — and, on GET /decks/:deckId, ownerDisplayName — comes straight from Firestore with no server-side escaping. HTML-escape (or otherwise sanitize) name, ownerDisplayName, and any other user-authored string field before rendering it in your own UI.
A missing id behaves differently on the two deck-fetch endpoints. GET /decks/:deckId (the single-deck endpoint) returns 404 for a deck that doesn't exist or isn't public. POST /decks/details never does this — every requested id that can't be resolved (malformed, private, or nonexistent, indistinguishably) is placed in the response's unresolved array instead, and the batch call still returns 200. If your integration expects a 404 per deck from the bulk endpoint, it will hang waiting for one that never comes — check unresolved instead.
updatedSince is for incremental sync, with caveats:
- It only combines with the default
sort=updatedAt— any othersortvalue withupdatedSinceset returns400. - The
updatedAt >= updatedSinceboundary is inclusive. Store theupdatedAtof the last deck you processed and pass it back asupdatedSinceon your next sync — expect to see that same deck again in the response and dedupe it client-side. - Timestamps are compared using Sleeved's server clock, not the requesting client's. Don't assume your local clock and Sleeved's are in lockstep to the second; the inclusive boundary is what makes this safe even with modest clock drift.
- Delta syncing alone cannot detect deletions or unpublishing. A deck that stops being public no longer appears in any
updatedSincewindow — it simply vanishes from future pages rather than showing up with a tombstone. Periodically run a full (non-incremental) enumeration ofGET /decks/publicand diff it against your local mirror to catch decks that were removed or made private since your last full pass.
Next Steps
- Authentication — get your API key set up
- Game Sync Metadata — check whether your local card index needs updating
- Browse Cards — paginate through card data
- Get Card — fetch a single card by its ID
- Get Deck — fetch decks as JSON, plain text (Limitless TCG, Untap.in), or TTS card data (Grand Archive)
- List Public Decks — paginate through a game's public deck summaries
- Get Deck Details — bulk-fetch full contents for up to 50 decks by id
- Share Tokens — access private decks
- Rate Limiting — understand request limits
- API Contract Guarantees — versioning, deprecation, and breaking-change policy