Opening Hands
Overview
Every opening hand recorded on Play Nice, grouped by commander, with the result of the game it was kept in.
Authenticate with your partner key in an Authorization: Bearer header.
Endpoint
GET https://api.playnicemtg.com/v1/hands
Authorization: Bearer YOUR_PARTNER_KEYGet the hands
GET/v1/hands
No parameters. The response is the full dataset.
Cache it on your side. The data is rebuilt once a day, so fetching more often returns the same result.
Request
curl https://api.playnicemtg.com/v1/hands \
-H 'Authorization: Bearer YOUR_PARTNER_KEY'Response
An object keyed by commander name, sorted A–Z. Each value is that commander's list of hands.
- Names are Scryfall card names.
- Partner pairs are both names joined by
/, e.g.Kraum, Ludevic's Opus / Tymna the Weaver.
Response · 200
{
"Kinnan, Bonder Prodigy": [
{
"date": "2026-10-12T19:30:00.000Z",
"isWin": true,
"isLoss": false,
"isDraw": false,
"isTournament": true,
"cards": [
"bd3d4b4b-cf31-4f89-8140-9650edb03c7b",
"c8817585-0d32-4d56-9142-0d29512e86a9",
"0afa0e33-4804-4b00-b625-c2d6b61090fc"
],
"endingTurn": 4,
"mulliganSize": 7,
"seatPosition": 2
}
],
"Kraum, Ludevic's Opus / Tymna the Weaver": [
{
"date": "2026-10-11T18:05:00.000Z",
"isWin": false,
"isLoss": true,
"isDraw": false,
"isTournament": false,
"cards": ["…"],
"endingTurn": null,
"mulliganSize": 6,
"seatPosition": 1
}
]
}Hand fields
| Field | Type | Description |
|---|---|---|
cards | string[] | The hand as Scryfall card ids, 1–7 cards. |
mulliganSize | number | Cards kept: 7 for a seven on the first or second hand, otherwise 1–6. 0 when not recorded. |
isWin | boolean | The player who kept the hand won. |
isLoss | boolean | They didn't win and the game wasn't a draw. |
isDraw | boolean | The game was a draw. |
isTournament | boolean | A tournament, TopDeck.gg tournament or league game. |
endingTurn | number | null | The turn the game ended. null when not recorded. |
seatPosition | number | The player's seat, 1–5. |
date | string | When the game was played, ISO 8601. |
Which hands are included
- Published games where the player who recorded the game entered their opening hand.
- Each hand is that player's own. Opponents' hands aren't recorded.
- Games with an unknown deck are left out.
Errors
| Status | Body | What to do |
|---|---|---|
| 200 | message | No hands are available yet. Keep your cached copy and try again later. |
| 401 | message | Check the partner key. |
| 500 | error | Temporary. Retry later. |
Check for message before reading the data. A 200 with no hands has the same status as a full response.
No hands · 200
{
"message": "No Play Nice games with opening hands found. Please try again."
}Response · 401
{
"message": "Invalid API key."
}Response · 500
{
"error": "Failed to fetch opening hands"
}