Scrollrack provides a simple and efficient REST API for validating trading card game decklists. This document details the endpoints, request/response formats, and usage examples.
| Method | URL | Description |
|---|---|---|
| POST | /api/validate |
Validate a TCG decklist |
/api/validateThis endpoint validates a decklist against game-specific format rules.
POST /api/validate
Content-Type: application/json
| Parameter | Type | Required | Description |
|---|---|---|---|
game |
string | Yes | Game identifier (mtg for Magic: The Gathering, pokemon for Pokémon) |
format |
string | Yes | Format to validate against (e.g., commander for MTG, standard for Pokémon) |
list |
string | Yes | Plain text decklist with section formatting |
{
"game": "mtg",
"format": "commander",
"list": "~~Commanders~~\n1 Atraxa, Praetors' Voice\n\n~~Mainboard~~\n4 Sol Ring\n3 Cultivate\n92 Plains"
}
{
"game": "pokemon",
"format": "standard",
"list": "~~Pokemon~~\n4 Pikachu SVI 123\n2 Charizard PAL 45\n\n~~Trainer~~\n4 Boss's Orders FST 236\n\n~~Energy~~\n10 Basic Fire Energy"
}
The API returns a JSON response with validation results.
| Field | Type | Description |
|---|---|---|
valid |
boolean | Whether the deck is valid for the given format |
format |
string | The format that was validated against |
errors |
array | List of validation errors (only when valid is false) |
decklist |
object | Normalized decklist with card data (only when valid is true) |
cardsPerSection |
object | Count of cards in each section (only when valid is true) |
totalCards |
number | Total number of cards in the deck (only when valid is true) |
meta |
object | Format metadata including rules and requirements |
{
"valid": true,
"format": "commander",
"decklist": {
"commanders": {
"Atraxa, Praetors' Voice": {
"quantity": 1,
"id": "bf6c1462-f1d2-4f58-b7a4-cb5b21399152"
}
},
"mainboard": {
"Sol Ring": {
"quantity": 1,
"id": "0afa0e33-4804-4b00-b625-c2d6b61090fc"
},
"Cultivate": {
"quantity": 3,
"id": "6e209ae9-7eca-4cf0-8070-c39a4da517f7"
},
"Plains": {
"quantity": 95,
"id": "3e9f26c9-64ec-4a23-a2a9-3eee8d0dcaac"
}
}
},
"cardsPerSection": {
"commanders": 1,
"mainboard": 99
},
"totalCards": 100,
"meta": {
"requiredSections": ["mainboard", "commanders"],
"rules": {
"requiredSections": ["mainboard", "commanders"],
"deckSize": { "exact": 100 },
"commanders": { "max": 2 },
"mainboard": { "min": 98 },
"maxCopies": 1
}
}
}
{
"valid": true,
"format": "standard",
"decklist": {
"pokemon": {
"Pikachu": {
"quantity": 4,
"set_id": "SVI 123",
"id": "abc123"
},
"Charizard": {
"quantity": 2,
"set_id": "PAL 45",
"id": "def456"
}
},
"trainer": {
"Boss's Orders": {
"quantity": 4,
"set_id": "FST 236",
"id": "ghi789"
}
},
"energy": {
"Fire Energy": {
"quantity": 10,
"set_id": null,
"id": "jkl012"
}
}
},
"cardsPerSection": {
"pokemon": 6,
"trainer": 4,
"energy": 10
},
"totalCards": 20,
"meta": {
"requiredSections": ["pokemon", "trainer", "energy"],
"rules": {
"requiredSections": ["pokemon", "trainer", "energy"],
"deckSize": { "exact": 60 },
"maxCopies": 4
}
}
}
{
"valid": false,
"errors": [
"Too Many Copies Of: Mana Crypt (4 > 1)",
"Use of Illegal Card: Mana Crypt"
],
"format": "commander",
"meta": {
"requiredSections": ["mainboard", "commanders"],
"rules": {
"requiredSections": ["mainboard", "commanders"],
"deckSize": { "exact": 100 },
"commanders": { "max": 2 },
"mainboard": { "min": 98 },
"maxCopies": 1
}
}
}
Decklists should be structured using section markers with the following format:
~~Section Name~~
[quantity] Card Name
~~Mainboard~~: Primary deck cards~~Commanders~~: Commander cards (for formats like Commander)~~Sideboard~~: Sideboard cards~~Pokemon~~: Pokémon cards ~~Trainer~~: Trainer cards~~Energy~~: Energy cardsCards can be formatted in several ways:
4 Lightning Bolt <- Quantity followed by card name
Lightning Bolt <- Quantity defaults to 1 if omitted
4 Pikachu SVI 123 <- Quantity, set code, card number, and name
2 Basic Fire Energy <- Energy cards can be specified by name
mtg)Formats:
commander: Commander/EDH format (100 cards including commander)paupercommander: Pauper Commander (100 cards, 1-2 commanders)modern, standard, legacy, etc. use default rules (60 card minimum, 15 card sideboard maximum)pokemon)Formats:
standard: Standard format (60 cards exactly)expanded: Same as aboveunlimited: Same as aboveThe API can return various error types:
Missing Sections: When required sections are missing
"Missing required section: ~~Commanders~~"Deck Size Violations: When deck size doesn't meet format requirements
"Deck must contain exactly 100 cards (mainboard + commanders). Currently: 65"Section Constraints: When a section violates its size constraints
"Mainboard must have at least 98 cards. Currently: 45"Card Quantity Violations: When a card exceeds its copy limit
"Too Many Copies Of: Lightning Bolt (5 > 4)"Legality Violations: When a card is not legal in the format
"Use of Illegal Card: Black Lotus"Unknown Cards: When a card name cannot be found in the database
"Unknown Card: Made Up Card Name"Card Name Mismatch (Pokémon only): When the provided name doesn't match the database name for the given set/number
"Card name mismatch: "Pkachu" does not match "Pikachu""The API currently does not implement rate limiting, but excessive usage may be throttled in the future.