{
  "openapi": "3.1.0",
  "info": {
    "title": "Runeterra Legal Public API",
    "version": "1.0.0",
    "description": "Read-only Region Expressions legality API. Server-to-server only; browser CORS is not enabled."
  },
  "servers": [
    {
      "url": "/",
      "description": "Current deployment origin"
    }
  ],
  "security": [
    {
      "bearerAuth": []
    }
  ],
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "rl_live"
      }
    },
    "headers": {
      "RateLimitLimit": {
        "description": "Account request limit for the current minute window.",
        "schema": {
          "type": "integer",
          "minimum": 1
        }
      },
      "RateLimitRemaining": {
        "description": "Account requests remaining in the current minute window.",
        "schema": {
          "type": "integer",
          "minimum": 0
        }
      },
      "RateLimitLimitDay": {
        "description": "Account request limit for the current rolling day window.",
        "schema": {
          "type": "integer",
          "minimum": 1
        }
      },
      "RateLimitRemainingDay": {
        "description": "Account requests remaining in the current rolling day window.",
        "schema": {
          "type": "integer",
          "minimum": 0
        }
      },
      "RetryAfter": {
        "description": "Seconds until the limiting window can accept another request.",
        "schema": {
          "type": "integer",
          "minimum": 1
        }
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "success",
          "code",
          "error"
        ],
        "properties": {
          "success": {
            "const": false
          },
          "code": {
            "type": "string",
            "enum": [
              "unauthorized",
              "rate_limited",
              "invalid_request",
              "invalid_deck_code",
              "unsupported_media_type",
              "payload_too_large",
              "not_found",
              "method_not_allowed",
              "unconfigured",
              "unavailable"
            ]
          },
          "error": {
            "type": "string"
          }
        }
      },
      "LegalityStatus": {
        "type": "string",
        "description": "needs_designation is returned only when an unresolved Expression designation is the sole legality blocker.",
        "enum": [
          "legal",
          "illegal",
          "needs_designation"
        ]
      },
      "Designation": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "definitionId"
        ],
        "properties": {
          "definitionId": {
            "type": "string",
            "minLength": 1,
            "maxLength": 128
          }
        }
      },
      "DeckCheckRequest": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "deckCode"
        ],
        "properties": {
          "deckCode": {
            "type": "string",
            "minLength": 1,
            "maxLength": 256
          },
          "designations": {
            "type": "array",
            "maxItems": 16,
            "items": {
              "$ref": "#/components/schemas/Designation"
            }
          }
        }
      },
      "LineupCheckRequest": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "deckCodes"
        ],
        "properties": {
          "deckCodes": {
            "type": "array",
            "minItems": 3,
            "maxItems": 3,
            "prefixItems": [
              {
                "type": "string",
                "minLength": 1,
                "maxLength": 256
              },
              {
                "type": "string",
                "minLength": 1,
                "maxLength": 256
              },
              {
                "type": "string",
                "minLength": 1,
                "maxLength": 256
              }
            ]
          },
          "designations": {
            "type": "array",
            "maxItems": 3,
            "prefixItems": [
              {
                "type": "array",
                "maxItems": 16,
                "items": {
                  "$ref": "#/components/schemas/Designation"
                }
              },
              {
                "type": "array",
                "maxItems": 16,
                "items": {
                  "$ref": "#/components/schemas/Designation"
                }
              },
              {
                "type": "array",
                "maxItems": 16,
                "items": {
                  "$ref": "#/components/schemas/Designation"
                }
              }
            ]
          }
        }
      },
      "Expression": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "name",
          "region"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "region": {
            "type": "string"
          }
        }
      },
      "ExpressionState": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "region",
          "status",
          "expressions",
          "candidates",
          "cardCodes"
        ],
        "properties": {
          "region": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "none",
              "inferred",
              "requires-choice",
              "designated",
              "conflicting"
            ]
          },
          "expressions": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Expression"
            }
          },
          "candidates": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Expression"
            }
          },
          "cardCodes": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "designatedExpression": {
            "$ref": "#/components/schemas/Expression"
          }
        }
      },
      "CardInfo": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "code",
          "name"
        ],
        "properties": {
          "code": {
            "type": "string"
          },
          "name": {
            "type": "string"
          }
        }
      },
      "ClientViolation": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "kind",
          "message"
        ],
        "properties": {
          "kind": {
            "type": "string",
            "enum": [
              "unknown-card",
              "noncollectible-card",
              "format-card",
              "deck-size",
              "copy-limit",
              "champion-limit",
              "region-origin"
            ]
          },
          "message": {
            "type": "string"
          },
          "cardCodes": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "RuleViolation": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "ruleId",
          "ruleName",
          "ruleType",
          "triggerCards",
          "forbiddenCards"
        ],
        "properties": {
          "ruleId": {
            "type": "string"
          },
          "ruleName": {
            "type": "string"
          },
          "ruleType": {
            "type": "string",
            "enum": [
              "if-then",
              "cross-region",
              "system"
            ]
          },
          "triggerCards": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CardInfo"
            }
          },
          "forbiddenCards": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CardInfo"
            }
          }
        }
      },
      "ValidationDataVersion": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "formatVersion",
          "catalogRevision",
          "catalogDigest",
          "membershipRevision",
          "legalityContractVersion"
        ],
        "properties": {
          "formatVersion": {
            "type": "integer",
            "minimum": 0
          },
          "catalogRevision": {
            "type": "string",
            "minLength": 1
          },
          "catalogDigest": {
            "type": "string",
            "minLength": 1
          },
          "membershipRevision": {
            "type": "string",
            "minLength": 1
          },
          "legalityContractVersion": {
            "type": "integer",
            "minimum": 1
          }
        }
      },
      "DeckCheckResult": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "status",
          "legal",
          "clientLegal",
          "tournamentLegal",
          "complete",
          "format",
          "formatVersion",
          "catalogRevision",
          "validationData",
          "clientIdentities",
          "clientViolations",
          "expressionStates",
          "violations"
        ],
        "properties": {
          "status": {
            "$ref": "#/components/schemas/LegalityStatus"
          },
          "legal": {
            "type": "boolean"
          },
          "clientLegal": {
            "type": "boolean"
          },
          "tournamentLegal": {
            "type": "boolean"
          },
          "complete": {
            "type": "boolean"
          },
          "format": {
            "const": "Eternal"
          },
          "formatVersion": {
            "type": "integer",
            "minimum": 0
          },
          "catalogRevision": {
            "type": "string"
          },
          "validationData": {
            "$ref": "#/components/schemas/ValidationDataVersion"
          },
          "clientIdentities": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "clientViolations": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ClientViolation"
            }
          },
          "expressionStates": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ExpressionState"
            }
          },
          "violations": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/RuleViolation"
            }
          }
        }
      },
      "DeckCheckResponse": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "success",
          "result"
        ],
        "properties": {
          "success": {
            "const": true
          },
          "result": {
            "$ref": "#/components/schemas/DeckCheckResult"
          }
        }
      },
      "CardOverlap": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "cardCode",
          "deckIndices"
        ],
        "properties": {
          "cardCode": {
            "type": "string"
          },
          "cardName": {
            "type": "string"
          },
          "deckIndices": {
            "type": "array",
            "items": {
              "type": "integer",
              "minimum": 1,
              "maximum": 3
            }
          }
        }
      },
      "LineupDeck": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "deckIndex",
          "deckCode",
          "result"
        ],
        "properties": {
          "deckIndex": {
            "type": "integer",
            "minimum": 1,
            "maximum": 3
          },
          "deckCode": {
            "type": "string"
          },
          "result": {
            "$ref": "#/components/schemas/DeckCheckResult"
          }
        }
      },
      "LineupCheckResult": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "status",
          "lineupLegal",
          "cardLocked",
          "format",
          "formatVersion",
          "catalogRevision",
          "validationData",
          "cardOverlaps",
          "decks"
        ],
        "properties": {
          "status": {
            "$ref": "#/components/schemas/LegalityStatus"
          },
          "lineupLegal": {
            "type": "boolean"
          },
          "cardLocked": {
            "type": "boolean"
          },
          "format": {
            "const": "Eternal"
          },
          "formatVersion": {
            "type": "integer",
            "minimum": 0
          },
          "catalogRevision": {
            "type": "string"
          },
          "validationData": {
            "$ref": "#/components/schemas/ValidationDataVersion"
          },
          "cardOverlaps": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CardOverlap"
            }
          },
          "decks": {
            "type": "array",
            "minItems": 3,
            "maxItems": 3,
            "items": {
              "$ref": "#/components/schemas/LineupDeck"
            }
          }
        }
      },
      "LineupCheckResponse": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "success",
          "result"
        ],
        "properties": {
          "success": {
            "const": true
          },
          "result": {
            "$ref": "#/components/schemas/LineupCheckResult"
          }
        }
      },
      "FormatSettings": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "oneExpressionPerRegion",
          "cardLockedLineup"
        ],
        "properties": {
          "oneExpressionPerRegion": {
            "type": "boolean"
          },
          "cardLockedLineup": {
            "type": "boolean"
          }
        }
      },
      "ExampleCard": {
        "type": [
          "object",
          "null"
        ],
        "required": [
          "code",
          "name"
        ],
        "properties": {
          "code": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "imageUrl": {
            "type": "string"
          },
          "fullImageUrl": {
            "type": "string"
          }
        }
      },
      "ExpressionDefinition": {
        "type": "object",
        "required": [
          "id",
          "name",
          "region",
          "regionRef",
          "iconShape",
          "createdAt",
          "updatedAt"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "region": {
            "type": "string"
          },
          "regionRef": {
            "type": "string"
          },
          "iconShape": {
            "type": "string",
            "enum": [
              "circle",
              "triangle",
              "square"
            ]
          },
          "description": {
            "type": "string"
          },
          "rationale": {
            "type": "string"
          },
          "mechanicsSummary": {
            "type": "string"
          },
          "exampleCardCode": {
            "type": "string"
          },
          "exampleCard": {
            "$ref": "#/components/schemas/ExampleCard"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "TaggedCard": {
        "type": "object",
        "required": [
          "cardCode",
          "cardName",
          "expressions",
          "isNew",
          "updatedAt"
        ],
        "properties": {
          "cardCode": {
            "type": "string"
          },
          "cardName": {
            "type": "string"
          },
          "expressions": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Expression"
            }
          },
          "isNew": {
            "type": "boolean"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          },
          "imageUrl": {
            "type": "string"
          },
          "fullImageUrl": {
            "type": "string"
          }
        }
      },
      "RuleCondition": {
        "type": "object",
        "properties": {
          "cardCodes": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "regions": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "expressions": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Expression"
            }
          }
        }
      },
      "CrossRegionConfig": {
        "type": "object",
        "required": [
          "regionA",
          "expressionA",
          "regionB",
          "expressionB"
        ],
        "properties": {
          "regionA": {
            "type": "string"
          },
          "expressionA": {
            "$ref": "#/components/schemas/Expression"
          },
          "regionB": {
            "type": "string"
          },
          "expressionB": {
            "$ref": "#/components/schemas/Expression"
          },
          "incompatibilitySummary": {
            "type": "string"
          },
          "exampleCardCodeA": {
            "type": "string"
          },
          "exampleCardCodeB": {
            "type": "string"
          },
          "rationale": {
            "type": "string"
          }
        }
      },
      "Rule": {
        "type": "object",
        "required": [
          "id",
          "name",
          "description",
          "ifCondition",
          "thenForbid",
          "enabled",
          "createdAt",
          "updatedAt"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "ruleType": {
            "type": "string",
            "enum": [
              "if-then",
              "cross-region"
            ]
          },
          "ifCondition": {
            "$ref": "#/components/schemas/RuleCondition"
          },
          "thenForbid": {
            "$ref": "#/components/schemas/RuleCondition"
          },
          "crossRegionConfig": {
            "$ref": "#/components/schemas/CrossRegionConfig"
          },
          "enabled": {
            "type": "boolean"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "CrossRegionRestriction": {
        "type": "object",
        "required": [
          "ruleId",
          "ruleName",
          "regionA",
          "expressionA",
          "regionB",
          "expressionB",
          "reasoning"
        ],
        "properties": {
          "ruleId": {
            "type": "string"
          },
          "ruleName": {
            "type": "string"
          },
          "regionA": {
            "type": "string"
          },
          "expressionA": {
            "type": "string"
          },
          "regionB": {
            "type": "string"
          },
          "expressionB": {
            "type": "string"
          },
          "reasoning": {
            "type": "string"
          },
          "incompatibilitySummary": {
            "type": "string"
          },
          "rationale": {
            "type": "string"
          },
          "exampleCardA": {
            "$ref": "#/components/schemas/ExampleCard"
          },
          "exampleCardB": {
            "$ref": "#/components/schemas/ExampleCard"
          }
        }
      },
      "FormatResult": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "version",
          "catalogRevision",
          "validationData",
          "formatSettings",
          "expressionDefinitions",
          "taggedCards",
          "crossRegionRestrictions",
          "rules"
        ],
        "properties": {
          "version": {
            "type": "integer",
            "minimum": 0
          },
          "publishedAt": {
            "type": "string",
            "format": "date-time"
          },
          "catalogRevision": {
            "type": "string"
          },
          "validationData": {
            "$ref": "#/components/schemas/ValidationDataVersion"
          },
          "formatSettings": {
            "$ref": "#/components/schemas/FormatSettings"
          },
          "expressionDefinitions": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ExpressionDefinition"
            }
          },
          "taggedCards": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TaggedCard"
            }
          },
          "crossRegionRestrictions": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CrossRegionRestriction"
            }
          },
          "rules": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Rule"
            }
          }
        }
      },
      "FormatResponse": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "success",
          "result"
        ],
        "properties": {
          "success": {
            "const": true
          },
          "result": {
            "$ref": "#/components/schemas/FormatResult"
          }
        }
      }
    },
    "responses": {
      "InvalidRequest": {
        "description": "Invalid request body or deck code.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Unauthorized": {
        "description": "Missing or invalid API key.",
        "headers": {
          "WWW-Authenticate": {
            "schema": {
              "type": "string",
              "const": "Bearer"
            }
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "RateLimited": {
        "description": "Account, invalid-token, or global rate limit exceeded.",
        "headers": {
          "Retry-After": {
            "$ref": "#/components/headers/RetryAfter"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "PayloadTooLarge": {
        "description": "Request body exceeds 16 KiB.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "UnsupportedMediaType": {
        "description": "Content-Type must be application/json.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Unavailable": {
        "description": "The API is disabled, unconfigured, or temporarily unavailable.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      }
    }
  },
  "paths": {
    "/api/v1/decks/check": {
      "post": {
        "operationId": "checkDeck",
        "summary": "Check one deck code",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DeckCheckRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Deck legality result.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Limit-Day": {
                "$ref": "#/components/headers/RateLimitLimitDay"
              },
              "X-RateLimit-Remaining-Day": {
                "$ref": "#/components/headers/RateLimitRemainingDay"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeckCheckResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "413": {
            "$ref": "#/components/responses/PayloadTooLarge"
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/api/v1/lineups/check": {
      "post": {
        "operationId": "checkLineup",
        "summary": "Check an exactly three-deck lineup",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/LineupCheckRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Lineup legality result.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Limit-Day": {
                "$ref": "#/components/headers/RateLimitLimitDay"
              },
              "X-RateLimit-Remaining-Day": {
                "$ref": "#/components/headers/RateLimitRemainingDay"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LineupCheckResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "413": {
            "$ref": "#/components/responses/PayloadTooLarge"
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/api/v1/format": {
      "get": {
        "operationId": "getFormat",
        "summary": "Get the published format snapshot",
        "responses": {
          "200": {
            "description": "Published tags, rules, settings, and version.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Limit-Day": {
                "$ref": "#/components/headers/RateLimitLimitDay"
              },
              "X-RateLimit-Remaining-Day": {
                "$ref": "#/components/headers/RateLimitRemainingDay"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FormatResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    }
  }
}
