# General

General operations (profile, orders, reference data)

## Create and pay for an order

`POST /user/api/orders/purchase`

```json
{
  "tags": [
    "General"
  ],
  "summary": "Create and pay for an order",
  "description": "Purchase by product name, location, and cycle. For Datacenter/ISP, location is required. For Standart Residential Proxy, location is not required.",
  "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": "Success",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/PurchaseResponse"
          }
        }
      }
    },
    "400": {
      "description": "Validation/balance error/insufficient stock",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/ApiError"
          }
        }
      }
    },
    "401": {
      "description": "Unauthorized",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/ApiError"
          }
        }
      }
    }
  }
}
```

## Calculate order cost

`GET /user/api/orders/calculate`

```json
{
  "tags": [
    "General"
  ],
  "summary": "Calculate order cost",
  "description": "Calculates price by product name, cycle name and quantity. Uses the same validation rules as purchase (allowed billing cycles, promo rules).",
  "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": "URL-encoded JSON array of add-ons, e.g. [{\"addon_key\":\"p0f_slots\",\"qty\":5}]",
      "schema": {
        "type": "string",
        "nullable": true
      }
    }
  ],
  "responses": {
    "200": {
      "description": "Success",
      "content": {
        "application/json": {
          "schema": {
            "type": "object",
            "properties": {
              "original_price": {
                "type": "integer"
              },
              "final_price": {
                "type": "integer"
              },
              "discount_percent": {
                "type": "integer"
              },
              "addons_price": {
                "type": "integer",
                "description": "Add-ons total, minor units"
              },
              "total_with_addons": {
                "type": "integer",
                "description": "final_price + addons_price"
              }
            }
          }
        }
      }
    },
    "400": {
      "description": "Validation error",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/ApiError"
          }
        }
      }
    },
    "401": {
      "description": "Unauthorized",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/ApiError"
          }
        }
      }
    }
  }
}
```

## Change the order billing cycle

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

```json
{
  "tags": [
    "General"
  ],
  "summary": "Change the order billing cycle",
  "description": "Changes the billing cycle by cycle name. Only for Datacenter & ISP proxies. If the promo code is not available for the selected cycle, it will be automatically reset.",
  "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": "Success",
      "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": "Invalid product or cycle",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/ApiError"
          }
        }
      }
    },
    "401": {
      "description": "Unauthorized",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/ApiError"
          }
        }
      }
    },
    "403": {
      "description": "Cycle is not available for this user",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/ApiError"
          }
        }
      }
    }
  }
}
```

## Change order auto-renewal

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

```json
{
  "tags": [
    "General"
  ],
  "summary": "Change order auto-renewal",
  "description": "Enable/disable auto-renewal. Only for Datacenter & ISP proxies.",
  "parameters": [
    {
      "in": "path",
      "name": "order_id",
      "required": true,
      "schema": {
        "type": "integer"
      }
    },
    {
      "in": "query",
      "name": "auto_renewal",
      "required": true,
      "schema": {
        "type": "boolean"
      }
    }
  ],
  "responses": {
    "200": {
      "description": "Success",
      "content": {
        "application/json": {
          "schema": {
            "type": "object",
            "properties": {
              "success": {
                "type": "boolean"
              },
              "message": {
                "type": "string"
              }
            }
          }
        }
      }
    },
    "400": {
      "description": "Invalid product for this operation",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/ApiError"
          }
        }
      }
    },
    "401": {
      "description": "Unauthorized",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/ApiError"
          }
        }
      }
    }
  }
}
```

## Get products and their cycles

`GET /user/api/proxies/products`

```json
{
  "tags": [
    "General"
  ],
  "summary": "Get products and their cycles",
  "description": "Returns API products with the names of available cycles.",
  "responses": {
    "200": {
      "description": "Product list",
      "content": {
        "application/json": {
          "schema": {
            "type": "object",
            "properties": {
              "success": {
                "type": "boolean"
              },
              "products": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/ProductWithCycles"
                }
              }
            },
            "required": [
              "success",
              "products"
            ]
          }
        }
      }
    }
  }
}
```

## Get available proxy count

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

