Getting Started
Welcome to the Magic: The Gathering API! You can use the API to access Magic: The Gathering API endpoints, which can get information on cards and sets. All API access is performed over HTTPS and accessed from the https://api.magicthegathering.io
domain.
To use the API endpoints, the format is as follows:
https://api.magicthegathering.io/<version>/<resource>
For example:
https://api.magicthegathering.io/v1/cards
There are multiple SDKs available to make it even easier to consume the API. To chat with other developers and discuss the API and SDKs, check out the Discord Server!
Developer SDKs
There are multiple developer SDKs available. To see how to install and use them, refer to the links below:
- Ruby SDK: https://github.com/MagicTheGathering/mtg-sdk-ruby
- Python SDK: https://github.com/MagicTheGathering/mtg-sdk-python
- Javascript SDK: https://github.com/MagicTheGathering/mtg-sdk-javascript
- .NET SDK: https://github.com/MagicTheGathering/mtg-sdk-dotnet
- Java SDK: https://github.com/MagicTheGathering/mtg-sdk-java
- PHP SDK: https://github.com/MagicTheGathering/mtg-sdk-php
- Kotlin SDK: https://github.com/MagicTheGathering/mtg-sdk-kotlin
- Go SDK: https://github.com/MagicTheGathering/mtg-sdk-go
- Swift SDK: https://github.com/MagicTheGathering/mtg-sdk-swift
- Typescript SDK: https://github.com/MagicTheGathering/mtg-sdk-typescript
Rate Limits
Overview
Rate limits are enforced for all third-party applications and services. This document is an overview of the rate limits themselves, as well as how they are enforced and best practices for handling the errors returned when a rate limit is reached.
Third-party applications are currently throttled to 5000 requests per hour. As this API continues to age, the rate limits may be updated to provide better performance to users
Rationale
As previously mentioned, the primary goal is to provide a responsive interface for developers and users to use when accessing the MTG data. Since each request made to the API incurs a computational cost, it’s in the best interest of both Magic: The Gathering API and its developer partners that these costs be minimized to the greatest degree possible.
Rate limiting also helps third-party developers by encouraging them to build their integrations to make economical use of API requests.
HTTP/1.1 403 Forbidden
Date: Mon, 21 Apr 2014 13:26:48 GMT
Content-Type: application/json; charset=utf-8
{
"message": "Rate Limit Exceeded"
}
Errors
Code | Name | Description |
---|---|---|
400 | Bad Request | We could not process that action |
403 | Forbidden | You exceeded the rate limit |
404 | Not Found | The requested resource could not be found |
500 | Internal Server Error | We had a problem with our server. Please try again later |
503 | Service Unavailable | We are temporarily offline for maintenance. Please try again later |
{
"status": 404,
"error": "error message here"
}
Headers
There are quite a few custom response headers available when making a request. Some of these will only show up when the results are paginated.
Link
: Link headers with prev, last, next, first links (when appropriate)Page-Size
: The page size for the requestCount
: The number of elements returnedTotal-Count
: The total number of elements (across all pages)Ratelimit-Limit
: The ratelimit for a given userRatelimit-Remaining
: The number of requests left before the ratelimit is exceeded.
HTTP/1.1 200 Ok
Link: <http://api.magicthegathering.io/v1/cards?page=311>; rel="last", <http://api.magicthegathering.io/v1/cards?page=2>; rel="next"
Page-Size: 100
Count: 100
Total-Count: 31090
Ratelimit-Limit: 5000
Ratelimit-Remaining: 4999
/cards
Get All Cards
This call will return a maximum of 100 cards
Paginate the response using the page
parameter.
Each field below can be used as a query parameter. By default, fields that have a singular value such as rarity, set, and name will always use a logical “or” operator when querying with a list of values. Fields that can have multiple values such as colors, supertypes, and subtypes can use a logical “and” or a logical “or” operator.
The accepted delimiters when querying fields are the pipe character or a comma character. The pipe represents a logical “or”, and a comma represents a logical “and”. The comma can only be used with fields that accept multiple values (like colors).
Example:name=nissa, worldwaker|jace|ajani, caller
More examples: colors=red,white,blue
versus colors=red|white|blue
Parameters
- name
- The card name. For split, double-faced and flip cards, just the name of one side of the card. Basically each ‘sub-card’ has its own record.
- layout
- The card layout. Possible values: normal, split, flip, double-faced, token, plane, scheme, phenomenon, leveler, vanguard, aftermath
- cmc
- Converted mana cost. Always a number
- colors
- The card colors. Usually this is derived from the casting cost, but some cards are special (like the back of dual sided cards and Ghostfire).
- colorIdentity
- The card’s color identity, by color code. [“Red”, “Blue”] becomes [“R”, “U”]. A card’s color identity includes colors from the card’s rules text.
- type
- The card type. This is the type you would see on the card if printed today. Note: The dash is a UTF8 ‘long dash’ as per the MTG rules
- supertypes
- The supertypes of the card. These appear to the far left of the card type. Example values: Basic, Legendary, Snow, World, Ongoing
- types
- The types of the card. These appear to the left of the dash in a card type. Example values: Instant, Sorcery, Artifact, Creature, Enchantment, Land, Planeswalker
- subtypes
- The subtypes of the card. These appear to the right of the dash in a card type. Usually each word is its own subtype. Example values: Trap, Arcane, Equipment, Aura, Human, Rat, Squirrel, etc.
- rarity
- The rarity of the card. Examples: Common, Uncommon, Rare, Mythic Rare, Special, Basic Land
- set
- The set the card belongs to (set code).
- setName
- The set the card belongs to.
- text
- The oracle text of the card. May contain mana symbols and other symbols.
- flavor
- The flavor text of the card.
- artist
- The artist of the card. This may not match what is on the card as MTGJSON corrects many card misprints.
- number
- The card number. This is printed at the bottom-center of the card in small text. This is a string, not an integer, because some cards have letters in their numbers.
- power
- The power of the card. This is only present for creatures. This is a string, not an integer, because some cards have powers like: “1+*”
- toughness
- The toughness of the card. This is only present for creatures. This is a string, not an integer, because some cards have toughness like: “1+*”
- loyalty
- The loyalty of the card. This is only present for planeswalkers.
- language
- The language the card is printed in. Use this parameter along with the name parameter when searching by foreignName
- gameFormat
- The game format, such as Commander, Standard, Legacy, etc. (when used, legality defaults to Legal unless supplied)
- legality
- The legality of the card for a given format, such as Legal, Banned or Restricted.
- page
- The page of data to request
- pageSize
- The amount of data to return in a single request. The default (and max) is 100.
- orderBy
- The field to order by in the response results
- random
- Fetch any number of cards (controlled by pageSize) randomly
- contains
- Filter cards based on whether or not they have a specific field available (like imageUrl)
- id
- A unique id for this card. It is made up by doing an SHA1 hash of setCode + cardName + cardImageName
- multiverseid
- The multiverseid of the card on Wizard’s Gatherer web page. Cards from sets that do not exist on Gatherer will NOT have a multiverseid. Sets not on Gatherer are: ATH, ITP, DKM, RQS, DPA and all sets with a 4 letter code that starts with a lowercase ‘p’.
Other Fields in Response
The fields below are also part of the response (if not null), but cannot currently be used as query parameters
Parameters
- names
- Only used for split, flip and dual cards. Will contain all the names on this card, front or back
- manaCost
- The mana cost of this card. Consists of one or more mana symbols. (use cmc and colors to query)
- variations
- If a card has alternate art (for example, 4 different Forests, or the 2 Brothers Yamazaki) then each other variation’s multiverseid will be listed here, NOT including the current card’s multiverseid.
- imageUrl
- The image url for a card. Only exists if the card has a multiverse id.
- watermark
- The watermark on the card. Note: Split cards don’t currently have this field set, despite having a watermark on each side of the split card.
- border
- If the border for this specific card is DIFFERENT than the border specified in the top level set JSON, then it will be specified here. (Example: Unglued has silver borders, except for the lands which are black bordered)
- timeshifted
- If this card was a timeshifted card in the set.
- hand
- Maximum hand size modifier. Only exists for Vanguard cards.
- life
- Starting life total modifier. Only exists for Vanguard cards.
- reserved
- Set to true if this card is reserved by Wizards Official Reprint Policy
- releaseDate
- The date this card was released. This is only set for promo cards. The date may not be accurate to an exact day and month, thus only a partial date may be set (YYYY-MM-DD or YYYY-MM or YYYY). Some promo cards do not have a known release date.
- starter
- Set to true if this card was only released as part of a core box set. These are technically part of the core sets and are tournament legal despite not being available in boosters
- rulings
- The rulings for the card. An array of objects, each object having ‘date’ and ‘text’ keys.
- foreignNames
- Foreign language names for the card, if this card in this set was printed in another language. An array of objects, each object having ‘language’, ‘name’ and ‘multiverseid’ keys. Not available for all sets.
- printings
- The sets that this card was printed in, expressed as an array of set codes.
- originalText
- The original text on the card at the time it was printed. This field is not available for promo cards.
- originalType
- The original type on the card at the time it was printed. This field is not available for promo cards.
- legalities
- Which formats this card is legal, restricted or banned in. An array of objects, each object having ‘format’ and ‘legality’.
- source
- For promo cards, this is where this card was originally obtained. For box sets that are theme decks, this is which theme deck the card is from.
require 'mtg_sdk'
# Get all Cards
cards = MTG::Card.all
# Filter Cards
# You can chain 'where' clauses together. The key of the hash
# should be the URL parameter you are trying to filter on
cards = MTG::Card.where(supertypes: 'legendary')
.where(types: 'creature')
.where(colors: 'red,white')
.all
# Get cards on a specific page / pageSize
cards = MTG::Card.where(page: 50).where(pageSize: 50).all
from mtgsdk import Card
# Get all cards
cards = Card.all()
# Filter Cards
# You can chain 'where' clauses together. The key of the hash
# should be the URL parameter you are trying to filter on
cards = Card.where(supertypes='legendary') \
.where(types='creature') \
.where(colors='red,white') \
.all()
# Get cards on a specific page / pageSize
cards = Card.where(page=50).where(pageSize=50).all()
const mtg = require('mtgsdk')
// Get all cards
mtg.card.all()
.on('data', function (card) {
console.log(card.name)
});
// Filter Cards
mtg.card.all({ supertypes: 'legendary', types: 'creature', colors: 'red,white' })
.on('data', function (card) {
console.log(card.name)
});
// Get cards on a specific page / pageSize
mtg.card.where({ page: 50, pageSize: 50})
.then(cards => {
console.log(cards[0].name)
})
# Get all cards
curl "https://api.magicthegathering.io/v1/cards"
# Filter cards
curl "https://api.magicthegathering.io/v1/cards?supertypes=legendary&types=creature&colors=red,white"
# Get specific page of data
curl "https://api.magicthegathering.io/v1/cards?page=50&pageSize=50"
{
"cards":[
{
"name":"Archangel Avacyn",
"names":[
"Archangel Avacyn",
"Avacyn, the Purifier"
],
"manaCost":"{3}{W}{W}",
"cmc":5,
"colors":[
"White"
],
"colorIdentity":[
"W"
],
"type":"Legendary Creature — Angel",
"supertypes":[
"Legendary"
],
"types":[
"Creature"
],
"subtypes":[
"Angel"
],
"rarity":"Mythic Rare",
"set":"SOI",
"text":"Flash\nFlying, vigilance\nWhen Archangel Avacyn enters the battlefield, creatures you control gain indestructible until end of turn.\nWhen a non-Angel creature you control dies, transform Archangel Avacyn at the beginning of the next upkeep.",
"artist":"James Ryman",
"number":"5a",
"power":"4",
"toughness":"4",
"layout":"double-faced",
"multiverseid":409741,
"imageUrl":"http://gatherer.wizards.com/Handlers/Image.ashx?multiverseid=409741&type=card",
"rulings":[
{
"date":"2016-04-08",
"text":"Archangel Avacyn’s delayed triggered ability triggers at the beginning of the next upkeep regardless of whose turn it is."
},
{
"date":"2016-04-08",
"text":"Archangel Avacyn’s delayed triggered ability won’t cause it to transform back into Archangel Avacyn if it has already transformed into Avacyn, the Purifier, perhaps because several creatures died in one turn."
},
{
"date":"2016-04-08",
"text":"For more information on double-faced cards, see the Shadows over Innistrad mechanics article (http://magic.wizards.com/en/articles/archive/feature/shadows-over-innistrad-mechanics)."
}
],
"foreignNames":[
{
"name":"大天使艾维欣",
"language":"Chinese Simplified",
"multiverseid":410071
},
{
"name":"大天使艾維欣",
"language":"Chinese Traditional",
"multiverseid":410401
},
{
"name":"Archange Avacyn",
"language":"French",
"multiverseid":411061
},
{
"name":"Erzengel Avacyn",
"language":"German",
"multiverseid":410731
},
{
"name":"Arcangelo Avacyn",
"language":"Italian",
"multiverseid":411391
},
{
"name":"大天使アヴァシン",
"language":"Japanese",
"multiverseid":411721
},
{
"name":"대천사 아바신",
"language":"Korean",
"multiverseid":412051
},
{
"name":"Arcanjo Avacyn",
"language":"Portuguese (Brazil)",
"multiverseid":412381
},
{
"name":"Архангел Авацина",
"language":"Russian",
"multiverseid":412711
},
{
"name":"Arcángel Avacyn",
"language":"Spanish",
"multiverseid":413041
}
],
"printings":[
"SOI"
],
"originalText":"Flash\nFlying, vigilance\nWhen Archangel Avacyn enters the battlefield, creatures you control gain indestructible until end of turn.\nWhen a non-Angel creature you control dies, transform Archangel Avacyn at the beginning of the next upkeep.",
"originalType":"Legendary Creature — Angel",
"id":"02ea5ddc89d7847abc77a0fbcbf2bc74e6456559"
},
{ ... },
{ ... }
]
}
/cards/:id
Get Card
Returns a specific card by id or multiverseid
require 'mtg_sdk'
card = MTG::Card.find(386616)
from mtgsdk import Card
card = Card.find(386616)
const mtg = require('mtgsdk')
mtg.card.find(386616)
.then(result => {
console.log(result.card.name)
})
curl "https://api.magicthegathering.io/v1/cards/386616"
{
"card":{
"name":"Narset, Enlightened Master",
"manaCost":"{3}{U}{R}{W}",
"cmc":6,
"colors":[
"White",
"Blue",
"Red"
],
"type":"Legendary Creature — Human Monk",
...
}
}
/sets
Get All Sets
Currently, only the name and block fields can be used as query parameters. To query on multiple names or blocks at a time, use a pipe separated list (ex. sets?name=khans|origins
).
Parameters
- name
- The name of the set
- block
- The block the set is in
Other Fields In Reponse
The fields below are also part of the response (if not null), but cannot be used as query parameters.
Parameters
- code
- The code name of the set
- gathererCode
- The code that Gatherer uses for the set. Only present if different than ‘code’
- oldCode
- An old style code used by some Magic software. Only present if different than ‘gathererCode’ and ‘code’
- magicCardsInfoCode
- The code that magiccards.info uses for the set. Only present if magiccards.info has this set
- releaseDate
- When the set was released (YYYY-MM-DD). For promo sets, the date the first card was released
- border
- The type of border on the cards, either “white”, “black” or “silver”
- expansion
- Type of set. One of: “core”, “expansion”, “reprint”, “box”, “un”, “from the vault”, “premium deck”, “duel deck”, “starter”, “commander”, “planechase”, “archenemy”, “promo”, “vanguard”, “masters”
- onlineOnly
- Present and set to true if the set was only released online
- booster
- Booster contents for this set
require 'mtg_sdk'
# Get all Sets
sets = MTG::Set.all
# Filter Sets
sets = MTG::Set.where(name: 'khans').all
# Get sets on a specific page / pageSize
sets = MTG::Set.where(page: 2).where(pageSize: 10).all
from mtgsdk import Set
# Get all Sets
sets = Set.all()
# Filter Sets
sets = Set.where(name='khans').all()
# Get sets on a specific page / pageSize
sets = Set.where(page=2).where(pageSize=10).all()
# Get all sets
curl "https://api.magicthegathering.io/v1/sets"
# Filter cards
curl "https://api.magicthegathering.io/v1/sets?name=khans"
# Get specific page of data
curl "https://api.magicthegathering.io/v1/sets?page=2&pageSize=10"
{
"sets":[
{
"code":"KTK",
"name":"Khans of Tarkir",
"type":"expansion",
"border":"black",
"mkm_id":1495,
"booster":[
[
"rare",
"mythic rare"
],
"uncommon",
"uncommon",
"uncommon",
"common",
"common",
"common",
"common",
"common",
"common",
"common",
"common",
"common",
"common",
"land",
"marketing"
],
"mkm_name":"Khans of Tarkir",
"releaseDate":"2014-09-26",
"magicCardsInfoCode":"ktk",
"block":"Khans of Tarkir"
},
{ ... }.
{ ... }
]
}
/sets/:id
Get Set
Returns a specific set by the set code
require 'mtg_sdk'
card = MTG::Set.find('ktk')
from mtgsdk import Set
card = Set.find('ktk')
curl "https://api.magicthegathering.io/v1/sets/ktk"
{
"set":{
"code":"KTK",
"name":"Khans of Tarkir",
"type":"expansion",
"border":"black",
"mkm_id":1495,
"booster":[
[
"rare",
"mythic rare"
],
"uncommon",
"uncommon",
"uncommon",
"common",
"common",
"common",
"common",
"common",
"common",
"common",
"common",
"common",
"common",
"land",
"marketing"
],
"mkm_name":"Khans of Tarkir",
"releaseDate":"2014-09-26",
"magicCardsInfoCode":"ktk",
"block":"Khans of Tarkir"
}
}
/sets/:id/booster
Generate Booster Pack
Returns a list of cards for a specific set representing a booster pack for the set.
The number of commons, uncommons, rares, etc. are determined by the booster
field in a set response.
require 'mtg_sdk'
card = MTG::Set.generate_booster('ktk')
from mtgsdk import Set
from mtgsdk import Card
card = Set.generate_booster('ktk')
curl "https://api.magicthegathering.io/v1/sets/ktk/booster"
{
"cards": [
{
"name": "Meandering Towershell",
"manaCost": "{3}{G}{G}",
"cmc": 5,
"colors": [
"Green"
],
"type": "Creature — Turtle",
"types": [
"Creature"
],
"subtypes": [
"Turtle"
],
...
}
]
}
/types
Get All Types
require 'mtg_sdk'
types = MTG::Type.all
from mtgsdk import Type
types = Type.all()
curl "https://api.magicthegathering.io/v1/types"
{
"types":[
"Artifact",
"Conspiracy",
"Creature",
"Enchantment",
"Instant",
"Land",
"Phenomenon",
"Plane",
"Planeswalker",
"Scheme",
"Sorcery",
"Tribal",
"Vanguard"
]
}
/subtypes
Get All Sub Types
require 'mtg_sdk'
subtypes = MTG::Subtype.all
from mtgsdk import Subtype
subtypes = Subtype.all()
curl "https://api.magicthegathering.io/v1/subtypes"
{
"subtypes":[
"Advisor",
"Ajani",
"Alara",
"Ally",
"Angel",
"Antelope",
"Ape",
"Arcane"
]
}
/supertypes
Get All Super Types
require 'mtg_sdk'
supertypes = MTG::Supertype.all
from mtgsdk import Supertype
supertypes = Supertype.all()
curl "https://api.magicthegathering.io/v1/supertypes"
{
"supertypes":[
"Basic",
"Legendary",
"Ongoing",
"Snow",
"World"
]
}
/formats
Get All Game Formats
{
"formats": [
"Amonkhet Block",
"Battle for Zendikar Block",
"Classic",
"Commander",
"Extended",
"Freeform",
"Ice Age Block",
"Innistrad Block",
"Invasion Block",
"Kaladesh Block",
"Kamigawa Block",
"Khans of Tarkir Block",
"Legacy",
"Lorwyn-Shadowmoor Block",
"Masques Block",
"Mirage Block",
"Mirrodin Block",
"Modern",
"Odyssey Block",
"Onslaught Block",
"Prismatic",
"Ravnica Block",
"Return to Ravnica Block",
"Scars of Mirrodin Block",
"Shadows over Innistrad Block",
"Shards of Alara Block",
"Singleton 100",
"Standard",
"Tempest Block",
"Theros Block",
"Time Spiral Block",
"Tribal Wars Legacy",
"Un-Sets",
"Urza Block",
"Vintage",
"Zendikar Block"
]
}
Find by foreign name
Get Cards by Foriegn Name
Returns cards by name
require 'mtg_sdk'
cards = MTG::Card.where(name: 'Arcángel Avacyn')
.where(language: 'spanish')
.all
from mtgsdk import Card
cards = Card.where(name='Arcángel Avacyn')
.where(language='spanish')
.all()
const mtg = require('mtgsdk')
mtg.card.where({name: 'Arcángel Avacyn', language: 'spanish'})
.then(results => {
console.log(results)
})
curl "https://api.magicthegathering.io/v1/cards?name=Arcángel Avacyn&language=spanish"
{
"cards":[
{
"name":"Archangel Avacyn",
"names":[
"Archangel Avacyn",
"Avacyn, the Purifier"
],
"manaCost":"{3}{W}{W}",
"cmc":5,
...
]
}
Find by name
Get Cards by Name
Returns cards by name
require 'mtg_sdk'
# partial name match
cards = MTG::Card.where(name: 'avacyn').all
# exact name mtch
cards = MTG::Card.where(name: '"Archangel Avacyn"').all
from mtgsdk import Card
# partial name match
cards = Card.where(name='avacyn').all()
# exact name match
cards = Card.where(name='"Archangel Avacyn"').all()
const mtg = require('mtgsdk')
// partial name match
mtg.card.where({name: 'Archangel Avacyn'})
.then(results => {
console.log(results)
})
// exact name match
mtg.card.where({name: '"Archangel Avacyn"'})
.then(results => {
console.log(results)
})
# partial name match
curl "https://api.magicthegathering.io/v1/cards?name=avacyn"
# exact name match
curl 'https://api.magicthegathering.io/v1/cards?name="Archangel Avacyn"'
{
"cards":[
{
"name":"Archangel Avacyn",
"names":[
"Archangel Avacyn",
"Avacyn, the Purifier"
],
"manaCost":"{3}{W}{W}",
"cmc":5,
...
]
}