{
  "openapi": "3.1.0",
  "info": {
    "title": "Kardilo Catalogue API",
    "version": "1.0.0",
    "description": "Read-only partner catalogue. Exchange approved Auth0 client credentials for a bearer token with catalog:read. No prices or personal collections."
  },
  "servers": [
    {
      "url": "https://kardilo.com/api/v1"
    }
  ],
  "security": [
    {
      "catalogueBearer": []
    }
  ],
  "paths": {
    "/catalog/sets": {
      "get": {
        "operationId": "listSets",
        "summary": "List all sets across all release zones",
        "tags": [
          "Catalogue"
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "Successful catalogue read",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Set"
                      }
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Invalid query parameters."
          },
          "401": {
            "description": "Missing, invalid, expired or insufficient-scope catalogue bearer token.",
            "headers": {
              "WWW-Authenticate": {
                "schema": {
                  "type": "string"
                },
                "description": "Bearer challenge with a resource_metadata URL for authentication discovery."
              }
            }
          }
        }
      }
    },
    "/catalog/sets/{code}/cards": {
      "get": {
        "operationId": "listSetCards",
        "summary": "List a page of cards using a returned set code or full set ID",
        "tags": [
          "Catalogue"
        ],
        "parameters": [
          {
            "name": "code",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1
            }
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "default": 1
            }
          },
          {
            "name": "pageSize",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "default": 50
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful catalogue read",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Card"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/Page"
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Invalid query parameters."
          },
          "401": {
            "description": "Missing, invalid, expired or insufficient-scope catalogue bearer token.",
            "headers": {
              "WWW-Authenticate": {
                "schema": {
                  "type": "string"
                },
                "description": "Bearer challenge with a resource_metadata URL for authentication discovery."
              }
            }
          },
          "404": {
            "description": "The set or card is not in the active catalogue."
          }
        }
      }
    },
    "/catalog/cards/{cardId}": {
      "get": {
        "operationId": "getCard",
        "summary": "Get a card by its full returned catalogue ID",
        "tags": [
          "Catalogue"
        ],
        "parameters": [
          {
            "name": "cardId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful catalogue read",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Card"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Invalid query parameters."
          },
          "401": {
            "description": "Missing, invalid, expired or insufficient-scope catalogue bearer token.",
            "headers": {
              "WWW-Authenticate": {
                "schema": {
                  "type": "string"
                },
                "description": "Bearer challenge with a resource_metadata URL for authentication discovery."
              }
            }
          },
          "404": {
            "description": "The set or card is not in the active catalogue."
          }
        }
      }
    },
    "/catalog/search": {
      "get": {
        "operationId": "searchCards",
        "summary": "Search catalogue text in normalized printed-number order",
        "tags": [
          "Catalogue"
        ],
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 2,
              "maxLength": 200
            }
          },
          {
            "name": "zone",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "intl",
                "jp",
                "chn"
              ]
            }
          },
          {
            "name": "set",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 50
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 25
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful catalogue read",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Card"
                      }
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Invalid query parameters."
          },
          "401": {
            "description": "Missing, invalid, expired or insufficient-scope catalogue bearer token.",
            "headers": {
              "WWW-Authenticate": {
                "schema": {
                  "type": "string"
                },
                "description": "Bearer challenge with a resource_metadata URL for authentication discovery."
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "catalogueBearer": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "JWT",
        "description": "Requires catalog:read. Audience: https://kardilo.com/api/v1/mcp, for both REST and MCP."
      }
    },
    "schemas": {
      "Card": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "minLength": 1
          },
          "name": {
            "type": "string",
            "minLength": 1
          },
          "setName": {
            "type": "string",
            "minLength": 1
          },
          "setCode": {
            "type": "string",
            "minLength": 1
          },
          "number": {
            "type": "string",
            "minLength": 1
          },
          "language": {
            "type": "string",
            "minLength": 2
          },
          "year": {
            "type": "integer",
            "minimum": 1996,
            "maximum": 9007199254740991
          },
          "variant": {
            "default": "standard",
            "type": "string"
          },
          "rarity": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100
          },
          "imageUrl": {
            "type": "string",
            "format": "uri"
          },
          "zone": {
            "type": "string",
            "enum": [
              "intl",
              "jp",
              "chn"
            ]
          },
          "totalCards": {
            "anyOf": [
              {
                "type": "integer",
                "exclusiveMinimum": 0,
                "maximum": 9007199254740991
              },
              {
                "type": "null"
              }
            ]
          },
          "illustrator": {
            "anyOf": [
              {
                "type": "string",
                "minLength": 1
              },
              {
                "type": "null"
              }
            ]
          },
          "cardmarketId": {
            "anyOf": [
              {
                "type": "string",
                "minLength": 1
              },
              {
                "type": "null"
              }
            ]
          },
          "cardmarketPath": {
            "anyOf": [
              {
                "type": "string",
                "minLength": 1
              },
              {
                "type": "null"
              }
            ]
          },
          "tcgplayerId": {
            "anyOf": [
              {
                "type": "string",
                "minLength": 1
              },
              {
                "type": "null"
              }
            ]
          },
          "scanFallbackUrl": {
            "anyOf": [
              {
                "type": "string",
                "format": "uri"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": [
          "id",
          "name",
          "setName",
          "setCode",
          "number",
          "language",
          "variant",
          "zone"
        ],
        "additionalProperties": false
      },
      "Set": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "minLength": 1
          },
          "code": {
            "type": "string",
            "minLength": 1
          },
          "name": {
            "type": "string",
            "minLength": 1
          },
          "zone": {
            "type": "string",
            "enum": [
              "intl",
              "jp",
              "chn"
            ]
          },
          "releasedOn": {
            "type": "string",
            "format": "date",
            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
          },
          "cardCount": {
            "type": "integer",
            "minimum": 0,
            "maximum": 9007199254740991
          }
        },
        "required": [
          "id",
          "code",
          "name",
          "zone",
          "cardCount"
        ],
        "additionalProperties": false
      },
      "Page": {
        "type": "object",
        "properties": {
          "page": {
            "type": "integer",
            "exclusiveMinimum": 0,
            "maximum": 9007199254740991
          },
          "pageSize": {
            "type": "integer",
            "exclusiveMinimum": 0,
            "maximum": 9007199254740991
          },
          "total": {
            "type": "integer",
            "minimum": 0,
            "maximum": 9007199254740991
          }
        },
        "required": [
          "page",
          "pageSize",
          "total"
        ],
        "additionalProperties": false
      }
    }
  }
}
