# General

Загальні операції (профіль, замовлення, довідники)

## Створити та сплатити замовлення

`POST /user/api/orders/purchase`

```json
{
  "tags": [
    "General"
  ],
  "summary": "Створити та сплатити замовлення",
  "description": "Купівля на ім'я продукту, локації та циклу.\nДля Datacenter/ISP - location обов'язковий.\nДля Standart Residential Proxy location не потрібно.\n",
  "requestBody": {
    "required": true,
    "content": {
      "application/json": {
        "schema": {
          "oneOf": [
            {
              "$ref": "#/components/schemas/PurchaseRequestDcIsp"
            },
            {
              "$ref": "#/components/schemas/PurchaseRequestResidentialStandard"
            },
            {
              "$ref": "#/components/schemas/PurchaseRequestResidentialPremium"
            },
            {
              "$ref": "#/components/schemas/PurchaseRequestResidentialUnmetered"
            },
            {
              "$ref": "#/components/schemas/PurchaseRequest"
            }
          ]
        }
      }
    }
  },
  "responses": {
    "200": {
      "description": "Успішно",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/PurchaseResponse"
          }
        }
      }
    },
    "400": {
      "description": "Помилка валідації/балансу/недолік стоку",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/ApiError"
          }
        }
      }
    },
    "401": {
      "description": "Неавторизований",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/ApiError"
          }
        }
      }
    }
  }
}
```

## Розрахувати вартість замовлення

`GET /user/api/orders/calculate`

```json
{
  "tags": [
    "General"
  ],
  "summary": "Розрахувати вартість замовлення",
  "description": "Розраховує ціну за назвою продукту, назвою циклу та кількістю. Використовує ті самі правила перевірки, що й покупка (дозволені платіжні цикли, правила рекламної акції).",
  "parameters": [
    {
      "in": "query",
      "name": "product",
      "required": true,
      "schema": {
        "type": "string"
      }
    },
    {
      "in": "query",
      "name": "location",
      "required": false,
      "schema": {
        "type": "string",
        "nullable": true
      }
    },
    {
      "in": "query",
      "name": "cycle",
      "required": false,
      "schema": {
        "type": "string",
        "nullable": true
      }
    },
    {
      "in": "query",
      "name": "quantity",
      "required": false,
      "schema": {
        "type": "integer",
        "nullable": true
      }
    },
    {
      "in": "query",
      "name": "promo_code",
      "required": false,
      "schema": {
        "type": "string",
        "nullable": true
      }
    },
    {
      "in": "query",
      "name": "addons_json",
      "required": false,
      "description": "Масив JSON із кодуванням URL-адреси доповнень, напр. [{\"addon_key\":\"p0f_slots\",\"qty\":5}]",
      "schema": {
        "type": "string",
        "nullable": true
      }
    }
  ],
  "responses": {
    "200": {
      "description": "Успіх",
      "content": {
        "application/json": {
          "schema": {
            "type": "object",
            "properties": {
              "original_price": {
                "type": "integer"
              },
              "final_price": {
                "type": "integer"
              },
              "discount_percent": {
                "type": "integer"
              },
              "addons_price": {
                "type": "integer",
                "description": "Загальна вартість додаткових компонентів у мінімальних одиницях"
              },
              "total_with_addons": {
                "type": "integer",
                "description": "final_price + addons_price"
              }
            }
          }
        }
      }
    },
    "400": {
      "description": "Помилка підтвердження",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/ApiError"
          }
        }
      }
    },
    "401": {
      "description": "Потрібна авторизація",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/ApiError"
          }
        }
      }
    }
  }
}
```

## Змінити платіжний цикл замовлення

`POST /user/api/orders/change-billing-cycle/{order_id}`

```json
{
  "tags": [
    "General"
  ],
  "summary": "Змінити платіжний цикл замовлення",
  "description": "Змінює цикл оплати за назвою циклу. Тільки для Datacenter & ISP проксі.\nЯкщо промокод недоступний для вибраного циклу, він буде автоматично скинутий.\n",
  "parameters": [
    {
      "in": "path",
      "name": "order_id",
      "required": true,
      "schema": {
        "type": "integer"
      }
    }
  ],
  "requestBody": {
    "required": true,
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "cycle": {
              "type": "string"
            }
          },
          "required": [
            "cycle"
          ]
        }
      }
    }
  },
  "responses": {
    "200": {
      "description": "Успішно",
      "content": {
        "application/json": {
          "schema": {
            "type": "object",
            "properties": {
              "success": {
                "type": "boolean"
              },
              "message": {
                "type": "string"
              },
              "order_id": {
                "type": "integer"
              },
              "original_price": {
                "type": "integer"
              },
              "final_price": {
                "type": "integer"
              },
              "discount_percent": {
                "type": "integer"
              }
            }
          }
        }
      }
    },
    "400": {
      "description": "Неправильний продукт чи цикл",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/ApiError"
          }
        }
      }
    },
    "401": {
      "description": "Неавторизований",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/ApiError"
          }
        }
      }
    },
    "403": {
      "description": "Цикл недоступний для цього користувача",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/ApiError"
          }
        }
      }
    }
  }
}
```

