API Reference – Scrollrack.gg

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.

Endpoint Overview

Method URL Description
POST /api/validate Validate a TCG decklist

POST /api/validate

This endpoint validates a decklist against game-specific format rules.

Request

POST /api/validate
Content-Type: application/json

Request Body Parameters

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

Example Request for MTG

{
  "game": "mtg",
  "format": "commander",
  "list": "~~Commanders~~\n1 Atraxa, Praetors' Voice\n\n~~Mainboard~~\n4 Sol Ring\n3 Cultivate\n92 Plains"
}

Example Request for Pokémon

{
  "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"
}

Response

The API returns a JSON response with validation results.

Response Fields

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

Example Response - Valid MTG Deck

{
  "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
    }
  }
}

Example Response - Valid Pokémon Deck

{
  "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
    }
  }
}

Example Response - Invalid Deck

{
  "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
    }
  }
}

Decklist Format

Decklists should be structured using section markers with the following format:

~~Section Name~~
[quantity] Card Name

Section Names by Game

Magic: The Gathering

Pokémon

Card Format

Cards can be formatted in several ways:

Magic: The Gathering

4 Lightning Bolt   <- Quantity followed by card name
Lightning Bolt     <- Quantity defaults to 1 if omitted

Pokémon

4 Pikachu SVI 123   <- Quantity, set code, card number, and name
2 Basic Fire Energy <- Energy cards can be specified by name

Supported Games and Formats

Magic: The Gathering (mtg)

Formats:

Pokémon (pokemon)

Formats:

Error Types

The API can return various error types:

  1. Missing Sections: When required sections are missing

    • Example: "Missing required section: ~~Commanders~~"
  2. Deck Size Violations: When deck size doesn't meet format requirements

    • Example: "Deck must contain exactly 100 cards (mainboard + commanders). Currently: 65"
  3. Section Constraints: When a section violates its size constraints

    • Example: "Mainboard must have at least 98 cards. Currently: 45"
  4. Card Quantity Violations: When a card exceeds its copy limit

    • Example: "Too Many Copies Of: Lightning Bolt (5 > 4)"
  5. Legality Violations: When a card is not legal in the format

    • Example: "Use of Illegal Card: Black Lotus"
  6. Unknown Cards: When a card name cannot be found in the database

    • Example: "Unknown Card: Made Up Card Name"
  7. Card Name Mismatch (Pokémon only): When the provided name doesn't match the database name for the given set/number

    • Example: "Card name mismatch: "Pkachu" does not match "Pikachu""

Rate Limiting

The API currently does not implement rate limiting, but excessive usage may be throttled in the future.