```json
{
  "tags": [
    "General"
  ],
  "summary": "Get available proxy count",
  "description": "Returns the total available quantity for all products.",
  "responses": {
    "200": {
      "description": "Success",
      "content": {
        "application/json": {
          "schema": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AvailableCountResponse"
            }
          }
        }
      }
    }
  }
}
```

## User information

`GET /user/api/me`

```json
{
  "tags": [
    "General"
  ],
  "summary": "User information",
  "responses": {
    "200": {
      "description": "Profile data",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/ApiMeResponse"
          }
        }
      }
    }
  }
}
```

## Order list

`GET /user/api/orders`

```json
{
  "tags": [
    "General"
  ],
  "summary": "Order list",
  "parameters": [
    {
      "in": "query",
      "name": "status",
      "required": true,
      "description": "active | on-hold | cancelled | all",
      "schema": {
        "type": "string"
      }
    },
    {
      "in": "query",
      "name": "offset",
      "required": false,
      "description": "Result offset (default 0)",
      "schema": {
        "type": "integer",
        "minimum": 0
      }
    },
    {
      "in": "query",
      "name": "limit",
      "required": false,
      "description": "Page size (1..100, default 20)",
      "schema": {
        "type": "integer",
        "minimum": 1,
        "maximum": 100
      }
    }
  ],
  "responses": {
    "200": {
      "description": "Order list",
      "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 expiration time"
                    },
                    "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": "Number of orders in the current result set"
              },
              "prev": {
                "type": "string",
                "nullable": true,
                "description": "Previous page URI"
              },
              "next": {
                "type": "string",
                "nullable": true,
                "description": "Next page URI"
              }
            },
            "required": [
              "success",
              "orders"
            ]
          }
        }
      }
    }
  }
}
```

## Get order information

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

```json
{
  "tags": [
    "General"
  ],
  "summary": "Get order information",
  "parameters": [
    {
      "in": "path",
      "name": "id",
      "required": true,
      "schema": {
        "type": "integer"
      }
    }
  ],
  "responses": {
    "200": {
      "description": "Order information",
      "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": "Base subscription price in cents"
                  },
                  "addons_price_paid": {
                    "type": "integer",
                    "description": "Total add-on cost in cents"
                  },
                  "addons": {
                    "type": "array",
                    "description": "Add-on lines attached to this order",
                    "items": {
                      "$ref": "#/components/schemas/AddonLine"
                    }
                  },
                  "p0f_slots_available": {
                    "type": "integer",
                    "description": "Active p0f signature slots (from add-ons)"
                  },
                  "p0f_slots_used": {
                    "type": "integer",
                    "description": "Slots currently occupied by signed proxies"
                  },
                  "p0f_slots_next": {
                    "type": "integer",
                    "description": "Slots that will be active after next renewal"
                  },
                  "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"
            ]
          }
        }
      }
    }
  }
}
```

## Renew order

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

```json
{
  "tags": [
    "General"
  ],
  "summary": "Renew order",
  "description": "Renewal is available only when order status is `on-hold`.",
  "parameters": [
    {
      "in": "path",
      "name": "id",
      "required": true,
      "schema": {
        "type": "integer"
      }
    }
  ],
  "responses": {
    "200": {
      "description": "Success",
      "content": {
        "application/json": {
          "schema": {
            "type": "object",
            "properties": {
              "success": {
                "type": "boolean"
              },
              "message": {
                "type": "string",
                "example": "Order renewed successfully"
              }
            },
            "required": [
              "success",
              "message"
            ]
          }
        }
      }
    },
    "400": {
      "description": "Insufficient balance/validation",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/ApiError"
          }
        }
      }
    }
  }
}
```

## Change order tag

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

```json
{
  "tags": [
    "General"
  ],
  "summary": "Change order tag",
  "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": "Success",
      "content": {
        "application/json": {
          "schema": {
            "type": "object",
            "properties": {
              "success": {
                "type": "boolean"
              },
              "message": {
                "type": "string",
                "example": "Order tag updated"
              }
            },
            "required": [
              "success",
              "message"
            ]
          }
        }
      }
    }
  }
}
```