## Змінити автопродовження замовлення

`POST /user/api/orders/edit-auto-renewal/{order_id}`

```json
{
  "tags": [
    "General"
  ],
  "summary": "Змінити автопродовження замовлення",
  "description": "Увімкнути/вимкнути авто-продовження. Тільки для Datacenter & ISP проксі.\n",
  "parameters": [
    {
      "in": "path",
      "name": "order_id",
      "required": true,
      "schema": {
        "type": "integer"
      }
    },
    {
      "in": "query",
      "name": "auto_renewal",
      "required": true,
      "schema": {
        "type": "boolean"
      }
    }
  ],
  "responses": {
    "200": {
      "description": "Успішно",
      "content": {
        "application/json": {
          "schema": {
            "type": "object",
            "properties": {
              "success": {
                "type": "boolean"
              },
              "message": {
                "type": "string"
              }
            }
          }
        }
      }
    },
    "400": {
      "description": "Неправильний продукт для операції",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/ApiError"
          }
        }
      }
    },
    "401": {
      "description": "Неавторизований",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/ApiError"
          }
        }
      }
    }
  }
}
```

## Отримати продукти та їх цикли

`GET /user/api/proxies/products`

```json
{
  "tags": [
    "General"
  ],
  "summary": "Отримати продукти та їх цикли",
  "description": "Повертає продукти API з назвами доступних циклів.",
  "responses": {
    "200": {
      "description": "Список продуктів",
      "content": {
        "application/json": {
          "schema": {
            "type": "object",
            "properties": {
              "success": {
                "type": "boolean"
              },
              "products": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/ProductWithCycles"
                }
              }
            },
            "required": [
              "success",
              "products"
            ]
          }
        }
      }
    }
  }
}
```

## Отримати кількість доступних проксі

`GET /user/api/proxies/available-count`

```json
{
  "tags": [
    "General"
  ],
  "summary": "Отримати кількість доступних проксі",
  "description": "Повертає доступну сумарну кількість для всіх продуктів.",
  "responses": {
    "200": {
      "description": "Успішно",
      "content": {
        "application/json": {
          "schema": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AvailableCountResponse"
            }
          }
        }
      }
    }
  }
}
```

## Інформація про користувача

`GET /user/api/me`

```json
{
  "tags": [
    "General"
  ],
  "summary": "Інформація про користувача",
  "responses": {
    "200": {
      "description": "Дані профілю",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/ApiMeResponse"
          }
        }
      }
    }
  }
}
```

## Список замовлень

`GET /user/api/orders`

```json
{
  "tags": [
    "General"
  ],
  "summary": "Список замовлень",
  "parameters": [
    {
      "in": "query",
      "name": "status",
      "required": true,
      "description": "активний | на утриманні | скасовано | все",
      "schema": {
        "type": "string"
      }
    },
    {
      "in": "query",
      "name": "offset",
      "required": false,
      "description": "Зміщення вибірки (за умовчанням 0)",
      "schema": {
        "type": "integer",
        "minimum": 0
      }
    },
    {
      "in": "query",
      "name": "limit",
      "required": false,
      "description": "Розмір сторінки (1..100, за замовчуванням 20)",
      "schema": {
        "type": "integer",
        "minimum": 1,
        "maximum": 100
      }
    }
  ],
  "responses": {
    "200": {
      "description": "Список замовлень",
      "content": {
        "application/json": {
          "schema": {
            "type": "object",
            "properties": {
              "success": {
                "type": "boolean"
              },
              "orders": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "order_id": {
                      "type": "integer"
                    },
                    "product_id": {
                      "type": "integer"
                    },
                    "product_name": {
                      "type": "string"
                    },
                    "cycle_id": {
                      "type": "integer"
                    },
                    "cycle_name": {
                      "type": "string"
                    },
                    "expires_at": {
                      "type": "string",
                      "nullable": true,
                      "description": "ISO8601 час закінчення"
                    },
                    "auto_renewal": {
                      "type": "boolean",
                      "nullable": true
                    },
                    "tag": {
                      "type": "string",
                      "nullable": true
                    }
                  },
                  "required": [
                    "order_id",
                    "product_id",
                    "product_name",
                    "cycle_id",
                    "cycle_name"
                  ]
                }
              },
              "count": {
                "type": "integer",
                "description": "Кількість замовлень у поточній вибірці"
              },
              "prev": {
                "type": "string",
                "nullable": true,
                "description": "URI попередньої сторінки"
              },
              "next": {
                "type": "string",
                "nullable": true,
                "description": "URI наступної сторінки"
              }
            },
            "required": [
              "success",
              "orders"
            ]
          }
        }
      }
    }
  }
}
```

