API Documentation
Access tournament results, decklists, stores, scenes, and card data.
https://api.digilab.cards Overview
The DigiLab API provides read-only access to tournament data, decklists, store listings, scene information, and card data for the Digimon TCG competitive community.
The API is free for non-commercial use. Request an API key to get started.
What's available
- Tournament listings — event dates, formats, player counts, winners, winning decks
- Decklists — player submissions with archetype, placement, and tournament context
- Stores — game store directory with locations and scene associations
- Scenes — geographic regions (metro areas, states, countries)
- Deck archetypes — archetype info, colors, display cards
- Cards — card search with set, color, and type filters
What's not available
Player profiles, ratings, leaderboard rankings, and metagame analysis are not available via the API. These are exclusive to digilab.cards.
Conventions
- All endpoints are
GETrequests that return JSON - Responses include standard
Cache-Controlheaders (15 min edge cache for listings) - Paginated endpoints return a
paginationobject withpage,per_page,total, andtotal_pages - Listing endpoints include extra metadata (
stats,formats,event_types) only on page 1 to reduce payload size - Null values are included in responses (not omitted)
Quick Start
Make your first API request in 30 seconds.
1. Get an API key
Request one in the #api channel on Discord.
Join Discord2. Make a request
curl -H "X-API-Key: dl_k_your_key_here" \
"https://api.digilab.cards/api/tournaments?per_page=2" 3. Get data back
{
"data": [
{
"tournament_id": 1234,
"event_date": "2026-04-15",
"event_type": "locals",
"format": "BT18",
"player_count": 16,
"store_name": "Card Masters",
"winner_name": "PlayerName",
"winning_deck": "Blue Flare"
}
],
"pagination": { "page": 1, "per_page": 2, "total": 342, "total_pages": 171 }
} That's it. All endpoints follow this same pattern — pass your key in the X-API-Key header, get JSON back.
Authentication
All API requests from external consumers require an API key. Pass it via the X-API-Key header:
curl -H "X-API-Key: dl_k_your_key_here" \
https://api.digilab.cards/api/tournaments Getting an API key
API keys are issued by DigiLab admins. To request one, reach out in the #api channel with:
- What you're building (bot, website, tool, etc.)
- Expected request volume
- Your contact info
Keys are shown once at generation and cannot be retrieved later. Do not commit keys to public repositories.
Rate Limits
Two rate limits apply to all API requests:
| Limit | Window | Scope |
|---|---|---|
| 60 requests | per minute | Per IP address |
| 300 requests | per minute | Per API key |
When rate limited, the API returns 429 Too Many Requests with a Retry-After header:
HTTP/1.1 429 Too Many Requests
Retry-After: 45
Content-Type: application/json
{"error": "Rate limit exceeded. Please slow down."} Errors
All error responses return JSON with an error field:
{ "error": "Resource not found" } | Status | Meaning | Common Cause |
|---|---|---|
400 | Bad Request | Invalid or missing query parameters |
401 | Unauthorized | Missing X-API-Key header |
403 | Forbidden | Invalid, revoked, or inactive API key |
404 | Not Found | Invalid ID or slug in path (e.g. /api/store/99999) |
429 | Too Many Requests | Rate limit exceeded — check Retry-After header |
500 | Server Error | Unexpected failure — please report on Discord |
Error response example
HTTP/1.1 404 Not Found
Content-Type: application/json
{ "error": "Store not found" } HTTP/1.1 401 Unauthorized
Content-Type: application/json
{ "error": "API key required. Pass your key via the X-API-Key header." } GET /api/tournaments
Paginated tournament listings with filtering and sorting.
Query parameters
| Param | Type | Description |
|---|---|---|
page | int | Page number. Default: 1 |
per_page | int | Results per page. Default: 50, max: 100 |
scene | string | Filter by scene slug (e.g. austin-tx) |
country | string | Filter by country code (e.g. US, JP) |
state | string | Filter by state/region (e.g. TX) |
continent | string | Filter by continent (e.g. North America) |
format | string | Filter by format ID (e.g. BT18) |
event_type | string | Filter by event type. Repeatable for multi-select. Values: locals, regional, major, online |
search | string | Search store names |
date_from | string | Start date (YYYY-MM-DD) |
date_to | string | End date (YYYY-MM-DD) |
sort | string | Sort field. Default: date. Values: date, player_count, event_type, store, format |
sort_dir | string | Sort direction. Default: desc. Values: asc, desc |
Response
{
"data": [
{
"tournament_id": 1234,
"event_date": "2026-04-15",
"event_type": "locals",
"format": "BT18",
"player_count": 16,
"store_name": "Card Masters",
"store_slug": "card-masters-austin",
"city": "Austin",
"state_region": "TX",
"country": "US",
"winner_name": "PlayerName",
"winner_slug": "playername",
"winning_deck": "Blue Flare",
"winning_deck_slug": "blue-flare",
"winning_deck_color": "Blue",
"winning_deck_secondary_color": null
}
],
"pagination": { "page": 1, "per_page": 50, "total": 342, "total_pages": 7 },
"stats": { ... },
"monthly": [{ "month": "2026-04", "count": 48 }],
"formats": [{ "format_id": "BT18", "set_name": "...", "display_name": "...", "release_date": "..." }],
"event_types": [{ "event_type": "locals", "count": 210 }]
} Response fields
| Field | Type | Description |
|---|---|---|
tournament_id | int | Unique tournament identifier |
event_date | string | Event date in YYYY-MM-DD format |
event_type | string | Tournament tier: locals, regional, major, online |
format | string | Card set format ID (e.g. BT18) |
player_count | int | Number of participants |
store_name | string | Host store display name |
store_slug | string | URL-safe store identifier for linking |
city | string|null | Store city |
state_region | string|null | Store state or region code |
country | string|null | Two-letter country code (ISO 3166-1) |
winner_name | string|null | First-place player display name |
winner_slug | string|null | Winner URL slug (for linking to profile) |
winning_deck | string|null | Winning deck archetype name |
winning_deck_slug | string|null | Winning deck URL slug |
winning_deck_color | string|null | Primary color: Red, Blue, Yellow, Green, Black, Purple, White |
winning_deck_secondary_color | string|null | Secondary color (for dual-color decks), or null |
stats, monthly, formats, and event_types are only included on page 1.
Error responses
| Status | When |
|---|---|
401 / 403 | Missing or invalid API key |
429 | Rate limit exceeded |
GET /api/decklists
Paginated decklist listings. Supports scene-aware listing mode or archetype-filtered mode.
Query parameters
| Param | Type | Description |
|---|---|---|
page | int | Page number. Default: 1 |
per_page | int | Results per page. Default: 50, max: 100 |
archetype_id | int | Filter to a single archetype (activates archetype detail mode) |
archetype_ids | string | Comma-separated archetype IDs for multi-select |
archetype | string | Filter by archetype slug (e.g. blue-flare) |
format | string | Filter by format ID |
event_type | string | Filter by event type. Repeatable |
placement_max | int | Max placement (e.g. 8 for top 8 only) |
colors | string | Comma-separated color filters (e.g. Blue,Red) |
scene | string | Filter by scene slug |
country | string | Filter by country code |
search | string | Search archetype or player names |
date_from | string | Start date (YYYY-MM-DD) |
date_to | string | End date (YYYY-MM-DD) |
sort | string | Sort field. Default: date. Values: date, placement, player_count, event_type, archetype, format |
sort_dir | string | Sort direction. Default: desc |
Response
{
"data": [
{
"result_id": 5678,
"tournament_id": 1234,
"event_date": "2026-04-15",
"event_type": "locals",
"format": "BT18",
"player_count": 16,
"placement": 1,
"wins": 4,
"losses": 0,
"ties": 0,
"player_name": "PlayerName",
"player_slug": "playername",
"store_name": "Card Masters",
"store_slug": "card-masters-austin",
"archetype_name": "Blue Flare",
"archetype_slug": "blue-flare",
"primary_color": "Blue",
"secondary_color": null,
"display_card_id": "BT13-027"
}
],
"pagination": { "page": 1, "per_page": 50, "total": 156, "total_pages": 4 },
"stats": { ... },
"collage": [{ "card_id": "BT13-027" }],
"formats": [...],
"event_types": [...]
} Response fields
| Field | Type | Description |
|---|---|---|
result_id | int | Unique result identifier |
tournament_id | int | Associated tournament ID |
event_date | string | Tournament date (YYYY-MM-DD) |
event_type | string | Tournament tier |
format | string | Format ID |
player_count | int | Tournament size |
placement | int | Final standing (1 = winner) |
wins | int | Match wins |
losses | int | Match losses |
ties | int | Match ties/draws |
player_name | string | Player display name |
player_slug | string | Player URL slug |
store_name | string | Host store name |
store_slug | string | Store URL slug |
archetype_name | string | Deck archetype display name |
archetype_slug | string | Deck archetype URL slug |
primary_color | string | Deck primary color |
secondary_color | string|null | Deck secondary color, or null |
display_card_id | string | Representative card ID for art display (e.g. BT13-027) |
stats, collage, formats, and event_types are only included on page 1.
Error responses
| Status | When |
|---|---|
401 / 403 | Missing or invalid API key |
429 | Rate limit exceeded |
GET /api/stores
Paginated store directory with search and geographic filtering.
Query parameters
| Param | Type | Description |
|---|---|---|
page | int | Page number. Default: 1 |
per_page | int | Results per page. Default: 50, max: 100 |
scene | string | Filter by scene slug |
country | string | Filter by country code |
state | string | Filter by state/region |
continent | string | Filter by continent |
search | string | Search store names and cities |
min_tournaments | int | Minimum tournament count. Default: 0 |
min_avg_turnout | int | Minimum average player turnout. Default: 0 |
sort | string | Sort field. Default: tournaments. Values: name, tournaments, avg_turnout, players, recent |
sort_dir | string | Sort direction. Default: desc |
Response
{
"data": [
{
"store_id": 42,
"name": "Card Masters",
"slug": "card-masters-austin",
"city": "Austin",
"state": "TX",
"country": "US",
"is_online": false,
"scene_name": "Austin, TX",
"scene_slug": "austin-tx",
"tournament_count": 28,
"unique_players": 67,
"avg_turnout": 14,
"most_recent": "2026-04-22",
"latitude": 30.2672,
"longitude": -97.7431
}
],
"pagination": { ... },
"stats": { ... },
"map_points": [{ "lat": 30.27, "lng": -97.74, "name": "Card Masters", "slug": "card-masters-austin", "city": "Austin", "country": "US", "is_online": false }]
} Response fields
| Field | Type | Description |
|---|---|---|
store_id | int | Unique store identifier |
name | string | Store display name |
slug | string | URL-safe identifier |
city | string|null | City name |
state | string|null | State/region code |
country | string|null | Two-letter country code |
is_online | bool | true for online-only organizers |
scene_name | string|null | Associated scene display name |
scene_slug | string|null | Scene URL slug |
tournament_count | int | Total tournaments hosted |
unique_players | int | Distinct players who've attended |
avg_turnout | int | Average players per event |
most_recent | string|null | Date of most recent event (YYYY-MM-DD) |
latitude | float|null | Store latitude (for mapping) |
longitude | float|null | Store longitude (for mapping) |
stats and map_points are only included on page 1.
Error responses
| Status | When |
|---|---|
401 / 403 | Missing or invalid API key |
429 | Rate limit exceeded |
GET /api/store/:id
Individual store data including location, scene, and summary stats.
Path parameters
| Param | Type | Description |
|---|---|---|
:id | int | required Store ID |
Response
{
"store": {
"id": 42,
"name": "Card Masters",
"slug": "card-masters-austin",
"city": "Austin",
"state": "TX",
"country": "US",
"scene_name": "Austin, TX",
"scene_slug": "austin-tx",
"total_tournaments": 28,
"total_players": 67,
"last_event": "2026-04-22",
"top_deck": {
"name": "Blue Flare",
"primary_color": "Blue",
"secondary_color": null
}
}
} Response fields
| Field | Type | Description |
|---|---|---|
id | int | Store ID |
name | string | Store display name |
slug | string | URL-safe identifier |
city | string|null | City |
state | string|null | State/region code |
country | string|null | Country code |
scene_name | string|null | Scene display name |
scene_slug | string|null | Scene URL slug |
total_tournaments | int | Lifetime tournament count |
total_players | int | Cumulative player-entries across all tournaments |
last_event | string|null | Most recent event date |
top_deck | object|null | Most-played deck archetype at this store |
Error responses
| Status | When |
|---|---|
404 | No store with the given ID exists |
GET /api/scenes
All active scenes with geographic coordinates. Useful for building maps.
Response
[
{
"scene_id": 1,
"name": "Austin, TX",
"slug": "austin-tx",
"display_name": "Austin, TX",
"scene_type": "metro",
"state_region": "TX",
"country": "US",
"continent": "North America",
"lat": 30.2672,
"lng": -97.7431
}
] Response fields
| Field | Type | Description |
|---|---|---|
scene_id | int | Unique scene identifier |
name | string | Scene name (used internally) |
slug | string | URL-safe identifier |
display_name | string | Human-readable display name |
scene_type | string | Geographic level: metro, state, country, continent |
state_region | string|null | State/region code |
country | string|null | Country code |
continent | string|null | Continent name |
lat | float|null | Center latitude (avg of store locations) |
lng | float|null | Center longitude |
Returns a flat array (not paginated). Coordinates are the average of all store locations in the scene.
GET /api/scene/:slug
Scene overview with deck meta, recent tournaments, and top players for the current format.
Path parameters
| Param | Type | Description |
|---|---|---|
:slug | string | required Scene slug (e.g. austin-tx) |
Response
{
"scope": { "level": "scene", "label": "Austin, TX" },
"decks": [
{
"archetype_name": "Blue Flare",
"primary_color": "Blue",
"secondary_color": null,
"slug": "blue-flare",
"display_card_id": "BT13-027",
"entries": 42,
"firsts": 8,
"wins": 120,
"losses": 48,
"pilots": 18
}
],
"tournaments": [
{
"tournament_id": 1234,
"event_date": "2026-04-15",
"event_type": "locals",
"format": "BT18",
"player_count": 16,
"store_name": "Card Masters",
"winner_name": "PlayerName",
"winning_deck": "Blue Flare",
"winning_deck_color": "Blue",
"winning_deck_secondary_color": null
}
],
"players": [
{
"id": 100,
"name": "PlayerName",
"slug": "playername",
"rating": 1285,
"events_played": 12,
"wins": 8,
"top3": 5,
"top_deck": "Blue Flare",
"deck_color": "Blue",
"deck_secondary_color": null
}
]
} Response fields
| Field | Type | Description |
|---|---|---|
scope.level | string | Data granularity: scene, state, country, or continent (cascades up if insufficient data) |
scope.label | string | Display label for the scope level |
decks[].entries | int | Total entries (results) for this archetype in this scope |
decks[].firsts | int | Number of first-place finishes |
decks[].wins | int | Total match wins |
decks[].losses | int | Total match losses |
decks[].pilots | int | Distinct players who've played this deck |
players[].rating | int | Competitive rating score |
players[].top3 | int | Number of top-3 finishes |
If the scene has fewer than 5 data points, data cascades up to state, country, or continent level. The scope field indicates the actual level returned.
Error responses
| Status | When |
|---|---|
404 | No scene with the given slug exists |
GET /api/scene/:slug/tournaments
Tournament listing for a specific scene.
Path parameters
| Param | Type | Description |
|---|---|---|
:slug | string | required Scene slug |
Response
{
"scope": { "level": "scene", "label": "Austin, TX" },
"tournaments": [
{
"tournament_id": 1234,
"event_date": "2026-04-15",
"event_type": "locals",
"format": "BT18",
"player_count": 16,
"store_name": "Card Masters",
"winner_name": "PlayerName",
"winning_deck": "Blue Flare",
"winning_deck_color": "Blue",
"winning_deck_secondary_color": null
}
]
} Tournament fields are the same as the tournaments endpoint. Scope cascades apply.
Error responses
| Status | When |
|---|---|
404 | No scene with the given slug exists |
GET /api/deck/:id
Deck archetype information with colors, stats, and display card.
Path parameters
| Param | Type | Description |
|---|---|---|
:id | int | required Archetype ID |
Response
{
"deck": {
"id": 15,
"name": "Blue Flare",
"slug": "blue-flare",
"primary_color": "Blue",
"secondary_color": null,
"display_card_id": "BT13-027",
"total_entries": 342,
"firsts": 64,
"pilots": 128,
"meta_pct": 12.4,
"top3_count": 95,
"top3_rate": 27.8
}
} Response fields
| Field | Type | Description |
|---|---|---|
id | int | Archetype ID |
name | string | Archetype display name |
slug | string | URL-safe identifier |
primary_color | string | Primary deck color |
secondary_color | string|null | Secondary color for dual-color decks |
display_card_id | string | Representative card ID |
total_entries | int | Total tournament results with this archetype |
firsts | int | First-place finishes |
pilots | int | Distinct players who've played this deck |
meta_pct | float | Metagame share percentage (current format) |
top3_count | int | Top-3 finishes |
top3_rate | float | Top-3 rate as percentage of entries |
Error responses
| Status | When |
|---|---|
404 | No archetype with the given ID exists |
GET /api/cards
Card search with filtering by set, color, type, and text.
Query parameters
| Param | Type | Description |
|---|---|---|
q | string | Search by card name or card ID (e.g. BT13-027) |
color | string | Filter by color: Red, Blue, Yellow, Green, Black, Purple, White |
card_type | string | Filter by type: Digimon, Tamer, Option, Digi-Egg |
set_code | string | Filter by set code (e.g. BT13) |
level_min | int | Minimum level (Digimon only) |
level_max | int | Maximum level |
cost_min | int | Minimum play cost |
cost_max | int | Maximum play cost |
page | int | Page number. Default: 1 |
per_page | int | Results per page. Default: 50 |
Response
{
"data": [
{
"card_id": "BT13-027",
"name": "MailBirdramon",
"display_name": null,
"card_type": "Digimon",
"color": "Blue",
"color2": null,
"level": 4,
"dp": 5000,
"play_cost": 5,
"digi_type": "Bird",
"attribute": "Vaccine",
"stage": "Champion",
"rarity": "C",
"set_code": "BT13"
}
],
"pagination": { "page": 1, "per_page": 50, "total": 1, "total_pages": 1 }
} Response fields
| Field | Type | Description |
|---|---|---|
card_id | string | Unique card identifier (e.g. BT13-027) |
name | string | Card name |
display_name | string|null | Alternate display name, if different from name |
card_type | string | Digimon, Tamer, Option, or Digi-Egg |
color | string | Primary card color |
color2 | string|null | Secondary color (dual-color cards) |
level | int|null | Digimon level (null for non-Digimon) |
dp | int|null | Digimon Power (null for non-Digimon) |
play_cost | int|null | Memory cost to play |
digi_type | string|null | Digimon type (e.g. Dragon, Bird) |
attribute | string|null | Digimon attribute: Vaccine, Virus, Data, Free |
stage | string|null | Evolution stage: In-Training, Rookie, Champion, Ultimate, Mega |
rarity | string | Card rarity: C, U, R, SR, SEC |
set_code | string | Set code (e.g. BT13, EX05) |
Error responses
| Status | When |
|---|---|
401 / 403 | Missing or invalid API key |
429 | Rate limit exceeded |
GET /api/search
Cross-entity search across players, stores, decks, and scenes.
Query parameters
| Param | Type | Description |
|---|---|---|
q | string | required Search query (2-100 characters) |
Response
{
"players": [
{ "id": 100, "name": "PlayerName", "slug": "playername", "rating": 1285, "events_played": 12, "scene_name": "Austin, TX", "scene_slug": "austin-tx" }
],
"stores": [
{ "id": 42, "name": "Card Masters", "slug": "card-masters-austin", "city": "Austin", "state": "TX", "country": "US", "scene_name": "Austin, TX", "scene_slug": "austin-tx" }
],
"decks": [
{ "id": 15, "name": "Blue Flare", "slug": "blue-flare", "primary_color": "Blue", "secondary_color": null, "total_entries": 342, "meta_pct": 12.4 }
],
"scenes": [
{ "id": 1, "name": "Austin, TX", "slug": "austin-tx", "display_name": "Austin, TX", "scene_type": "metro", "country": "US", "state_region": "TX", "continent": "North America" }
]
} Response fields
Each array contains the top matches for that entity type. Arrays may be empty.
| Field | Type | Description |
|---|---|---|
players[].rating | int | Competitive rating score |
players[].events_played | int | Total tournament entries |
decks[].total_entries | int | Times this archetype has been played |
decks[].meta_pct | float | Current metagame share percentage |
Common fields like id, name, slug follow the same conventions as their respective endpoints.
Error responses
| Status | When |
|---|---|
400 | Query q is missing, too short (< 2 chars), or too long (> 100 chars) |
API Stability
The DigiLab API is unversioned. Here's what that means for you:
- We may add new fields to responses at any time. Your code should ignore unknown fields gracefully.
- We may add new endpoints without notice.
- We will not remove or rename existing fields without advance notice on Discord and in the changelog below.
- We will not change the meaning of existing fields.
- Breaking changes (removed fields, changed types, removed endpoints) will be announced at least 30 days in advance.
Parse responses with a lenient JSON parser and avoid strict schema validation. New fields appearing in responses is expected and not a breaking change.
Terms of Use
By using the DigiLab API, you agree to the following:
Permitted use
- Building community tools, Discord bots, websites, and apps for the Digimon TCG community
- Academic research and data analysis
- Personal projects and learning
Not permitted
- Commercial resale of raw API data
- Bulk scraping beyond normal API usage patterns
- Misrepresentation — do not present DigiLab data as your own without attribution
- Abuse — do not use the API to harass, spam, or harm community members
Attribution
If you display DigiLab data publicly, please include a visible link back to digilab.cards. Example:
Data provided by DigiLab (digilab.cards) Key revocation
API keys may be revoked without notice for violation of these terms, sustained abuse, or excessive load. If your key is revoked, contact us on Discord to discuss.
Changelog
| Date | Change |
|---|---|
| 2026-05-01 | Public API launch with 10 endpoints, API key authentication, and rate limiting. Documentation published at api.digilab.cards. |
Subscribe to the #api channel on Discord for update notifications.