{
  "openapi": "3.1.0",
  "info": {
    "title": "The Puzzle Section API",
    "version": "1.0.0",
    "description": "Enterprise-grade Puzzles as a Service (PaaS) API for digital publishers, print newspapers, and gaming platforms.\n\n## Authentication\n\nAll API requests require authentication via an API key passed in the `Authorization` header:\n\n```\nAuthorization: Bearer ps_live_xxxxxxxxxxxx\n```\n\n## Rate Limiting\n\nRate limits are applied per API key based on your subscription tier:\n\n| Tier | Requests/Minute | Requests/Month |\n|------|-----------------|----------------|\n| Free | 60 | 1,000 |\n| Starter | 300 | 50,000 |\n| Professional | 1,000 | 500,000 |\n| Enterprise | Custom | Unlimited |\n\nRate limit headers are included in all responses:\n- `X-RateLimit-Limit`: Maximum requests per window\n- `X-RateLimit-Remaining`: Remaining requests in current window\n- `X-RateLimit-Reset`: Unix timestamp when the window resets",
    "contact": {
      "name": "The Puzzle Section Support",
      "email": "support@puzzlesection.app",
      "url": "https://dashboard.puzzlesection.app/docs"
    },
    "license": {
      "name": "Proprietary"
    }
  },
  "servers": [
    {
      "url": "https://api.puzzlesection.app",
      "description": "Production"
    },
    {
      "url": "https://sandbox.puzzlesection.app",
      "description": "Sandbox"
    },
    {
      "url": "http://localhost:3000",
      "description": "Local Development"
    }
  ],
  "tags": [
    { "name": "Puzzles", "description": "Puzzle retrieval and gameplay" },
    { "name": "Users", "description": "User management and profiles" },
    { "name": "Progress", "description": "Puzzle progress and completions" },
    { "name": "Leaderboards", "description": "Rankings and leaderboards" },
    { "name": "Print", "description": "Batch puzzle generation for print publishing" }
  ],
  "paths": {
    "/v1/puzzles/{type}/daily": {
      "get": {
        "tags": ["Puzzles"],
        "summary": "Get daily puzzle",
        "description": "Retrieve today's puzzle for a specific puzzle type.",
        "operationId": "getDailyPuzzle",
        "parameters": [
          {
            "name": "type",
            "in": "path",
            "required": true,
            "description": "The puzzle type (e.g., sudoku, crossword, wordsearch)",
            "schema": {
              "type": "string",
              "enum": ["sudoku", "crossword", "wordsearch", "nonogram", "kakuro", "slitherlink"]
            }
          },
          {
            "name": "difficulty",
            "in": "query",
            "required": false,
            "description": "Filter by difficulty level",
            "schema": {
              "type": "string",
              "enum": ["easy", "medium", "hard", "expert"]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Daily puzzle retrieved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PuzzleResponse"
                }
              }
            }
          },
          "404": {
            "description": "Puzzle not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [{ "BearerAuth": [] }]
      }
    },
    "/v1/puzzles/{id}": {
      "get": {
        "tags": ["Puzzles"],
        "summary": "Get puzzle by ID",
        "description": "Retrieve a specific puzzle by its unique identifier.",
        "operationId": "getPuzzleById",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The puzzle ID",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Puzzle retrieved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PuzzleResponse"
                }
              }
            }
          },
          "404": {
            "description": "Puzzle not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [{ "BearerAuth": [] }]
      }
    },
    "/v1/puzzles/{type}/archive": {
      "get": {
        "tags": ["Puzzles"],
        "summary": "Get puzzle archive",
        "description": "Retrieve historical puzzles for a specific type with pagination.",
        "operationId": "getPuzzleArchive",
        "parameters": [
          {
            "name": "type",
            "in": "path",
            "required": true,
            "description": "The puzzle type",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 1
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 20,
              "maximum": 100
            }
          },
          {
            "name": "difficulty",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": ["easy", "medium", "hard", "expert"]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Archive retrieved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PuzzleListResponse"
                }
              }
            }
          }
        },
        "security": [{ "BearerAuth": [] }]
      }
    },
    "/v1/users": {
      "post": {
        "tags": ["Users"],
        "summary": "Create user",
        "description": "Create a new user in your tenant. Users are scoped to your API key.",
        "operationId": "createUser",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateUserRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "User created successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UserResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [{ "BearerAuth": [] }]
      }
    },
    "/v1/users/{userId}": {
      "get": {
        "tags": ["Users"],
        "summary": "Get user",
        "description": "Retrieve a user by their Puzzle Section ID or external ID.",
        "operationId": "getUser",
        "parameters": [
          {
            "name": "userId",
            "in": "path",
            "required": true,
            "description": "User ID (prefix with 'ext:' for external IDs)",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "User retrieved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UserResponse"
                }
              }
            }
          },
          "404": {
            "description": "User not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [{ "BearerAuth": [] }]
      },
      "put": {
        "tags": ["Users"],
        "summary": "Update user",
        "description": "Update an existing user's profile.",
        "operationId": "updateUser",
        "parameters": [
          {
            "name": "userId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateUserRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "User updated successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UserResponse"
                }
              }
            }
          }
        },
        "security": [{ "BearerAuth": [] }]
      },
      "delete": {
        "tags": ["Users"],
        "summary": "Delete user",
        "description": "Delete a user and all associated data. This action is irreversible.",
        "operationId": "deleteUser",
        "parameters": [
          {
            "name": "userId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "User deleted successfully"
          },
          "404": {
            "description": "User not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [{ "BearerAuth": [] }]
      }
    },
    "/v1/progress": {
      "post": {
        "tags": ["Progress"],
        "summary": "Save progress",
        "description": "Save puzzle progress for a user. Creates or updates existing progress.",
        "operationId": "saveProgress",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SaveProgressRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Progress saved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProgressResponse"
                }
              }
            }
          }
        },
        "security": [{ "BearerAuth": [] }]
      }
    },
    "/v1/progress/{userId}/{puzzleId}": {
      "get": {
        "tags": ["Progress"],
        "summary": "Get progress",
        "description": "Retrieve puzzle progress for a specific user and puzzle.",
        "operationId": "getProgress",
        "parameters": [
          {
            "name": "userId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "puzzleId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Progress retrieved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProgressResponse"
                }
              }
            }
          },
          "404": {
            "description": "Progress not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [{ "BearerAuth": [] }]
      }
    },
    "/v1/leaderboards/{puzzleId}": {
      "get": {
        "tags": ["Leaderboards"],
        "summary": "Get puzzle leaderboard",
        "description": "Retrieve the leaderboard for a specific puzzle.",
        "operationId": "getPuzzleLeaderboard",
        "parameters": [
          {
            "name": "puzzleId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 10,
              "maximum": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Leaderboard retrieved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LeaderboardResponse"
                }
              }
            }
          }
        },
        "security": [{ "BearerAuth": [] }]
      }
    },
    "/v1/print/pdf": {
      "post": {
        "tags": ["Print"],
        "summary": "Generate print-ready PDF",
        "description": "Generate a print-ready PDF for a puzzle with customizable layout options.",
        "operationId": "generatePrintPdf",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PrintPdfRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "PDF generated successfully",
            "content": {
              "application/pdf": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          }
        },
        "security": [{ "BearerAuth": [] }]
      }
    },
    "/v1/print/bulk": {
      "post": {
        "tags": ["Print"],
        "summary": "Generate bulk print package",
        "description": "Generate multiple puzzles for print publication (e.g., weekly newspaper supplement).",
        "operationId": "generateBulkPrint",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BulkPrintRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Bulk package generated successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BulkPrintResponse"
                }
              }
            }
          }
        },
        "security": [{ "BearerAuth": [] }]
      }
    }
  },
  "components": {
    "securitySchemes": {
      "BearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "API Key",
        "description": "API key authentication. Use your API key as the bearer token."
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "required": ["error"],
        "properties": {
          "error": {
            "type": "object",
            "required": ["code", "message"],
            "properties": {
              "code": {
                "type": "string",
                "description": "Machine-readable error code"
              },
              "message": {
                "type": "string",
                "description": "Human-readable error message"
              },
              "details": {
                "type": "object",
                "description": "Additional error details"
              }
            }
          }
        }
      },
      "Puzzle": {
        "type": "object",
        "required": ["id", "type", "difficulty", "date"],
        "properties": {
          "id": {
            "type": "string",
            "description": "Unique puzzle identifier"
          },
          "type": {
            "type": "string",
            "description": "Puzzle type",
            "enum": ["sudoku", "crossword", "wordsearch", "nonogram", "kakuro", "slitherlink"]
          },
          "difficulty": {
            "type": "string",
            "enum": ["easy", "medium", "hard", "expert"]
          },
          "date": {
            "type": "string",
            "format": "date",
            "description": "Publication date (YYYY-MM-DD)"
          },
          "grid": {
            "type": "array",
            "description": "Puzzle grid data (format varies by puzzle type)"
          },
          "solution": {
            "type": "array",
            "description": "Puzzle solution (only included if requested)"
          },
          "metadata": {
            "type": "object",
            "properties": {
              "title": { "type": "string" },
              "author": { "type": "string" },
              "estimatedTime": { "type": "integer", "description": "Estimated solve time in seconds" }
            }
          }
        }
      },
      "PuzzleResponse": {
        "type": "object",
        "required": ["data"],
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Puzzle"
          }
        }
      },
      "PuzzleListResponse": {
        "type": "object",
        "required": ["data", "pagination"],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Puzzle"
            }
          },
          "pagination": {
            "$ref": "#/components/schemas/Pagination"
          }
        }
      },
      "Pagination": {
        "type": "object",
        "properties": {
          "page": { "type": "integer" },
          "limit": { "type": "integer" },
          "total": { "type": "integer" },
          "totalPages": { "type": "integer" }
        }
      },
      "User": {
        "type": "object",
        "required": ["id"],
        "properties": {
          "id": {
            "type": "string",
            "description": "Puzzle Section user ID"
          },
          "externalId": {
            "type": "string",
            "description": "Your system's user ID"
          },
          "displayName": {
            "type": "string"
          },
          "email": {
            "type": "string",
            "format": "email"
          },
          "metadata": {
            "type": "object",
            "description": "Custom metadata for your application"
          },
          "statistics": {
            "$ref": "#/components/schemas/UserStatistics"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "UserStatistics": {
        "type": "object",
        "properties": {
          "puzzlesCompleted": { "type": "integer" },
          "totalScore": { "type": "integer" },
          "averageTime": { "type": "integer", "description": "Average solve time in seconds" },
          "currentStreak": { "type": "integer" },
          "longestStreak": { "type": "integer" }
        }
      },
      "UserResponse": {
        "type": "object",
        "required": ["data"],
        "properties": {
          "data": {
            "$ref": "#/components/schemas/User"
          }
        }
      },
      "CreateUserRequest": {
        "type": "object",
        "required": ["externalId"],
        "properties": {
          "externalId": {
            "type": "string",
            "description": "Your system's unique identifier for this user"
          },
          "displayName": {
            "type": "string"
          },
          "email": {
            "type": "string",
            "format": "email"
          },
          "metadata": {
            "type": "object"
          }
        }
      },
      "UpdateUserRequest": {
        "type": "object",
        "properties": {
          "displayName": {
            "type": "string"
          },
          "email": {
            "type": "string",
            "format": "email"
          },
          "metadata": {
            "type": "object"
          }
        }
      },
      "Progress": {
        "type": "object",
        "properties": {
          "userId": { "type": "string" },
          "puzzleId": { "type": "string" },
          "state": {
            "type": "object",
            "description": "Current puzzle state"
          },
          "timeSpent": {
            "type": "integer",
            "description": "Time spent in seconds"
          },
          "hintsUsed": {
            "type": "integer"
          },
          "completed": {
            "type": "boolean"
          },
          "score": {
            "type": "integer"
          },
          "completedAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "ProgressResponse": {
        "type": "object",
        "required": ["data"],
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Progress"
          }
        }
      },
      "SaveProgressRequest": {
        "type": "object",
        "required": ["userId", "puzzleId", "state"],
        "properties": {
          "userId": { "type": "string" },
          "puzzleId": { "type": "string" },
          "state": {
            "type": "object",
            "description": "Current puzzle state to save"
          },
          "timeSpent": {
            "type": "integer",
            "description": "Total time spent in seconds"
          },
          "completed": {
            "type": "boolean",
            "default": false
          }
        }
      },
      "LeaderboardEntry": {
        "type": "object",
        "properties": {
          "rank": { "type": "integer" },
          "userId": { "type": "string" },
          "displayName": { "type": "string" },
          "score": { "type": "integer" },
          "timeSpent": { "type": "integer" },
          "completedAt": { "type": "string", "format": "date-time" }
        }
      },
      "LeaderboardResponse": {
        "type": "object",
        "required": ["data"],
        "properties": {
          "data": {
            "type": "object",
            "properties": {
              "puzzleId": { "type": "string" },
              "entries": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/LeaderboardEntry"
                }
              }
            }
          }
        }
      },
      "PrintPdfRequest": {
        "type": "object",
        "required": ["puzzleId"],
        "properties": {
          "puzzleId": { "type": "string" },
          "options": {
            "type": "object",
            "properties": {
              "pageSize": {
                "type": "string",
                "enum": ["A4", "Letter", "Tabloid"],
                "default": "A4"
              },
              "includeSolution": {
                "type": "boolean",
                "default": false
              },
              "cellSize": {
                "type": "number",
                "description": "Cell size in mm"
              }
            }
          }
        }
      },
      "BulkPrintRequest": {
        "type": "object",
        "required": ["puzzles"],
        "properties": {
          "puzzles": {
            "type": "array",
            "items": {
              "type": "object",
              "required": ["type", "difficulty"],
              "properties": {
                "type": { "type": "string" },
                "difficulty": { "type": "string" },
                "count": { "type": "integer", "default": 1 }
              }
            }
          },
          "format": {
            "type": "string",
            "enum": ["pdf", "zip"],
            "default": "zip"
          }
        }
      },
      "BulkPrintResponse": {
        "type": "object",
        "properties": {
          "data": {
            "type": "object",
            "properties": {
              "downloadUrl": { "type": "string" },
              "expiresAt": { "type": "string", "format": "date-time" },
              "puzzleCount": { "type": "integer" }
            }
          }
        }
      }
    }
  }
}