## Отримати інформацію про замовлення

`GET /user/api/orders/{id}`

```json
{
  "tags": [
    "General"
  ],
  "summary": "Отримати інформацію про замовлення",
  "parameters": [
    {
      "in": "path",
      "name": "id",
      "required": true,
      "schema": {
        "type": "integer"
      }
    }
  ],
  "responses": {
    "200": {
      "description": "Інформація про замовлення",
      "content": {
        "application/json": {
          "schema": {
            "type": "object",
            "properties": {
              "success": {
                "type": "boolean"
              },
              "order": {
                "type": "object",
                "properties": {
                  "order_id": {
                    "type": "integer"
                  },
                  "product_name": {
                    "type": "string"
                  },
                  "cycle_name": {
                    "type": "string"
                  },
                  "quantity": {
                    "type": "integer"
                  },
                  "price_paid": {
                    "type": "integer",
                    "description": "Базова ціна підписки в центах"
                  },
                  "addons_price_paid": {
                    "type": "integer",
                    "description": "Загальна додаткова вартість у центах"
                  },
                  "addons": {
                    "type": "array",
                    "description": "Додаткові рядки додаються до цього замовлення",
                    "items": {
                      "$ref": "#/components/schemas/AddonLine"
                    }
                  },
                  "p0f_slots_available": {
                    "type": "integer",
                    "description": "Активні слоти для підпису p0f (з надбудов)"
                  },
                  "p0f_slots_used": {
                    "type": "integer",
                    "description": "Слоти, наразі зайняті підписаними проксі-серверами"
                  },
                  "p0f_slots_next": {
                    "type": "integer",
                    "description": "Слоти, які будуть активні після наступного оновлення"
                  },
                  "status": {
                    "type": "string"
                  },
                  "created_at": {
                    "type": "string",
                    "nullable": true
                  },
                  "expires_at": {
                    "type": "string",
                    "nullable": true
                  },
                  "promo_code": {
                    "type": "string",
                    "nullable": true
                  },
                  "auto_renewal": {
                    "type": "boolean",
                    "nullable": true
                  },
                  "tag": {
                    "type": "string",
                    "nullable": true
                  }
                }
              }
            },
            "required": [
              "success",
              "order"
            ]
          }
        }
      }
    }
  }
}
```

## Продовжити замовлення

`POST /user/api/orders/{id}/renew`

```json
{
  "tags": [
    "General"
  ],
  "summary": "Продовжити замовлення",
  "description": "Поновлення доступне тільки при статусі замовлення `on-hold`.",
  "parameters": [
    {
      "in": "path",
      "name": "id",
      "required": true,
      "schema": {
        "type": "integer"
      }
    }
  ],
  "responses": {
    "200": {
      "description": "Успішно",
      "content": {
        "application/json": {
          "schema": {
            "type": "object",
            "properties": {
              "success": {
                "type": "boolean"
              },
              "message": {
                "type": "string",
                "example": "Order renewed successfully"
              }
            },
            "required": [
              "success",
              "message"
            ]
          }
        }
      }
    },
    "400": {
      "description": "Недостатній баланс/валідація",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/ApiError"
          }
        }
      }
    }
  }
}
```

## Змінити тег замовлення

`POST /user/api/orders/{id}/tag`

```json
{
  "tags": [
    "General"
  ],
  "summary": "Змінити тег замовлення",
  "parameters": [
    {
      "in": "path",
      "name": "id",
      "required": true,
      "schema": {
        "type": "integer"
      }
    }
  ],
  "requestBody": {
    "required": true,
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "tag": {
              "type": "string"
            }
          },
          "required": [
            "tag"
          ]
        }
      }
    }
  },
  "responses": {
    "200": {
      "description": "Успішно",
      "content": {
        "application/json": {
          "schema": {
            "type": "object",
            "properties": {
              "success": {
                "type": "boolean"
              },
              "message": {
                "type": "string",
                "example": "Order tag updated"
              }
            },
            "required": [
              "success",
              "message"
            ]
          }
        }
      }
    }
  }
}
```
