{
  "info": {
    "name": "Sleeved Public API",
    "description": "Sleeved public API v1 — card data browsing, deck export, and share tokens for integration partners.",
    "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
  },
  "auth": {
    "type": "apikey",
    "apikey": [
      {
        "key": "key",
        "value": "X-API-Key",
        "type": "string"
      },
      {
        "key": "value",
        "value": "{{api_key}}",
        "type": "string"
      },
      {
        "key": "in",
        "value": "header",
        "type": "string"
      }
    ]
  },
  "variable": [
    {
      "key": "base_url",
      "value": "https://api.sleeved.gg/api/v1",
      "type": "string"
    },
    {
      "key": "api_key",
      "value": "slvd_live_your_key_here",
      "type": "string"
    },
    {
      "key": "game_slug",
      "value": "digimon",
      "type": "string"
    },
    {
      "key": "deck_id",
      "value": "",
      "type": "string"
    },
    {
      "key": "share_token",
      "value": "",
      "type": "string"
    }
  ],
  "item": [
    {
      "name": "Games",
      "item": [
        {
          "name": "List Available Games",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/games",
              "host": ["{{base_url}}"],
              "path": ["games"]
            },
            "description": "Returns all games supported by the public API with their slugs and Algolia index names.\n\nValid slugs: `digimon`, `gundam`, `grand-archive`, `chrono-core`"
          },
          "response": [
            {
              "name": "200 OK",
              "status": "OK",
              "code": 200,
              "header": [
                { "key": "Content-Type", "value": "application/json" }
              ],
              "body": "{\n  \"data\": [\n    {\n      \"id\": \"digimon\",\n      \"displayName\": \"Digimon Card Game\",\n      \"algoliaIndexName\": \"digimon_cards\"\n    },\n    {\n      \"id\": \"gundam\",\n      \"displayName\": \"Gundam Card Game\",\n      \"algoliaIndexName\": \"gundam_cards\"\n    },\n    {\n      \"id\": \"grand-archive\",\n      \"displayName\": \"Grand Archive TCG\",\n      \"algoliaIndexName\": \"grand_archive_cards\"\n    },\n    {\n      \"id\": \"chrono-core\",\n      \"displayName\": \"Chrono Core TCG\",\n      \"algoliaIndexName\": \"chrono_core_cards\"\n    }\n  ]\n}"
            }
          ]
        },
        {
          "name": "Get Game Sync Metadata",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/games/{{game_slug}}/meta",
              "host": ["{{base_url}}"],
              "path": ["games", "{{game_slug}}", "meta"]
            },
            "description": "Returns card count and last sync timestamp for a game. Use this to decide whether your local index needs updating."
          },
          "response": [
            {
              "name": "200 OK",
              "status": "OK",
              "code": 200,
              "header": [
                { "key": "Content-Type", "value": "application/json" }
              ],
              "body": "{\n  \"data\": {\n    \"cardCount\": 4821,\n    \"lastUpdatedAt\": \"2025-10-14T08:32:00.000Z\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Browse All Cards (Paginated)",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/games/{{game_slug}}/cards?hitsPerPage=100",
              "host": ["{{base_url}}"],
              "path": ["games", "{{game_slug}}", "cards"],
              "query": [
                {
                  "key": "hitsPerPage",
                  "value": "100",
                  "description": "Records per page (1–1000, default 100)"
                },
                {
                  "key": "cursor",
                  "value": "",
                  "description": "Pagination cursor from previous response. Omit on first request.",
                  "disabled": true
                }
              ]
            },
            "description": "Paginated card browse for full index sync. Iterate with the returned `cursor` until it is `null`.\n\nMax `hitsPerPage`: 1000. Use 1000 for fastest full sync."
          },
          "response": [
            {
              "name": "200 OK",
              "status": "OK",
              "code": 200,
              "header": [
                { "key": "Content-Type", "value": "application/json" }
              ],
              "body": "{\n  \"data\": {\n    \"hits\": [\n      {\n        \"id\": \"BT1-001\",\n        \"name\": \"Koromon\",\n        \"gameId\": \"digimon\"\n      }\n    ],\n    \"cursor\": \"eyJwYWdlIjoxfQ==\",\n    \"totalHits\": 4821\n  }\n}"
            }
          ]
        },
        {
          "name": "Get Single Card",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/games/{{game_slug}}/cards/BT1-001",
              "host": ["{{base_url}}"],
              "path": ["games", "{{game_slug}}", "cards", "BT1-001"]
            },
            "description": "Fetch a single card by ID. Card IDs are alphanumeric with hyphens and underscores, max 100 characters."
          },
          "response": [
            {
              "name": "200 OK",
              "status": "OK",
              "code": 200,
              "header": [
                { "key": "Content-Type", "value": "application/json" }
              ],
              "body": "{\n  \"data\": {\n    \"id\": \"BT1-001\",\n    \"name\": \"Koromon\",\n    \"gameId\": \"digimon\",\n    \"type\": \"Digimon\",\n    \"color\": \"Red\",\n    \"level\": 2\n  }\n}"
            },
            {
              "name": "400 Invalid Card ID",
              "status": "Bad Request",
              "code": 400,
              "header": [
                { "key": "Content-Type", "value": "application/json" }
              ],
              "body": "{\n  \"error\": \"Invalid card ID format\"\n}"
            }
          ]
        }
      ]
    },
    {
      "name": "Decks",
      "item": [
        {
          "name": "Get Deck (JSON)",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/decks/{{deck_id}}",
              "host": ["{{base_url}}"],
              "path": ["decks", "{{deck_id}}"],
              "query": [
                {
                  "key": "token",
                  "value": "{{share_token}}",
                  "description": "Share token for private decks. Omit for public decks.",
                  "disabled": true
                }
              ]
            },
            "description": "Fetch a deck as JSON with cards, zones, and metadata.\n\nPublic decks are accessible directly. Private decks require a `token` query parameter."
          },
          "response": [
            {
              "name": "200 OK",
              "status": "OK",
              "code": 200,
              "header": [
                { "key": "Content-Type", "value": "application/json" }
              ],
              "body": "{\n  \"data\": {\n    \"id\": \"deck_abc123\",\n    \"name\": \"Red Blitz Aggro\",\n    \"gameId\": \"digimon\",\n    \"ownerDisplayName\": \"CardShark99\",\n    \"cards\": [\n      {\n        \"cardId\": \"BT1-010\",\n        \"quantity\": 4,\n        \"zoneId\": \"main\"\n      },\n      {\n        \"cardId\": \"BT1-086\",\n        \"quantity\": 4,\n        \"zoneId\": \"egg\"\n      }\n    ],\n    \"createdAt\": \"2025-08-20T14:00:00.000Z\",\n    \"updatedAt\": \"2025-09-03T11:45:00.000Z\"\n  }\n}"
            },
            {
              "name": "404 Not Found",
              "status": "Not Found",
              "code": 404,
              "header": [
                { "key": "Content-Type", "value": "application/json" }
              ],
              "body": "{\n  \"error\": \"Deck not found or not public\"\n}"
            }
          ]
        },
        {
          "name": "Get Deck (Untap Text)",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/decks/{{deck_id}}/text?format=untap",
              "host": ["{{base_url}}"],
              "path": ["decks", "{{deck_id}}", "text"],
              "query": [
                {
                  "key": "format",
                  "value": "untap",
                  "description": "Export format: untap or limitless"
                },
                {
                  "key": "token",
                  "value": "{{share_token}}",
                  "description": "Share token for private decks.",
                  "disabled": true
                }
              ]
            },
            "description": "Export a deck as plain text in Untap format.\n\nFormat: `{qty} {cardName} ({GAME}) ({CARD-ID})` per line.\n\nGame abbreviations: DCG (Digimon), GUN (Gundam), GA (Grand Archive), CC (Chrono Core)"
          },
          "response": [
            {
              "name": "200 OK",
              "status": "OK",
              "code": 200,
              "header": [
                { "key": "Content-Type", "value": "text/plain; charset=utf-8" }
              ],
              "body": "4 Agumon (DCG) (BT1-010)\n4 Koromon (DCG) (BT1-001)\n2 Greymon (DCG) (BT1-018)"
            },
            {
              "name": "400 Missing Format",
              "status": "Bad Request",
              "code": 400,
              "header": [
                { "key": "Content-Type", "value": "application/json" }
              ],
              "body": "{\n  \"error\": \"format is required\"\n}"
            },
            {
              "name": "400 Unknown Format",
              "status": "Bad Request",
              "code": 400,
              "header": [
                { "key": "Content-Type", "value": "application/json" }
              ],
              "body": "{\n  \"error\": \"Unknown format. Supported: limitless, untap\"\n}"
            }
          ]
        },
        {
          "name": "Get Deck (Limitless Text)",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/decks/{{deck_id}}/text?format=limitless",
              "host": ["{{base_url}}"],
              "path": ["decks", "{{deck_id}}", "text"],
              "query": [
                {
                  "key": "format",
                  "value": "limitless",
                  "description": "Export format: untap or limitless"
                },
                {
                  "key": "token",
                  "value": "{{share_token}}",
                  "description": "Share token for private decks.",
                  "disabled": true
                }
              ]
            },
            "description": "Export a deck as plain text in Limitless format. The exact format varies by game."
          },
          "response": []
        },
        {
          "name": "Get Deck (Private, with Token)",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/decks/{{deck_id}}?token={{share_token}}",
              "host": ["{{base_url}}"],
              "path": ["decks", "{{deck_id}}"],
              "query": [
                {
                  "key": "token",
                  "value": "{{share_token}}",
                  "description": "24-hour share token for private deck access"
                }
              ]
            },
            "description": "Fetch a private deck using a share token. Tokens are generated by Sleeved users via the app UI and are valid for 24 hours."
          },
          "response": []
        }
      ]
    },
    {
      "name": "Errors",
      "item": [
        {
          "name": "401 — Missing API Key",
          "request": {
            "auth": { "type": "noauth" },
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/games",
              "host": ["{{base_url}}"],
              "path": ["games"]
            },
            "description": "Request without an API key to see the 401 response."
          },
          "response": [
            {
              "name": "401 API Key Required",
              "status": "Unauthorized",
              "code": 401,
              "header": [
                { "key": "Content-Type", "value": "application/json" }
              ],
              "body": "{\n  \"error\": \"API key required\"\n}"
            }
          ]
        },
        {
          "name": "429 — Rate Limit Exceeded",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/games",
              "host": ["{{base_url}}"],
              "path": ["games"]
            },
            "description": "When the per-key rate limit is exceeded (fixed 15-minute window)."
          },
          "response": [
            {
              "name": "429 Rate Limited",
              "status": "Too Many Requests",
              "code": 429,
              "header": [
                { "key": "Content-Type", "value": "application/json" }
              ],
              "body": "{\n  \"error\": \"Rate limit exceeded\"\n}"
            }
          ]
        }
      ]
    }
  ]
}
