Using the API
Every route mirrors Scryfall. Replace https://api.scryfall.com with the
base URL below and existing Scryfall clients work unchanged.
https://api.dtmdeck.com
Cards
| Method | Endpoint | Description |
|---|---|---|
| GET | /cards/search?q=… | Search with Scryfall query syntax (see below). Params: order, dir, unique, page. |
| GET | /cards/named?exact= / ?fuzzy= | One card by exact or fuzzy name. Optional set. |
| GET | /cards/random | A random card. Optional q to filter. |
| POST | /cards/collection | Batch lookup. Body: {"identifiers":[…]}. |
| GET | /cards/{id} | By Scryfall UUID. Add ?format=image&version= for the image. |
| GET | /cards/{set}/{number}/{lang?} | By set code + collector number (language defaults to en). |
| GET | /cards/{multiverse|arena|mtgo|tcgplayer|cardmarket}/{id} | By external ID. |
| GET | /cards/{id}/rulings | Rulings for a card. |
| GET | /cards/{id}/image/{version?} | Image. Versions: small normal large png art_crop border_crop. ?face= for back faces. |
Sets & bulk data
| Method | Endpoint | Description |
|---|---|---|
| GET | /sets | All sets. |
| GET | /sets/{code} | A set by code (e.g. lea). |
| GET | /sets/{id} · /sets/tcgplayer/{id} | A set by Scryfall UUID or TCGplayer group id. |
| GET | /bulk-data | This mirror's available datasets. |
| GET | /bulk-data/{type}/file | Streamed full export of a dataset as a JSON array. |
Search query syntax
A pragmatic subset of Scryfall's syntax. Combine terms with spaces (AND),
OR, negation (-), and parentheses for grouping.
| Operator | Matches |
|---|---|
bolt / "draw a card" | Card name contains the word/phrase. |
c: color: | Colors. c:rg = contains R and G; supports >=, <=, =. c:m multicolor, c:c colorless. |
id: identity: | Color identity (same comparison rules). |
t: type: | Type line, e.g. t:goblin, t:instant. |
o: oracle: | Oracle text, e.g. o:"draw a card". |
s: e: set: | Set code, e.g. set:neo. |
mv: cmc: | Mana value with comparisons, e.g. mv>=15, cmc=3. |
pow: tou: | Power / toughness, e.g. pow>=5. |
r: rarity: | Rarity, e.g. r>=rare (common < uncommon < rare < mythic). |
a: artist: · lang: · year: · layout: | Artist, language, release year, layout. |
is: not: | split, flip, transform, dfc, mdfc, saga, adventure, leveler, reserved, reprint, promo, digital, fullart, textless, oversized, funny, token. |
Result params
order = name · cmc · power · toughness · released · rarity · set · artist ·
number · dir = asc · desc ·
unique = cards · prints · art · page (175 per page).
Unsupported operators are ignored rather than erroring.
Examples
https://api.dtmdeck.com/cards/search?q=c:rg+t:creature&order=cmc
https://api.dtmdeck.com/cards/search?q=o:"draw a card"+t:instant&unique=cards
https://api.dtmdeck.com/cards/search?q=(t:goblin OR t:elf) -c:r
https://api.dtmdeck.com/cards/search?q=mv>=15&order=cmc&dir=desc
Response format
Single objects carry an "object" field (card, set,
ruling). Lists use Scryfall's pagination shape:
{
"object": "list",
"total_cards": 540,
"has_more": true,
"next_page": "https://api.dtmdeck.com/cards/search?q=…&page=2",
"data": [ { "object": "card", … } ]
}
Errors mirror Scryfall too: {"object":"error","code":"not_found","status":404,"details":"…"}.
Operating the mirror
Run these from the project root (php artisan …):
# Manually sync now (downloads changed datasets, refreshes sets)
php artisan scryfall:sync
# Process queued ingestion jobs (keep this running)
php artisan queue:work
A daily sync at 10:00 is scheduled; it requires php artisan schedule:run to be
invoked every minute (cron, or a Windows Task Scheduler task) plus a running queue worker.
See the project README.md for full setup details.