{
  "openapi": "3.0.3",
  "info": {
    "title": "Pizza API Lab",
    "version": "1.0.0",
    "description": "Вымышленная пиццерия. Начните с POST /sessions, вставьте token в Authorize. Токен действует 24 часа. Каждый студент работает со своими заказами. Данные, цены и роли учебные."
  },
  "servers": [
    {
      "url": "/api",
      "description": "Этот учебный сайт"
    }
  ],
  "tags": [
    {
      "name": "Старт"
    },
    {
      "name": "Меню"
    },
    {
      "name": "Заказы"
    },
    {
      "name": "Ошибки"
    },
    {
      "name": "Отчёты"
    }
  ],
  "paths": {
    "/sessions": {
      "post": {
        "tags": [
          "Старт"
        ],
        "summary": "Создать сессию без регистрации",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": false,
                "example": {}
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Новая сессия",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "token": {
                      "type": "string"
                    },
                    "session_id": {
                      "type": "string"
                    },
                    "expires_at": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Ошибка 400",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Ошибка 429",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/session": {
      "get": {
        "tags": [
          "Старт"
        ],
        "summary": "Проверить свой токен",
        "security": [
          {
            "StudentToken": []
          }
        ],
        "responses": {
          "200": {
            "description": "Сессия",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "session_id": {
                      "type": "string"
                    },
                    "expires_at": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Ошибка 401",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/session/data": {
      "delete": {
        "tags": [
          "Старт"
        ],
        "summary": "Удалить только свои заказы и отчёты",
        "security": [
          {
            "StudentToken": []
          }
        ],
        "responses": {
          "200": {
            "description": "Удалено",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Ошибка 401",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/menu": {
      "get": {
        "tags": [
          "Меню"
        ],
        "summary": "Получить меню",
        "parameters": [
          {
            "name": "category",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "pizza",
                "drink"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Меню",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "items": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Dish"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/orders": {
      "get": {
        "tags": [
          "Заказы"
        ],
        "summary": "Мои заказы",
        "security": [
          {
            "StudentToken": []
          }
        ],
        "responses": {
          "200": {
            "description": "Заказы",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "items": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Order"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Ошибка 401",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Заказы"
        ],
        "summary": "Создать заказ или получить результат повтора",
        "security": [
          {
            "StudentToken": []
          }
        ],
        "description": "Лимит 60 заказов. Тот же ключ и тело → 200 и прежний ID. Тот же ключ с другими данными → 409.",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 100,
              "pattern": "^[A-Za-z0-9_.:-]+$"
            },
            "example": "lesson-01"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "dish_id",
                  "quantity"
                ],
                "properties": {
                  "dish_id": {
                    "type": "integer",
                    "enum": [
                      7,
                      8,
                      9
                    ],
                    "example": 7
                  },
                  "quantity": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 10,
                    "example": 2
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Повтор",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Order"
                }
              }
            }
          },
          "201": {
            "description": "Создан",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Order"
                }
              }
            }
          },
          "400": {
            "description": "Ошибка 400",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Ошибка 401",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Ошибка 409",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Ошибка 429",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/orders/{id}": {
      "get": {
        "tags": [
          "Заказы"
        ],
        "summary": "Прочитать заказ",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "security": [
          {
            "StudentToken": []
          }
        ],
        "responses": {
          "200": {
            "description": "Заказ",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Order"
                }
              }
            }
          },
          "401": {
            "description": "Ошибка 401",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Ошибка 403",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Ошибка 404",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/instructor": {
      "get": {
        "tags": [
          "Ошибки"
        ],
        "summary": "Для учебной роли student всегда 403",
        "security": [
          {
            "StudentToken": []
          }
        ],
        "responses": {
          "401": {
            "description": "Ошибка 401",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Ошибка 403",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/reports": {
      "post": {
        "tags": [
          "Отчёты"
        ],
        "summary": "Начать отчёт · имитация ожидания",
        "security": [
          {
            "StudentToken": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": false,
                "example": {}
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Принят",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "processing"
                      ]
                    },
                    "status_url": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Ошибка 401",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Ошибка 429",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/reports/{id}": {
      "get": {
        "tags": [
          "Отчёты"
        ],
        "summary": "Через 3 секунды ready · снимок числа заказов на момент POST",
        "security": [
          {
            "StudentToken": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Состояние",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "processing",
                        "ready"
                      ]
                    },
                    "order_count": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Ошибка 401",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Ошибка 403",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Ошибка 404",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "StudentToken": {
        "type": "http",
        "scheme": "bearer",
        "description": "Только учебный токен из POST /sessions. Без слова Bearer."
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string"
          },
          "message": {
            "type": "string"
          }
        },
        "required": [
          "error",
          "message"
        ]
      },
      "Dish": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "name": {
            "type": "string"
          },
          "category": {
            "type": "string"
          },
          "price": {
            "type": "integer"
          },
          "currency": {
            "type": "string"
          }
        }
      },
      "Order": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "dish_id": {
            "type": "integer"
          },
          "quantity": {
            "type": "integer"
          },
          "total": {
            "type": "integer"
          },
          "currency": {
            "type": "string",
            "enum": [
              "RUB"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "created"
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "dish_id",
          "quantity",
          "total",
          "currency",
          "status"
        ]
      }
    }
  }
}