{
  "openapi": "3.0.4",
  "info": {
    "title": "Tip4Serv API",
    "description": "Tip4Serv API",
    "termsOfService": "https://tip4serv.com/terms-of-use",
    "contact": {
      "email": "duster@tip4serv.com"
    },
    "license": {
      "name": "Apache 2.0",
      "url": "https://www.apache.org/licenses/LICENSE-2.0.html"
    },
    "version": "1.0.12"
  },
  "servers": [
    {
      "url": "https://api.tip4serv.com/v1"
    }
  ],
  "tags": [
    {
      "name": "Store",
      "description": "General operations related to the store"
    },
    {
      "name": "Servers",
      "description": "Operations related to servers"
    },
    {
      "name": "Products",
      "description": "Operations related to products"
    },
    {
      "name": "Discounts",
      "description": "Operations related to discounts"
    },
    {
      "name": "Customers",
      "description": "Operations related to customers"
    },
    {
      "name": "Checkout",
      "description": "Operations related to checkout"
    },
    {
      "name": "Payments",
      "description": "Operations related to payments"
    },
    {
      "name": "Subscriptions",
      "description": "Operations related to subscriptions"
    },
    {
      "name": "User",
      "description": "Operations related to the user account from a user viewpoint."
    },
    {
      "name": "Payments (User)",
      "description": "Operations related to payments from a user viewpoint."
    },
    {
      "name": "Subscriptions (User)",
      "description": "Operations related to subscriptions from a user viewpoint."
    }
  ],
  "security": [
    {
      "bearerAuth": []
    }
  ],
  "paths": {
    "/store/whoami": {
      "get": {
        "tags": [
          "Store"
        ],
        "summary": "Get general information about the store",
        "description": "Retrieves general information about the store, including store name, \nowner, and basic settings.\n  \n**Authorization:**\n- Requires a valid JWT Bearer token.\n",
        "operationId": "whoami",
        "responses": {
          "200": {
            "description": "Successful operation",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Store"
                }
              }
            }
          },
          "403": {
            "description": "Missing or invalid Tip4Serv API Key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Unauthorized access. Please provide a valid Tip4Serv API Key."
                    },
                    "status": {
                      "type": "number",
                      "example": 403
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Unexpected server error"
                    },
                    "status": {
                      "type": "number",
                      "example": 500
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/store/theme": {
      "get": {
        "tags": [
          "Store"
        ],
        "summary": "Get general information about the store theme",
        "description": "Retrieves general information about the store's theme, including the \ncurrent active mode, colors, and associated images.\n\n**Authorization:**\n- Requires a valid JWT Bearer token.\n",
        "operationId": "getTheme",
        "responses": {
          "200": {
            "description": "Successful operation",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Theme"
                }
              }
            }
          },
          "403": {
            "description": "Missing or invalid Tip4Serv API Key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Unauthorized access. Please provide a valid Tip4Serv API Key."
                    },
                    "status": {
                      "type": "number",
                      "example": 403
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Unexpected server error"
                    },
                    "status": {
                      "type": "number",
                      "example": 500
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/store/payments": {
      "get": {
        "tags": [
          "Payments"
        ],
        "summary": "Get payments",
        "description": "Retrieves information about your payments. Use the `page` parameter \nto paginate results. Optionally, filter by a specific \nuser using the `identifier` parameter.\n\n**Accepted identifiers:**  \n`email`, `username`, `eosid`, `ue4_id`, `steam_username`, `steam_id`,  \n`minecraft_uuid`, `discord_id`, `discord_username`,  \n`fivem_xPlayer_id`, `fivem_citizen_id`, `minecraft_username`.\n\n**Authorization:**\n- Requires a valid JWT Bearer token.\n- The token must include the permission: `read-payments`.\n",
        "operationId": "getPayments",
        "parameters": [
          {
            "name": "page",
            "in": "query",
            "description": "The page number to retrieve.",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 1
            }
          },
          {
            "name": "max_page",
            "in": "query",
            "description": "The maximum number of elements per page. This number must be between 5-50.",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 50
            }
          },
          {
            "name": "identifier",
            "in": "query",
            "description": "Specify an identifier for a user to filter subscriptions. If omitted,\npayments for all users will be included.\n",
            "schema": {
              "type": "string",
              "example": ""
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful operation",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "payments": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/PaymentGeneral"
                      }
                    },
                    "payment_count": {
                      "type": "number",
                      "example": 356
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Missing or invalid Tip4Serv API Key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Unauthorized access. Please provide a valid Tip4Serv API Key."
                    },
                    "status": {
                      "type": "number",
                      "example": 403
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Unexpected server error"
                    },
                    "status": {
                      "type": "number",
                      "example": 500
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/store/payment/{id}": {
      "get": {
        "tags": [
          "Payments"
        ],
        "summary": "Get payment",
        "description": "Retrieves information about your payment. \nUseful if you want to get the different commands to be delivered.\n\n**Authorization:**\n- Requires a valid JWT Bearer token.\n- The token must include the permission: `read-payments`.\n",
        "operationId": "getPayment",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "The payment ID to retrieve.",
            "required": true,
            "schema": {
              "type": "integer",
              "default": 10669
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful operation",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Payment"
                }
              }
            }
          },
          "403": {
            "description": "Missing or invalid Tip4Serv API Key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Unauthorized access. Please provide a valid Tip4Serv API Key."
                    },
                    "status": {
                      "type": "number",
                      "example": 403
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Unexpected server error"
                    },
                    "status": {
                      "type": "number",
                      "example": 500
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/store/subscriptions": {
      "get": {
        "tags": [
          "Subscriptions"
        ],
        "summary": "Get subscriptions",
        "description": "Retrieves information about your subscriptions. Use the `page` parameter \nto paginate results. Set `only_recurring_subscription` to `true` to \nretrieve only recurring subscriptions. Optionally, filter by a specific \nuser using the `identifier` parameter.\n\n**Accepted identifiers:**  \n`email`, `username`, `eosid`, `ue4_id`, `steam_username`, `steam_id`,  \n`minecraft_uuid`, `discord_id`, `discord_username`,  \n`fivem_xPlayer_id`, `fivem_citizen_id`, `minecraft_username`.\n\n**Authorization:**\n- Requires a valid JWT Bearer token.\n- The token must include the permission: `read-subscriptions`.\n",
        "operationId": "getSubscriptions",
        "parameters": [
          {
            "name": "page",
            "in": "query",
            "description": "The page number to retrieve.",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 1
            }
          },
          {
            "name": "max_page",
            "in": "query",
            "description": "The maximum number of elements per page. This number must be between 5-50.",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 50
            }
          },
          {
            "name": "only_recurring_subscription",
            "in": "query",
            "description": "Include only recurring subscriptions.",
            "required": false,
            "schema": {
              "type": "boolean",
              "default": false
            }
          },
          {
            "name": "identifier",
            "in": "query",
            "description": "Specify an identifier for a user to filter subscriptions. If omitted, \nsubscriptions for all users will be included.\n",
            "schema": {
              "type": "string",
              "example": ""
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful operation",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "subscriptions": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/SubscriptionGeneral"
                      }
                    },
                    "subscription_count": {
                      "type": "number",
                      "example": 120
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Missing or invalid Tip4Serv API Key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Unauthorized access. Please provide a valid Tip4Serv API Key."
                    },
                    "status": {
                      "type": "number",
                      "example": 403
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Unexpected server error"
                    },
                    "status": {
                      "type": "number",
                      "example": 500
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/store/discount/discounts": {
      "get": {
        "tags": [
          "Discounts"
        ],
        "summary": "Get store discounts",
        "description": "Retrieves general product discounts for the store.\nUse the `page` parameter to paginate results.\n\n**Authorization:**\n- Requires a valid JWT Bearer token.\n- The token must include the permission: `read-discounts`.\n",
        "operationId": "getDiscounts",
        "parameters": [
          {
            "name": "page",
            "in": "query",
            "description": "The page number to retrieve.",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 1
            }
          },
          {
            "name": "max_page",
            "in": "query",
            "description": "The maximum number of elements per page. This number must be between 5-50.",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 50
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful operation",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "discounts": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ResponseDiscount"
                      }
                    },
                    "discount_count": {
                      "type": "number",
                      "example": 12
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Missing or invalid Tip4Serv API Key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Unauthorized access. Please provide a valid Tip4Serv API Key."
                    },
                    "status": {
                      "type": "number",
                      "example": 403
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Unexpected server error"
                    },
                    "status": {
                      "type": "number",
                      "example": 500
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/store/discount/giftcard/{id}": {
      "patch": {
        "tags": [
          "Discounts",
          "Discounts"
        ],
        "summary": "Update a store gift card",
        "description": "Update a store gift card.\n\n**Authorization:**\n- Requires a valid JWT Bearer token.\n- The token must include the permission: `update-discounts`.\n",
        "operationId": "updateGiftCard",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The ID of the giftcard.",
            "schema": {
              "type": "number"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateGiftCard"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful operation",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ResponseGiftCard"
                }
              }
            }
          },
          "400": {
            "description": "Error in your request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "One of the parameters is missing or is in the wrong format."
                    },
                    "status": {
                      "type": "integer",
                      "example": 400
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Missing or invalid Tip4Serv API Key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Unauthorized access. Please provide a valid Tip4Serv API Key."
                    },
                    "status": {
                      "type": "number",
                      "example": 403
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Unexpected server error"
                    },
                    "status": {
                      "type": "number",
                      "example": 500
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/store/discount/coupon/{id}": {
      "patch": {
        "tags": [
          "Discounts"
        ],
        "summary": "Update a store coupon",
        "description": "Update a store coupon.\n\n**Authorization:**\n- Requires a valid JWT Bearer token.\n- The token must include the permission: `update-discounts`.\n",
        "operationId": "updateCoupon",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The ID of the coupon.",
            "schema": {
              "type": "number"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateCoupon"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful operation",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ResponseCoupon"
                }
              }
            }
          },
          "400": {
            "description": "Error in your request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "One of the parameters is missing or is in the wrong format."
                    },
                    "status": {
                      "type": "integer",
                      "example": 400
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Missing or invalid Tip4Serv API Key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Unauthorized access. Please provide a valid Tip4Serv API Key."
                    },
                    "status": {
                      "type": "number",
                      "example": 403
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Unexpected server error"
                    },
                    "status": {
                      "type": "number",
                      "example": 500
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/store/discount/coupon": {
      "post": {
        "tags": [
          "Discounts"
        ],
        "summary": "Create a store coupon",
        "description": "Create a new store coupon.\n\n**Authorization:**\n- Requires a valid JWT Bearer token.\n- The token must include the permission: `create-discounts`.\n",
        "operationId": "createCoupon",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateCoupon"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful operation",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ResponseCoupon"
                }
              }
            }
          },
          "400": {
            "description": "Error in your request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "One of the parameters is missing or is in the wrong format."
                    },
                    "status": {
                      "type": "integer",
                      "example": 400
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Missing or invalid Tip4Serv API Key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Unauthorized access. Please provide a valid Tip4Serv API Key."
                    },
                    "status": {
                      "type": "number",
                      "example": 403
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "Conflicting conditions",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "This coupon code already exist within your coupons."
                    },
                    "status": {
                      "type": "number",
                      "example": 409
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Unexpected server error"
                    },
                    "status": {
                      "type": "number",
                      "example": 500
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/store/discount/coupons": {
      "get": {
        "tags": [
          "Discounts"
        ],
        "summary": "Get store coupons",
        "description": "Retrieves detailed information about all of your coupons. \nUse the `page` parameter to paginate results.\n\n**Authorization:**\n- Requires a valid JWT Bearer token.\n- The token must include the permission: `read-discounts`.\n",
        "operationId": "getCoupons",
        "parameters": [
          {
            "name": "page",
            "in": "query",
            "description": "The page number to retrieve.",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 1
            }
          },
          {
            "name": "max_page",
            "in": "query",
            "description": "The maximum number of elements per page. This number must be between 5-50.",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 50
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful operation",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "coupons": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ResponseCoupon"
                      }
                    },
                    "coupon_count": {
                      "type": "number",
                      "example": 23
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Missing or invalid Tip4Serv API Key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Unauthorized access. Please provide a valid Tip4Serv API Key."
                    },
                    "status": {
                      "type": "number",
                      "example": 403
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Unexpected server error"
                    },
                    "status": {
                      "type": "number",
                      "example": 500
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/store/discount/giftcard": {
      "post": {
        "tags": [
          "Discounts",
          "Discounts"
        ],
        "summary": "Create store gift card",
        "description": "Create store gift card.\n\n**Authorization:**\n- Requires a valid JWT Bearer token.\n- The token must include the permission: `create-discounts`.\n",
        "operationId": "createGiftcard",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateGiftCard"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful operation",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ResponseGiftCard"
                }
              }
            }
          },
          "400": {
            "description": "Error in your request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "One of the parameters is missing or is in the wrong format."
                    },
                    "status": {
                      "type": "integer",
                      "example": 400
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Missing or invalid Tip4Serv API Key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Unauthorized access. Please provide a valid Tip4Serv API Key."
                    },
                    "status": {
                      "type": "number",
                      "example": 403
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Unexpected server error"
                    },
                    "status": {
                      "type": "number",
                      "example": 500
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/store/discount/giftcards": {
      "get": {
        "tags": [
          "Discounts",
          "Discounts"
        ],
        "summary": "Get store gift cards",
        "description": "Retrieves detailed information about all of your gift cards.\nUse the `page` parameter to paginate results.\n\n**Authorization:**\n- Requires a valid JWT Bearer token.\n- The token must include the permission: `read-discounts`.\n",
        "operationId": "getGiftcards",
        "parameters": [
          {
            "name": "page",
            "in": "query",
            "description": "The page number to retrieve.",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 1
            }
          },
          {
            "name": "max_page",
            "in": "query",
            "description": "The maximum number of elements per page. This number must be between 5-50.",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 50
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful operation",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "giftcards": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ResponseGiftCard"
                      }
                    },
                    "giftcard_count": {
                      "type": "number",
                      "example": 44
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Error in your request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "One of the parameters is missing or is in the wrong format."
                    },
                    "status": {
                      "type": "integer",
                      "example": 400
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Missing or invalid Tip4Serv API Key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Unauthorized access. Please provide a valid Tip4Serv API Key."
                    },
                    "status": {
                      "type": "number",
                      "example": 403
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Unexpected server error"
                    },
                    "status": {
                      "type": "number",
                      "example": 500
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/store/customers": {
      "get": {
        "tags": [
          "Customers"
        ],
        "summary": "Get customers",
        "description": "Retrieves information about all of your customers. Use the `page` parameter \nto paginate results.\n\n**Sorting:** Use the `sort` parameter to order the returned customers.\n\nAvailable criteria:  \n- `revenue` – orders customers by total revenue.\n\n**Time filtering:** Use `date_filter` to select customers within a specific time range.\nTimestamps must be expressed in your store’s timezone.\n\nFormat: `[start_timestamp, end_timestamp]`\n\nExample: `[1759333917,1761234717]` selects customers from **October 1st to October 23rd** *(Europe/Paris timezone)*\n\n**Authorization:**\n- Requires a valid JWT Bearer token.\n- The token must include the permission: `read-customers`.\n",
        "operationId": "getCustomers",
        "parameters": [
          {
            "name": "page",
            "in": "query",
            "description": "The page number to retrieve.",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 1
            }
          },
          {
            "name": "max_page",
            "in": "query",
            "description": "The maximum number of elements per page. This number must be between 5-50.",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 50
            }
          },
          {
            "name": "sort",
            "in": "query",
            "description": "Defines the **sorting criteria** used to order the returned customers.\nBy default there's no sorting.\n",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "date_filter",
            "in": "query",
            "description": "Filter customers by a specific time interval.\nProvide timestamps in your store’s timezone.\n\n**Format:** `[start_timestamp, end_timestamp]`\n\n**Example:** `[1759333917000,1761234717]` selects customers from **October 1st to October 23rd** *(Europe/Paris timezone)*\n\nBy default this filter is omitted.\n",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful operation",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "customers": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/CustomerGeneral"
                      }
                    },
                    "customer_count": {
                      "type": "number",
                      "example": 410
                    },
                    "currency": {
                      "type": "string",
                      "description": "The store's currency. All total_revenue values represent the amount spent by each customer, converted to the store currency.",
                      "example": "EUR"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Didn't provide a valid Tip4Serv API Key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Unauthorized Access, Please submit a valid Tip4Serv API Key."
                    },
                    "status": {
                      "type": "number",
                      "example": 403
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Unexpected server error"
                    },
                    "status": {
                      "type": "integer",
                      "example": 500
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/store/products": {
      "get": {
        "tags": [
          "Products"
        ],
        "summary": "Get store products",
        "description": "Retrieves information about all products in your store.\nUse the `page` parameter to paginate results.\nSet `details` to `true` to include detailed product information.\nSet `only_enabled` to `true` to retrieve only enabled products.\n\n**Authorization:**\n- Requires a valid JWT Bearer token.\n- The token must include the permission: `read-products`.\n",
        "operationId": "getProducts",
        "parameters": [
          {
            "name": "page",
            "in": "query",
            "description": "The page number to retrieve.",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 1
            }
          },
          {
            "name": "max_page",
            "in": "query",
            "description": "The maximum number of elements per page. This number must be between 5-50.",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 50
            }
          },
          {
            "name": "details",
            "in": "query",
            "description": "Enable detailed response for each product.",
            "required": false,
            "schema": {
              "type": "boolean",
              "default": false
            }
          },
          {
            "name": "only_enabled",
            "in": "query",
            "description": "Include only enabled products.",
            "required": false,
            "schema": {
              "type": "boolean",
              "default": false
            }
          },
          {
            "name": "category",
            "in": "query",
            "description": "Limit products to a specific category ID.",
            "required": false,
            "schema": {
              "type": "integer",
              "example": 18
            }
          },
          {
            "name": "currency",
            "in": "query",
            "description": "Display currency code (optional). Supported currencies: GBP, USD, EUR, CAD, AUD, CHF. If omitted, prices are displayed in store currency. Converts all product prices (price, old_price, min_donation) and custom field prices.",
            "required": false,
            "schema": {
              "type": "string",
              "example": "USD"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful operation",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "products": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ProductGeneral"
                      }
                    },
                    "product_count": {
                      "type": "number",
                      "example": 87
                    },
                    "currency": {
                      "type": "string",
                      "description": "Currency in which all prices are expressed. Matches the requested `currency` parameter, or the store's default currency if not specified.",
                      "example": "GBP"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Didn't provide a valid Tip4Serv API Key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Unauthorized Access, Please submit a valid Tip4Serv API Key."
                    },
                    "status": {
                      "type": "number",
                      "example": 403
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Unexpected server error"
                    },
                    "status": {
                      "type": "integer",
                      "example": 500
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/store/servers": {
      "get": {
        "tags": [
          "Servers"
        ],
        "summary": "Get servers",
        "description": "Retrieves information about all servers associated with your store.\nUse the `page` parameter to paginate results.\n\n**Authorization:**\n- Requires a valid JWT Bearer token.\n- The token must include the permission: `read-servers`.\n",
        "operationId": "getServers",
        "parameters": [
          {
            "name": "page",
            "in": "query",
            "description": "The page number to retrieve",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 1
            }
          },
          {
            "name": "max_page",
            "in": "query",
            "description": "The maximum number of elements per page. This number must be between 5-50.",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 50
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful operation",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "servers": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ServerGeneral"
                      }
                    },
                    "server_count": {
                      "type": "number",
                      "example": 23
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Didn't provide a valid Tip4Serv API Key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Unauthorized Access, Please submit a valid Tip4Serv API Key"
                    },
                    "status": {
                      "type": "integer",
                      "example": 403
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Unexpected server error"
                    },
                    "status": {
                      "type": "integer",
                      "example": 500
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/store/discord_server": {
      "post": {
        "tags": [
          "Servers"
        ],
        "summary": "Create a new Discord server",
        "description": "Creates and connects a new Discord server to your store using its `discord_id`.\n\n**Authorization:**\n- Requires a valid JWT Bearer token.\n- The token must include the permission: `create-servers`.\n",
        "operationId": "createDiscordServer",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "discord_id": {
                    "type": "string",
                    "description": "ID of the discord server.",
                    "example": 1057619727985426400
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful operation.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": {
                      "type": "number",
                      "example": 200
                    },
                    "message": {
                      "type": "string",
                      "example": "Your Discord server has been successfully created and connected."
                    },
                    "server_id": {
                      "type": "number",
                      "example": 4040,
                      "description": "The ID of your brand new Discord Server."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Error in your request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "One of the parameters is missing or is in the wrong format."
                    },
                    "status": {
                      "type": "integer",
                      "example": 400
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Didn't provide a valid Tip4Serv API Key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Unauthorized Access, Please submit a valid Tip4Serv API Key"
                    },
                    "status": {
                      "type": "integer",
                      "example": 403
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "A conflicting reason is preventing you from creating a new Discord server.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Your store has reached the limit of 55 maximum servers"
                    },
                    "status": {
                      "type": "number",
                      "example": 409
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Unexpected server error"
                    },
                    "status": {
                      "type": "integer",
                      "example": 500
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/store/subscription/{id}/unsubscribe": {
      "patch": {
        "tags": [
          "Subscriptions"
        ],
        "summary": "Unsubscribe",
        "description": "Unsubscribes a user from a subscription identified by `id`.\n\n**Authorization:**\n- Requires a valid JWT Bearer token.\n- The token must include the permission: `update-subscriptions`.\n",
        "operationId": "unsubscribe",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The ID of the subscription.",
            "schema": {
              "type": "number"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful operation.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": {
                      "type": "number",
                      "example": 200
                    },
                    "message": {
                      "type": "string",
                      "example": "You have successfully unsubscribed from your subscription."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Error in your request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "One of the parameters is missing or is in the wrong format."
                    },
                    "status": {
                      "type": "integer",
                      "example": 400
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Didn't provide a valid Tip4Serv API Key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Unauthorized Access, Please submit a valid Tip4Serv API Key"
                    },
                    "status": {
                      "type": "integer",
                      "example": 403
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Active subscription was not found.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Active subscription was not found."
                    },
                    "status": {
                      "type": "integer",
                      "example": 404
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Unexpected server error"
                    },
                    "code": {
                      "type": "integer",
                      "example": 500
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/store/server/{id}/commands": {
      "post": {
        "tags": [
          "Servers"
        ],
        "security": [],
        "description": "Update the actions and get the remaining actions to execute.\n\n**Authorization:**\n- Requires a valid JWT Bearer token.\n- The token must include the permission: `update-delivery`.\n\n**⚠ For Plugin Developers:**\n\nIf you are implementing this endpoint inside a **game plugin (Rust, Minecraft, FiveM, etc.)**,  \n**do not use a JWT Bearer token**.  \nInstead, authenticate using **Server Keys**, as described in our Plugin Development Guide.\n\n→ [Developing Plugins](https://tip4serv.gitbook.io/tip4serv-api/developing-plugins)\n",
        "summary": "Update the actions and get the remaining server commands to execute.",
        "operationId": "updateServerCommands",
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DeliveredServerCommands"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The ID of the server.",
            "schema": {
              "type": "number"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Server commands found successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/PaymentDelivery"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Error in your request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "One of the parameters is missing or is in the wrong format."
                    },
                    "status": {
                      "type": "integer",
                      "example": 400
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Didn't provide a valid Tip4Serv API Key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Unauthorized Access, Please submit a valid Tip4Serv API Key"
                    },
                    "status": {
                      "type": "integer",
                      "example": 403
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Couldn't find the server with that id.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Couldn't find the server with that id."
                    },
                    "status": {
                      "type": "integer",
                      "example": 404
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Unexpected server error"
                    },
                    "code": {
                      "type": "integer",
                      "example": 500
                    }
                  }
                }
              }
            }
          }
        }
      },
      "get": {
        "tags": [
          "Servers"
        ],
        "security": [],
        "description": "Get the remaining actions to execute.\n\n**Authorization:**\n- Requires a valid JWT Bearer token.\n- The token must include the permission: `read-delivery`.\n\n**⚠ For Plugin Developers:**\n\nIf you are implementing this endpoint inside a **game plugin (Rust, Minecraft, FiveM, etc.)**,  \n**do not use a JWT Bearer token**.  \nInstead, authenticate using **Server Keys**, as described in our Plugin Development Guide.\n\n→ [Developing Plugins](https://tip4serv.gitbook.io/tip4serv-api/developing-plugins)\n",
        "summary": "Get the remaining actions to execute.",
        "operationId": "getServerCommands",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The ID of the server.",
            "schema": {
              "type": "number"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Server commands found successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/PaymentDelivery"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Error in your request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "One of the parameters is missing or is in the wrong format."
                    },
                    "status": {
                      "type": "integer",
                      "example": 400
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Didn't provide a valid Tip4Serv API Key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Unauthorized Access, Please submit a valid Tip4Serv API Key"
                    },
                    "status": {
                      "type": "integer",
                      "example": 403
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Couldn't find the server with that id.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Couldn't find the server with that id."
                    },
                    "status": {
                      "type": "integer",
                      "example": 404
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Unexpected server error"
                    },
                    "code": {
                      "type": "integer",
                      "example": 500
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/store/server/{id}": {
      "get": {
        "tags": [
          "Servers"
        ],
        "summary": "Get server by ID",
        "description": "Retrieves information about a specific server identified by `id`.\n\n**Authorization:**\n- Requires a valid JWT Bearer token.\n- The token must include the permission: `read-servers`.\n",
        "operationId": "getServerById",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The ID of the server to retrieve.",
            "schema": {
              "type": "number"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Server found successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Server"
                }
              }
            }
          },
          "400": {
            "description": "Error in your request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "One of the parameters is missing or is in the wrong format."
                    },
                    "status": {
                      "type": "integer",
                      "example": 400
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Didn't provide a valid Tip4Serv API Key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Unauthorized Access, Please submit a valid Tip4Serv API Key"
                    },
                    "status": {
                      "type": "integer",
                      "example": 403
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Couldn't find the server with that id.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Couldn't find the server with that id."
                    },
                    "status": {
                      "type": "integer",
                      "example": 404
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Unexpected server error"
                    },
                    "code": {
                      "type": "integer",
                      "example": 500
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/store/categories": {
      "get": {
        "tags": [
          "Products"
        ],
        "summary": "Get store categories",
        "description": "Retrieves information about all categories. Use `page` to paginate results.\nUse `parent` to filter subcategories of a specific parent category.\n\n  **Authorization:**\n- Requires a valid JWT Bearer token.\n- The token must include the permission: `read-products`.\n",
        "operationId": "getCategories",
        "parameters": [
          {
            "name": "page",
            "in": "query",
            "description": "The page number to retrieve.",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 1
            }
          },
          {
            "name": "max_page",
            "in": "query",
            "description": "The maximum number of elements per page. This number must be between 5-50.",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 50
            }
          },
          {
            "name": "parent",
            "in": "query",
            "description": "The parent category to which we will retrieve it's sub-categories.\nBy default it won't filter by parent category.\n",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful operation",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "categories": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Category"
                      }
                    },
                    "category_count": {
                      "type": "number",
                      "example": 8
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Didn't provide a valid Tip4Serv API Key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Unauthorized Access, Please submit a valid Tip4Serv API Key."
                    },
                    "status": {
                      "type": "number",
                      "example": 403
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Unexpected server error"
                    },
                    "status": {
                      "type": "integer",
                      "example": 500
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/store/checkout/identifiers": {
      "get": {
        "tags": [
          "Checkout"
        ],
        "summary": "Get necessary identifiers for basket",
        "description": "Get all the necessary user identifiers to purchase the requested basket.\nSome products require specific user identifiers in order to be purchased.\nFor example, a product that grants a Discord role will require a discord_id, and a product that provides perks in Ark: Survival Ascended will require an eos_id.\nThis route returns all the necessary information before proceeding with a purchase.\n\nNo API key is required.\n",
        "operationId": "checkoutAuth",
        "parameters": [
          {
            "name": "store",
            "in": "query",
            "required": true,
            "description": "Store ID. This ID is required in order to identify to which store you want to checkout. If you have an API key, you can request the /whoami route in order to figure out your store ID.",
            "schema": {
              "type": "integer",
              "example": 762
            }
          },
          {
            "name": "products",
            "in": "query",
            "required": true,
            "description": "An array of product id to be purchased.",
            "schema": {
              "type": "array",
              "example": [
                12,
                123
              ],
              "items": {
                "type": "integer"
              }
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Array of required user identifiers.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "example": [
                    "discord_id",
                    "eos_id"
                  ],
                  "items": {
                    "type": "string"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Error in your request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "One of the parameters is missing or is in the wrong format."
                    },
                    "status": {
                      "type": "integer",
                      "example": 400
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Unexpected server error"
                    },
                    "status": {
                      "type": "integer",
                      "example": 500
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/store/checkout": {
      "post": {
        "tags": [
          "Checkout"
        ],
        "summary": "Generate a checkout link",
        "description": "Generate an checkout link, provide a basket of what you want to checkout,\nand the endpoint will return you an URL to which to redirect.\n\nNo API key is required.\n",
        "operationId": "checkout",
        "parameters": [
          {
            "name": "store",
            "in": "query",
            "required": true,
            "description": "Store ID. This ID is required in order to identify to which store you want to checkout. If you have an API key, you can request the /whoami route in order to figure out your store ID.",
            "schema": {
              "type": "integer",
              "example": 762
            }
          },
          {
            "name": "currency",
            "in": "query",
            "description": "Display currency code (optional). Supported currencies: GBP, USD, EUR, CAD, AUD, CHF. If omitted, prices are displayed in store currency. Converts all product prices (price, old_price, min_donation) and custom field prices.",
            "required": false,
            "schema": {
              "type": "string",
              "example": "USD"
            }
          },
          {
            "name": "redirect",
            "in": "query",
            "required": false,
            "description": "If enabled, the endpoint will send a 302 Redirection instead of an JSON.",
            "schema": {
              "type": "boolean",
              "example": false,
              "default": false
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CheckoutRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Checkout link generated successfully.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "url": {
                      "type": "string",
                      "example": "https://fivem.tip4serv.com/checkout?key=eyJwcm9kdWN0cyI6IFt7InByb2R1Y3RfaWQiOjEyLCJ0eXBlIjoiYWRkdG9jYXJ0In1dfQ%3D%3D"
                    }
                  }
                }
              }
            }
          },
          "302": {
            "description": "Checkout link generated successfully."
          },
          "400": {
            "description": "Error in your request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "One of the parameters is missing or is in the wrong format."
                    },
                    "status": {
                      "type": "integer",
                      "example": 400
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "User not found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "This discord user was not found."
                    },
                    "status": {
                      "type": "integer",
                      "example": 404
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Unexpected server error"
                    },
                    "status": {
                      "type": "integer",
                      "example": 500
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/store/product/{slug}": {
      "get": {
        "tags": [
          "Products"
        ],
        "summary": "Get product by slug",
        "description": "Retrieves detailed information about a single product identified by it's `slug`.\nset `details` to `true` for full product details.\n\n**Authorization:**\n- Requires a valid JWT Bearer token.\n- The token must include the permission: `read-products`.\n",
        "operationId": "getProductBySlug",
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "description": "the slug of the product to retrieve.",
            "example": "vip-plus",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "details",
            "in": "query",
            "required": false,
            "description": "Enable detailed response.",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "currency",
            "in": "query",
            "description": "Display currency code (optional). Supported currencies: GBP, USD, EUR, CAD, AUD, CHF. If omitted, prices are displayed in store currency. Converts all product prices (price, old_price, min_donation) and custom field prices.",
            "required": false,
            "schema": {
              "type": "string",
              "example": "USD"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Product found successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Product"
                }
              }
            }
          },
          "400": {
            "description": "Error in your request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "One of the parameter is missing or is in the wrong format."
                    },
                    "status": {
                      "type": "integer",
                      "example": 400
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Didn't provide a valid Tip4Serv API Key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Unauthorized Access, Please submit a valid Tip4Serv API key."
                    },
                    "status": {
                      "type": "integer",
                      "example": 403
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Couldn't find the product with that id.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Couldn't find the product with that id."
                    },
                    "status": {
                      "type": "integer",
                      "example": 404
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Unexpected server error"
                    },
                    "code": {
                      "type": "integer",
                      "example": 500
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/store/product": {
      "post": {
        "tags": [
          "Products"
        ],
        "summary": "Create a product",
        "description": "Create a new product in your store.\n\n**Authorization:**\n- Requires a valid JWT Bearer token.\n- The token must include the permission: `create-discounts`.\n",
        "operationId": "createProduct",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateProduct"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful operation",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Product"
                }
              }
            }
          },
          "400": {
            "description": "Error in your request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "One of the parameters is missing or is in the wrong format."
                    },
                    "status": {
                      "type": "integer",
                      "example": 400
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Missing or invalid Tip4Serv API Key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Unauthorized access. Please provide a valid Tip4Serv API Key."
                    },
                    "status": {
                      "type": "number",
                      "example": 403
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Unexpected server error"
                    },
                    "status": {
                      "type": "number",
                      "example": 500
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/store/product/{id}/thumbnail": {
      "post": {
        "tags": [
          "Products"
        ],
        "summary": "Upload a thumbnail",
        "description": "Update a new product in your store.\n\n**Authorization:**\n- Requires a valid JWT Bearer token.\n- The token must include the permission: `create-products` or `update-products`.\n",
        "operationId": "uploadProductThumbnail",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The ID of the product to attach the file to.",
            "schema": {
              "type": "integer",
              "example": 123
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "required": [
                  "file"
                ],
                "properties": {
                  "file": {
                    "type": "string",
                    "format": "binary",
                    "description": "The thumbnail to upload. Ther image must not be heavier than 8Mb."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "File uploaded successfully.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "type": "string",
                      "example": "The thumbnail was successfully uploaded."
                    },
                    "status": {
                      "type": "integer",
                      "example": 200
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Error in your request.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "One of the parameters is missing or is in the wrong format."
                    },
                    "status": {
                      "type": "integer",
                      "example": 400
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Missing or invalid Tip4Serv API Key.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Unauthorized Access, Please submit a valid Tip4Serv API Key."
                    },
                    "status": {
                      "type": "integer",
                      "example": 403
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Product not found.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Couldn’t find the product with that id."
                    },
                    "status": {
                      "type": "integer",
                      "example": 404
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Unexpected server error"
                    },
                    "status": {
                      "type": "integer",
                      "example": 500
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/store/product/{id}/gallery": {
      "post": {
        "tags": [
          "Products"
        ],
        "summary": "Upload an image to be displayed in the product gallery",
        "description": "Update a new product in your store.\n\n**Authorization:**\n- Requires a valid JWT Bearer token.\n- The token must include the permission: `create-products` or `update-products`.\n",
        "operationId": "uploadProductGallery",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The ID of the product to attach the image to.",
            "schema": {
              "type": "integer",
              "example": 123
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "required": [
                  "file"
                ],
                "properties": {
                  "file": {
                    "type": "string",
                    "format": "binary",
                    "description": "The image to upload. The image must not be heavier than 8Mb."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Image uploaded successfully.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "type": "string",
                      "example": "The image was successfully uploaded."
                    },
                    "status": {
                      "type": "integer",
                      "example": 200
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Error in your request.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "One of the parameters is missing or is in the wrong format."
                    },
                    "status": {
                      "type": "integer",
                      "example": 400
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Missing or invalid Tip4Serv API Key.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Unauthorized Access, Please submit a valid Tip4Serv API Key."
                    },
                    "status": {
                      "type": "integer",
                      "example": 403
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Product not found.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Couldn’t find the product with that id."
                    },
                    "status": {
                      "type": "integer",
                      "example": 404
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Unexpected server error"
                    },
                    "status": {
                      "type": "integer",
                      "example": 500
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/store/product/{id}/file/{file_id}": {
      "delete": {
        "tags": [
          "Products"
        ],
        "summary": "Delete a monetized file",
        "description": "Delete a monetized file.\n\n**Authorization:**\n- Requires a valid JWT Bearer token.\n- The token must include the permission: `create-products` or `update-products`.\n",
        "operationId": "deleteProductFile",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The ID of the product to attach the file to.",
            "schema": {
              "type": "integer",
              "example": 123
            }
          },
          {
            "name": "file_id",
            "in": "path",
            "required": true,
            "description": "The id of the file attached to a product to delete.",
            "schema": {
              "type": "integer",
              "example": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "File uploaded successfully.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "type": "string",
                      "example": "The file was successfully deleted."
                    },
                    "status": {
                      "type": "integer",
                      "example": 200
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Error in your request.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "One of the parameters is missing or is in the wrong format."
                    },
                    "status": {
                      "type": "integer",
                      "example": 400
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Missing or invalid Tip4Serv API Key.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Unauthorized Access, Please submit a valid Tip4Serv API Key."
                    },
                    "status": {
                      "type": "integer",
                      "example": 403
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Product not found.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Couldn’t find the product with that id."
                    },
                    "status": {
                      "type": "integer",
                      "example": 404
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Unexpected server error"
                    },
                    "status": {
                      "type": "integer",
                      "example": 500
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/store/product/{id}/file": {
      "post": {
        "tags": [
          "Products"
        ],
        "summary": "Upload a file to sell for a product",
        "description": "Upload a file to sell in your product.\n\n**Authorization:**\n- Requires a valid JWT Bearer token.\n- The token must include the permission: `create-products` or `update-products`.\n",
        "operationId": "uploadProductFile",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The ID of the product to attach the file to.",
            "schema": {
              "type": "integer",
              "example": 123
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "required": [
                  "file"
                ],
                "properties": {
                  "expiration": {
                    "type": "integer",
                    "description": "Number of days the file remains available after purchase.\nUse `-1` to keep the file valid forever.\n\n(This will affect the other files for the same product)\n",
                    "default": -1,
                    "example": -1
                  },
                  "file": {
                    "type": "string",
                    "format": "binary",
                    "description": "The file to upload. The file must not be heavier than 50Mb."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "File uploaded successfully.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProductFile"
                }
              }
            }
          },
          "400": {
            "description": "Error in your request.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "One of the parameters is missing or is in the wrong format."
                    },
                    "status": {
                      "type": "integer",
                      "example": 400
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Missing or invalid Tip4Serv API Key.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Unauthorized Access, Please submit a valid Tip4Serv API Key."
                    },
                    "status": {
                      "type": "integer",
                      "example": 403
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Product not found.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Couldn’t find the product with that id."
                    },
                    "status": {
                      "type": "integer",
                      "example": 404
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "Storage quota exceeded.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Your store has reached its file storage quota."
                    },
                    "status": {
                      "type": "integer",
                      "example": 409
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Unexpected server error"
                    },
                    "status": {
                      "type": "integer",
                      "example": 500
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/store/product/{id}/gallery/{image_id}": {
      "delete": {
        "tags": [
          "Products"
        ],
        "summary": "Delete a gallery image from the product.",
        "description": "Delete a gallery image from the product.\n\n**Authorization:**\n- Requires a valid JWT Bearer token.\n- The token must include the permission: `create-products` or `update-products`.\n",
        "operationId": "deleteProductGallery",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The ID of the product where the image is attached to.",
            "schema": {
              "type": "integer",
              "example": 123
            }
          },
          {
            "name": "image_id",
            "in": "path",
            "required": true,
            "description": "\nThe `image_id` corresponds to the gallery image position, starting at 1.\n\nFor example, given the gallery:\n\n```json\n[\"image_1.webp\", \"image_2.webp\", \"image_3.png\"]\n```\n\nTo delete `image_2.webp`, send:\n\n```text\nimage_id = 2\n```\n\n**Important:**\nIf your product uses both a thumbnail and a gallery, the thumbnail may appear at the beginning of the gallery array returned by the API.\n\nDo not include the thumbnail when calculating the `image_id`.\n\nFor example, given:\n\n```json\n[\"thumbnail.jpg\", \"image_1.webp\", \"image_2.webp\", \"image_3.png\"]\n```\n\nTo delete `image_2.webp`, the `image_id` is still `2`, not `3`.\n",
            "schema": {
              "type": "integer",
              "example": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Image successfully deleted.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "type": "string",
                      "example": "The image was successfully deleted."
                    },
                    "status": {
                      "type": "integer",
                      "example": 200
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Error in your request.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "One of the parameters is missing or is in the wrong format."
                    },
                    "status": {
                      "type": "integer",
                      "example": 400
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Missing or invalid Tip4Serv API Key.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Unauthorized Access, Please submit a valid Tip4Serv API Key."
                    },
                    "status": {
                      "type": "integer",
                      "example": 403
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Product not found.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Couldn’t find the product with that id."
                    },
                    "status": {
                      "type": "integer",
                      "example": 404
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Unexpected server error"
                    },
                    "status": {
                      "type": "integer",
                      "example": 500
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/store/product/{id}": {
      "delete": {
        "tags": [
          "Products"
        ],
        "summary": "Delete the specified product.",
        "description": "Delete the specified product.\n\n**Authorization:**\n- Requires a valid JWT Bearer token.\n- The token must include the permissions: `delete-products`.\n",
        "operationId": "deleteProduct",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "the ID of the product to update.",
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful operation",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "type": "string",
                      "example": "The product has been successfully deleted."
                    },
                    "status": {
                      "type": "number",
                      "example": 200
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Error in your request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "One of the parameters is missing or is in the wrong format."
                    },
                    "status": {
                      "type": "integer",
                      "example": 400
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Missing or invalid Tip4Serv API Key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Unauthorized access. Please provide a valid Tip4Serv API Key."
                    },
                    "status": {
                      "type": "number",
                      "example": 403
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "Conflicting conditions",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "This product has active subscribers."
                    },
                    "status": {
                      "type": "number",
                      "example": 409
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Unexpected server error"
                    },
                    "status": {
                      "type": "number",
                      "example": 500
                    }
                  }
                }
              }
            }
          }
        }
      },
      "patch": {
        "tags": [
          "Products"
        ],
        "summary": "Update a product",
        "description": "Update a new product in your store.\n\n**Authorization:**\n- Requires a valid JWT Bearer token.\n- The token must include the permission: `update-products`.\n",
        "operationId": "updateProduct",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateProduct"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The ID of the product to update.",
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful operation",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Product"
                }
              }
            }
          },
          "400": {
            "description": "Error in your request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "One of the parameters is missing or is in the wrong format."
                    },
                    "status": {
                      "type": "integer",
                      "example": 400
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Missing or invalid Tip4Serv API Key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Unauthorized access. Please provide a valid Tip4Serv API Key."
                    },
                    "status": {
                      "type": "number",
                      "example": 403
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Unexpected server error"
                    },
                    "status": {
                      "type": "number",
                      "example": 500
                    }
                  }
                }
              }
            }
          }
        }
      },
      "get": {
        "tags": [
          "Products"
        ],
        "summary": "Get product by ID",
        "description": "Retrieves detailed information about a single product identified by `id`.\nSet `details` to `true` for full product details.\n\n**Authorization:**\n- Requires a valid JWT Bearer token.\n- The token must include the permission: `read-products`.\n",
        "operationId": "getProductById",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The ID of the product to retrieve.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "details",
            "in": "query",
            "required": false,
            "description": "Enable detailed response.",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "currency",
            "in": "query",
            "description": "Display currency code (optional). Supported currencies: GBP, USD, EUR, CAD, AUD, CHF. If omitted, prices are displayed in store currency. Converts all product prices (price, old_price, min_donation) and custom field prices.",
            "required": false,
            "schema": {
              "type": "string",
              "example": "USD"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Product found successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Product"
                }
              }
            }
          },
          "400": {
            "description": "Error in your request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "One of the parameters is missing or is in the wrong format."
                    },
                    "status": {
                      "type": "integer",
                      "example": 400
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Didn't provide a valid Tip4Serv API Key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Unauthorized Access, Please submit a valid Tip4Serv API Key"
                    },
                    "status": {
                      "type": "integer",
                      "example": 403
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Couldn't find the product with that id.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Couldn't find the product with that id."
                    },
                    "status": {
                      "type": "integer",
                      "example": 404
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Unexpected server error"
                    },
                    "code": {
                      "type": "integer",
                      "example": 500
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/user/whoami": {
      "get": {
        "tags": [
          "User"
        ],
        "summary": "Get general information about the user",
        "description": "Retrieves general information about the user, including the username, profile picture and other basic settings.\n\n**Authorization:**\n- Requires a valid JWT Bearer token.\n- The token must identify an authenticated end user.\n",
        "operationId": "userWhoami",
        "responses": {
          "200": {
            "description": "Succesful operation",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "user": {
                      "$ref": "#/components/schemas/User"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid user token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UnauthorizedError"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InternalServerError"
                }
              }
            }
          }
        }
      }
    },
    "/user/subscriptions": {
      "get": {
        "tags": [
          "Subscriptions (User)"
        ],
        "summary": "Get the authenticated user's subscriptions",
        "description": "Retrieves subscriptions belonging to the authenticated user.\nUse the `page` parameter to paginate results.\nSet `only_recurring_subscription` to `true` to retrieve only recurring subscriptions.\n\n**Authorization:**\n- Requires a valid JWT Bearer token.\n- The token must identify an authenticated end user.\n",
        "operationId": "getUserSubscriptions",
        "parameters": [
          {
            "name": "page",
            "in": "query",
            "description": "The page number to retrieve.",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 1
            }
          },
          {
            "name": "max_page",
            "in": "query",
            "description": "The maximum number of elements per page. This number must be between 5 and 50.",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 50
            }
          },
          {
            "name": "only_recurring_subscription",
            "in": "query",
            "description": "Include only recurring subscriptions.",
            "required": false,
            "schema": {
              "type": "boolean",
              "default": false
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful operation",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "subscriptions": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/SubscriptionGeneral"
                      }
                    },
                    "subscription_count": {
                      "type": "integer",
                      "example": 3
                    }
                  },
                  "required": [
                    "subscriptions",
                    "subscription_count"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid user token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UnauthorizedError"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InternalServerError"
                }
              }
            }
          }
        }
      }
    },
    "/user/subscriptions/unsubscribe": {
      "patch": {
        "tags": [
          "Subscriptions (User)"
        ],
        "summary": "Unsubscribe the authenticated user from a subscription",
        "description": "Unsubscribes the authenticated user from one of their active subscriptions.\n\n**Authorization:**\n- Requires a valid JWT Bearer token.\n- The token must identify an authenticated end user.\n",
        "operationId": "unsubscribeUserSubscription",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UserUnsubscribeSubscriptionRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful operation",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UserSubscriptionActionResponse"
                }
              }
            }
          },
          "400": {
            "description": "Error in your request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BadRequestError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid user token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UnauthorizedError"
                }
              }
            }
          },
          "404": {
            "description": "Active subscription was not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotFoundError"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InternalServerError"
                }
              }
            }
          }
        }
      }
    },
    "/user/payments": {
      "get": {
        "tags": [
          "Payments (User)"
        ],
        "summary": "Get the authenticated user's payments",
        "description": "Retrieves payments belonging to the authenticated user.\nUse the `page` parameter to paginate results.\n\n**Authorization:**\n- Requires a valid JWT Bearer token.\n- The token must identify an authenticated end user.\n",
        "operationId": "getUserPayments",
        "parameters": [
          {
            "name": "page",
            "in": "query",
            "description": "The page number to retrieve.",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 1
            }
          },
          {
            "name": "max_page",
            "in": "query",
            "description": "The maximum number of elements per page. This number must be between 5 and 50.",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 50
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful operation",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "payments": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/PaymentGeneral"
                      }
                    },
                    "payment_count": {
                      "type": "integer",
                      "example": 12
                    }
                  },
                  "required": [
                    "payments",
                    "payment_count"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid user token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UnauthorizedError"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InternalServerError"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "JWT"
      }
    },
    "schemas": {
      "User": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "example": 15421,
            "description": "The ID of the user."
          },
          "username": {
            "type": "string",
            "example": "Duster",
            "description": "The username of the user."
          },
          "email": {
            "type": "string",
            "example": "duster@tip4serv.com",
            "description": "The e-mail of the user."
          },
          "language": {
            "type": "string",
            "example": "English_en",
            "description": "The primary language of the user."
          },
          "timezone": {
            "type": "string",
            "example": "Europe/Paris",
            "description": "The timezone of the user."
          },
          "registration_date": {
            "type": "integer",
            "example": 1676373212,
            "description": "The registration date expressed in the user timezone."
          },
          "profile_picture": {
            "type": "string",
            "example": "https://cdn.tip4serv.com/user-data/avatars/f7b64cc1f38ad584f0a31bdcbb8a4452.png",
            "description": "The profile picture of the user."
          },
          "loyalty_points": {
            "type": "integer",
            "example": 360,
            "description": "Loyalty points posessed by the user. Is displayed only if loyalty points are set up on the targeted store."
          }
        }
      },
      "UserUnsubscribeSubscriptionRequest": {
        "type": "object",
        "properties": {
          "subscription_id": {
            "type": "integer",
            "description": "The ID of the subscription to unsubscribe from.",
            "example": 1452
          }
        },
        "required": [
          "subscription_id"
        ]
      },
      "UserSubscriptionActionResponse": {
        "type": "object",
        "properties": {
          "status": {
            "type": "integer",
            "example": 200
          },
          "message": {
            "type": "string",
            "example": "You have successfully unsubscribed from your subscription."
          }
        },
        "required": [
          "status",
          "message"
        ]
      },
      "BadRequestError": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string",
            "example": "One of the parameters is missing or is in the wrong format."
          },
          "status": {
            "type": "integer",
            "example": 400
          }
        },
        "required": [
          "error",
          "status"
        ]
      },
      "UnauthorizedError": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string",
            "example": "Unauthorized access. Please provide a valid user token."
          },
          "status": {
            "type": "integer",
            "example": 401
          }
        },
        "required": [
          "error",
          "status"
        ]
      },
      "NotFoundError": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string",
            "example": "Active subscription was not found."
          },
          "status": {
            "type": "integer",
            "example": 404
          }
        },
        "required": [
          "error",
          "status"
        ]
      },
      "InternalServerError": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string",
            "example": "Unexpected server error"
          },
          "status": {
            "type": "integer",
            "example": 500
          }
        },
        "required": [
          "error",
          "status"
        ]
      },
      "ProductGeneral": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "description": "Unique identifier of the product.",
            "example": "64"
          },
          "name": {
            "type": "string",
            "description": "Name of the product.",
            "example": "VIP +"
          },
          "status": {
            "type": "boolean",
            "description": "Indicates whether the product is enabled.",
            "example": true
          },
          "slug": {
            "type": "string",
            "description": "URL-friendly name of the product.",
            "example": "vip-plus"
          },
          "price": {
            "type": "integer",
            "description": "Actual price of the product after any applicable discounts. Expressed in the store's currency, or the requested display currency if the `currency` parameter was used.",
            "example": 17.99
          },
          "old_price": {
            "type": "integer",
            "description": "Original price of the product without any discounts. Expressed in the store's currency, or the requested display currency if the `currency` parameter was used.",
            "example": 19.99
          },
          "percent_off": {
            "type": "integer",
            "description": "If a discount applies, the percentage off from the original price.",
            "example": 10
          },
          "recurring_discount": {
            "type": "boolean",
            "description": "Indicates whether the discount applies to each occurrence of a subscription.",
            "example": true
          },
          "discount_end": {
            "type": "integer",
            "description": "Timestamp of the discount expiration. *(expressed in the store timezone)*",
            "example": 1758563356951
          },
          "donation": {
            "type": "boolean",
            "description": "Indicates if the product is a donation-type product, this allow the user to choose the amount of the donation,  `price` therefore defines the minimum donation amount.",
            "example": false
          },
          "min_donation": {
            "type": "number",
            "description": "Minimum donation amount (only present if donation is true). If currency parameter is used, this value is converted to the requested currency.",
            "example": 10.0
          },
          "small_description": {
            "type": "string",
            "description": "Shortened description of the product, limited to 512 characters.",
            "example": "This product is quite amazing. It allows you to unlock our VIP +\nperks...\n"
          },
          "category": {
            "oneOf": [
              {
                "type": "integer"
              },
              {
                "$ref": "#/components/schemas/Category"
              }
            ],
            "description": "Category the product belongs to *(either as an integer or as a full category object if details are enabled)*.",
            "example": 1
          },
          "subscription": {
            "type": "boolean",
            "description": "Indicates whether the product is a subscription.",
            "example": true
          },
          "stock": {
            "type": "integer",
            "description": "Available stock of the product.",
            "example": 10
          },
          "duration_periodicity": {
            "type": "string",
            "description": "Unit of time for the subscription's duration.\n\nPossible values:  \n- `day` – duration in days  \n- `week` – duration in weeks  \n- `month` – duration in months  \n- `year` – duration in years\n\nExample: If `duration_periodicity = month` and `period_num = 3`, the subscription lasts 3 months.\n",
            "example": "month"
          },
          "period_num": {
            "type": "number",
            "description": "Number of `duration_periodicity` units before the subscription expires or the next charge occurs.\n\nExamples:  \n- Charge the customer every 3 months  \n- Charge the customer every 1 year\n\nAccepted ranges:  \n- 1–99 for days  \n- 1–52 for weeks  \n- 1–12 for months  \n- 1–1 for years\n\nExample: `period_num: 3` → charge every 3 months\n",
            "example": 3
          },
          "trial": {
            "type": "number",
            "description": "Number of trial days offered in the subscription.",
            "example": 7
          },
          "featured": {
            "type": "boolean",
            "description": "Indicates whether the product is featured.",
            "example": true
          },
          "image": {
            "type": "string",
            "description": "Main thumbnail of the product.",
            "example": "https://cdn.tip4serv.com/shops-img/example.png"
          },
          "created_date": {
            "type": "number",
            "description": "Timestamp of product creation in the store's timezone.",
            "example": 1753098967
          },
          "currency": {
            "type": "string",
            "description": "Currency in which all prices are expressed. Matches the requested `currency` parameter, or the store's default currency if not specified.",
            "example": "GBP"
          }
        },
        "required": [
          "id",
          "name",
          "slug",
          "price",
          "status",
          "small_description",
          "category",
          "subscription",
          "featured",
          "created_date"
        ]
      },
      "CreateProduct": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "description": "Name of the product.",
            "example": "VIP +"
          },
          "status": {
            "type": "boolean",
            "description": "Indicates whether the product is enabled. If not specified, the product will be automatically enabled",
            "example": true,
            "default": true
          },
          "slug": {
            "type": "string",
            "description": "URL-friendly name of the product. If not specified will be automatically calculated.",
            "example": "vip-plus"
          },
          "price": {
            "type": "integer",
            "description": "Current price of the product after any applicable discounts, in the store's currency.",
            "example": 17.99
          },
          "recurring_discount": {
            "type": "boolean",
            "description": "Indicates whether the discount is applied on each occurrence of the subscription.",
            "example": true
          },
          "donation": {
            "type": "boolean",
            "description": "Indicates if the product is a donation-type product, this allow the user to choose the amount of the donation,  `price` therefore defines the minimum donation amount.",
            "example": false
          },
          "description": {
            "type": "string",
            "description": "Full description of the product.",
            "example": "This product is quite amazing. It allows you to unlock our VIP + perks and showcase your skills on our server."
          },
          "youtube": {
            "type": "string",
            "description": "URL of the video associated with the product.",
            "example": "https://youtu.be/K1QICrgxTjA"
          },
          "category": {
            "oneOf": [
              {
                "type": "integer"
              },
              {
                "$ref": "#/components/schemas/Category"
              }
            ],
            "description": "Category the product belongs to (integer or full category object if details are enabled). If not specified, the product will be automatically added to the default category.",
            "example": 1
          },
          "featured": {
            "type": "boolean",
            "description": "Indicates whether the product is featured. If not specified will be set to false.",
            "example": false
          },
          "enable_stock": {
            "type": "integer",
            "description": "Enable a system of limited stock for this product. By default if not set, no stock system will be implemented.",
            "example": true
          },
          "stock": {
            "type": "integer",
            "description": "Available stock of the product. `enable_stock` must be set to true first.",
            "example": 10
          },
          "enable_trial": {
            "type": "boolean",
            "description": "Indicates whether trial days are enabled.",
            "example": true
          },
          "trial": {
            "type": "integer",
            "description": "Number of trial days available for this product. If not specified no trial period will be set. `enable_trial` must first be set to true.",
            "example": 14
          },
          "renewal_start": {
            "type": "string",
            "description": "If trial days are enabled, defines when commands in the \"Do this after each renewal payment\" event start.\n\nAccepted values:  \n`first_payment`, `second_payment`\n",
            "example": "first_payment"
          },
          "quantity": {
            "type": "boolean",
            "description": "Indicates whether the customer can select the quantity to purchase. If not specified customers will by default be able to purchase the product multiple times.",
            "example": true
          },
          "cmd_multiplier": {
            "type": "boolean",
            "description": "If quantity is selectable, determines whether commands are multiplied by the chosen quantity. If set to true each command will be executed \"quantity\" times, by default `cmd_multiplier` is set to false.",
            "example": false
          },
          "subscription": {
            "type": "boolean",
            "description": "Indicates whether the product is a subscription. If not specified the product will not be an subscription.",
            "example": false
          },
          "disable_giftcard_payments": {
            "type": "boolean",
            "description": "Indicates whether the product can be purchased with a giftcard. If not specified this option will be set to false by default. If set to true a customer won't be able to purchase this product with a giftcard.\n",
            "example": false
          },
          "giftcard": {
            "type": "boolean",
            "description": "Indicates whether the product supports gift cards. If not specified the product will not offer any giftcard.",
            "example": false
          },
          "giftcard_expiration": {
            "type": "boolean",
            "description": "Indicates whether the generated gift card will eventually expire.",
            "example": false
          },
          "giftcard_expiration_duration_periodicity": {
            "type": "string",
            "description": "Unit of time for the gift card expiration duration.\n\nPossible values:  \n- `day` – duration in days   - `week` – duration in weeks   - `month` – duration in months   - `year` – duration in years\n\nExample: If `duration_periodicity = month` and `period_num = 3`, the giftcard will expire 3 months after the purchase.\n",
            "example": "month"
          },
          "giftcard_expiration_period_num": {
            "type": "integer",
            "description": "Number of `duration_periodicity` units before the giftcard expires.\nExamples:  \n- Giftcard expires after 3 months  \n- Giftcard expires after 1 year\nExample: `period_num: 3` → charge every 3 months\n",
            "example": 3
          },
          "custom_fields": {
            "type": "array",
            "description": "Array of custom fields attached to the product.",
            "items": {
              "$ref": "#/components/schemas/CustomField"
            }
          },
          "custom_rules": {
            "type": "array",
            "description": "Array of custom rules applied to the product's custom fields.",
            "items": {
              "$ref": "#/components/schemas/CreateCustomRule"
            }
          },
          "subscription_cycle": {
            "type": "string",
            "description": "Determines whether subscriptions are recurring or expire by default. Accepted values:   `each`, `expire`",
            "example": "each"
          },
          "cumul_sub": {
            "type": "boolean",
            "description": "If set to false prevents customers from subscribing to the same product multiple times. By default set to true.",
            "example": false
          },
          "onetime_sub": {
            "type": "boolean",
            "description": "Allows customers to purchase the product for a single billing cycle without subscribing. By default set to true.",
            "example": false
          },
          "duration_periodicity": {
            "type": "string",
            "description": "Unit of time for the subscription duration.\n\nPossible values:  \n- `day` – duration in days  \n- `week` – duration in weeks  \n- `month` – duration in months  \n- `year` – duration in years\n\nExample: If `duration_periodicity = month` and `period_num = 3`, the subscription lasts 3 months.\n",
            "example": "month"
          },
          "period_num": {
            "type": "number",
            "description": "Number of `duration_periodicity` units before the subscription expires or the next charge occurs.\n\nExamples:  \n- Charge the customer every 3 months  \n- Charge the customer every 1 year\n\nAccepted ranges:  \n- 1–99 for days  \n- 1–52 for weeks  \n- 1–12 for months  \n- 1–1 for years\n\nExample: `period_num: 3` → charge every 3 months\n\nIf not specified will be set by default to 1.\n",
            "example": 3
          },
          "purchase_limit": {
            "$ref": "#/components/schemas/PurchaseLimit",
            "description": "Rules limiting the number of times a customer can purchase the product."
          },
          "actions": {
            "type": "object",
            "description": "Array of different actions to execute, indexed by it's server ID. By default if not specified no actions will be executed",
            "additionalProperties": {
              "$ref": "#/components/schemas/Action"
            },
            "example": {
              "36252": {
                "payment_command": [
                  {
                    "str": "AddPoints {steam_id} 5000",
                    "event": "Must be online"
                  },
                  {
                    "str": "say Thanks {steam_username} for your purchase!",
                    "event": "Execute"
                  }
                ],
                "refund_command": [
                  {
                    "str": "RemovePoints {steam_id} 5000",
                    "event": "Must be online"
                  }
                ]
              }
            }
          }
        },
        "required": [
          "name",
          "price"
        ]
      },
      "UpdateProduct": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "description": "Name of the product.",
            "example": "VIP +"
          },
          "status": {
            "type": "boolean",
            "description": "Indicates whether the product is enabled. If not specified, the product will be automatically enabled",
            "example": true,
            "default": true
          },
          "slug": {
            "type": "string",
            "description": "URL-friendly name of the product. If not specified will be automatically calculated.",
            "example": "vip-plus"
          },
          "price": {
            "type": "integer",
            "description": "Current price of the product after any applicable discounts, in the store's currency.",
            "example": 17.99
          },
          "recurring_discount": {
            "type": "boolean",
            "description": "Indicates whether the discount is applied on each occurrence of the subscription.",
            "example": true
          },
          "donation": {
            "type": "boolean",
            "description": "Indicates if the product is a donation-type product, this allow the user to choose the amount of the donation,  `price` therefore defines the minimum donation amount.",
            "example": false
          },
          "description": {
            "type": "string",
            "description": "Full description of the product.",
            "example": "This product is quite amazing. It allows you to unlock our VIP + perks and showcase your skills on our server."
          },
          "youtube": {
            "type": "string",
            "description": "URL of the video associated with the product.",
            "example": "https://youtu.be/K1QICrgxTjA"
          },
          "category": {
            "oneOf": [
              {
                "type": "integer"
              },
              {
                "$ref": "#/components/schemas/Category"
              }
            ],
            "description": "Category the product belongs to (integer or full category object if details are enabled). If not specified, the product will be automatically added to the default category.",
            "example": 1
          },
          "featured": {
            "type": "boolean",
            "description": "Indicates whether the product is featured. If not specified will be set to false.",
            "example": false
          },
          "enable_stock": {
            "type": "integer",
            "description": "Enable a system of limited stock for this product. By default if not set, no stock system will be implemented.",
            "example": true
          },
          "stock": {
            "type": "integer",
            "description": "Available stock of the product. `enable_stock` must be set to true first.",
            "example": 10
          },
          "enable_trial": {
            "type": "boolean",
            "description": "Indicates whether trial days are enabled.",
            "example": true
          },
          "trial": {
            "type": "integer",
            "description": "Number of trial days available for this product. If not specified no trial period will be set. `enable_trial` must first be set to true.",
            "example": 14
          },
          "renewal_start": {
            "type": "string",
            "description": "If trial days are enabled, defines when commands in the \"Do this after each renewal payment\" event start.\n\nAccepted values:  \n`first_payment`, `second_payment`\n",
            "example": "first_payment"
          },
          "quantity": {
            "type": "boolean",
            "description": "Indicates whether the customer can select the quantity to purchase. If not specified customers will by default be able to purchase the product multiple times.",
            "example": true
          },
          "cmd_multiplier": {
            "type": "boolean",
            "description": "If quantity is selectable, determines whether commands are multiplied by the chosen quantity. If set to true each command will be executed \"quantity\" times, by default `cmd_multiplier` is set to false.",
            "example": true
          },
          "subscription": {
            "type": "boolean",
            "description": "Indicates whether the product is a subscription. If not specified the product will not be an subscription.",
            "example": false
          },
          "disable_giftcard_payments": {
            "type": "boolean",
            "description": "Indicates whether the product can be purchased with a giftcard. If not specified this option will be set to false by default. If set to true a customer won't be able to purchase this product with a giftcard.\n"
          },
          "giftcard": {
            "type": "boolean",
            "description": "Indicates whether the product supports gift cards. If not specified the product will not offer any giftcard.",
            "example": false
          },
          "giftcard_expiration": {
            "type": "boolean",
            "description": "Indicates whether the generated gift card will eventually expire.",
            "example": false
          },
          "giftcard_expiration_duration_periodicity": {
            "type": "string",
            "description": "Unit of time for the gift card expiration duration.\n\nPossible values:  \n- `day` – duration in days   - `week` – duration in weeks   - `month` – duration in months   - `year` – duration in years\n\nExample: If `duration_periodicity = month` and `period_num = 3`, the giftcard will expire 3 months after the purchase.\n",
            "example": "month"
          },
          "giftcard_expiration_period_num": {
            "type": "integer",
            "description": "Number of `duration_periodicity` units before the giftcard expires.\nExamples:  \n- Giftcard expires after 3 months  \n- Giftcard expires after 1 year\nExample: `period_num: 3` → charge every 3 months\n",
            "example": 3
          },
          "custom_fields": {
            "type": "array",
            "description": "Array of custom fields attached to the product.",
            "items": {
              "$ref": "#/components/schemas/CreateCustomField"
            }
          },
          "custom_rules": {
            "type": "array",
            "description": "Array of custom rules applied to the product's custom fields.",
            "items": {
              "$ref": "#/components/schemas/CreateCustomRule"
            }
          },
          "subscription_cycle": {
            "type": "string",
            "description": "Determines whether subscriptions are recurring or expire by default. Accepted values:   `each`, `expire`",
            "example": "each"
          },
          "cumul_sub": {
            "type": "boolean",
            "description": "If set to false prevents customers from subscribing to the same product multiple times.",
            "example": false
          },
          "onetime_sub": {
            "type": "boolean",
            "description": "Allows customers to purchase the product for a single billing cycle without subscribing.",
            "example": false
          },
          "duration_periodicity": {
            "type": "string",
            "description": "Unit of time for the subscription duration.\n\nPossible values:  \n- `day` – duration in days  \n- `week` – duration in weeks  \n- `month` – duration in months  \n- `year` – duration in years\n\nExample: If `duration_periodicity = month` and `period_num = 3`, the subscription lasts 3 months.\n",
            "example": "month"
          },
          "period_num": {
            "type": "number",
            "description": "Number of `duration_periodicity` units before the subscription expires or the next charge occurs.\n\nExamples:  \n- Charge the customer every 3 months  \n- Charge the customer every 1 year\n\nAccepted ranges:  \n- 1–99 for days  \n- 1–52 for weeks  \n- 1–12 for months  \n- 1–1 for years\n\nExample: `period_num: 3` → charge every 3 months\n",
            "example": 3
          },
          "purchase_limit": {
            "$ref": "#/components/schemas/PurchaseLimit",
            "description": "Rules limiting the number of times a customer can purchase the product."
          },
          "actions": {
            "type": "object",
            "description": "Array of different actions to execute, indexed by it's server ID. By default if not specified no actions will be executed",
            "additionalProperties": {
              "$ref": "#/components/schemas/Action"
            },
            "example": {
              "36252": {
                "payment_command": [
                  {
                    "str": "AddPoints {steam_id} 5000",
                    "event": "Must be online"
                  },
                  {
                    "str": "say Thanks {steam_username} for your purchase!",
                    "event": "Execute"
                  }
                ],
                "refund_command": [
                  {
                    "str": "RemovePoints {steam_id} 5000",
                    "event": "Must be online"
                  }
                ]
              }
            }
          }
        }
      },
      "Product": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "description": "Unique identifier of the product.",
            "example": "40"
          },
          "name": {
            "type": "string",
            "description": "Name of the product.",
            "example": "VIP +"
          },
          "status": {
            "type": "boolean",
            "description": "Indicates whether the product is enabled.",
            "example": true
          },
          "slug": {
            "type": "string",
            "description": "URL-friendly name of the product.",
            "example": "vip-plus"
          },
          "price": {
            "type": "integer",
            "description": "Current price of the product after any applicable discounts. Expressed in the store's currency, or the requested display currency if the `currency` parameter was used.",
            "example": 17.99
          },
          "old_price": {
            "type": "integer",
            "description": "Original price of the product without discounts. Expressed in the store's currency, or the requested display currency if the `currency` parameter was used.",
            "example": 19.99
          },
          "percent_off": {
            "type": "integer",
            "description": "Percentage off from the original price if a discount applies.",
            "example": 10
          },
          "recurring_discount": {
            "type": "boolean",
            "description": "Indicates whether the discount is applied on each occurrence of the subscription.",
            "example": true
          },
          "discount_end": {
            "type": "integer",
            "description": "Timestamp of the discount expiration. *(expressed in the store timezone)*",
            "example": 1758563356951
          },
          "donation": {
            "type": "boolean",
            "description": "Indicates if the product is a donation-type product, this allow the user to choose the amount of the donation,  `price` therefore defines the minimum donation amount.",
            "example": false
          },
          "min_donation": {
            "type": "number",
            "description": "Minimum donation amount (only present if donation is true). If currency parameter is used, this value is converted to the requested currency.",
            "example": 10.0
          },
          "description": {
            "type": "string",
            "description": "Full description of the product.",
            "example": "This product is quite amazing. It allows you to unlock our VIP + perks and showcase your skills on our server."
          },
          "gallery": {
            "type": "array",
            "description": "List of all images related to the product.",
            "items": {
              "type": "string"
            },
            "example": [
              "https://cdn.tip4serv.com/shops-img/example.png",
              "https://cdn.tip4serv.com/shops-img/another_image.jpg"
            ]
          },
          "youtube": {
            "type": "string",
            "description": "URL of the video associated with the product.",
            "example": "https://youtu.be/K1QICrgxTjA"
          },
          "category": {
            "oneOf": [
              {
                "type": "integer"
              },
              {
                "$ref": "#/components/schemas/Category"
              }
            ],
            "description": "Category the product belongs to (integer or full category object if details are enabled).",
            "example": 1
          },
          "featured": {
            "type": "boolean",
            "description": "Indicates whether the product is featured.",
            "example": true
          },
          "stock": {
            "type": "integer",
            "description": "Available stock of the product.",
            "example": 10
          },
          "trial": {
            "type": "integer",
            "description": "Number of trial days available for this product.",
            "example": 14
          },
          "renewal_start": {
            "type": "string",
            "description": "If trial days are enabled, defines when commands in the \"Do this after each renewal payment\" event start.\n\nAccepted values:  \n`first_payment`, `second_payment`\n",
            "example": "first_payment"
          },
          "delivery_method": {
            "type": "string",
            "description": "Indicates the delivery method used to deliver the actions of the product. Can\nPossible values:\n- `all_servers` : will deliver the product commands on every servers. - `server_choice` : the user will be prompted to choose on which server he wish to receive his product. - `auto_detect` : Tip4Serv will automatically detect on which server the user is connected, and deliver only on this server.\nIf no option is specified, the default option will be set to `all_servers`"
          },
          "server_choice": {
            "type": "boolean",
            "description": "Indicates whether the customer can select the server for product delivery.\n⚠ This flag is deprecated, please use delivery_mode instead, to know the delivery method of the actions.",
            "example": false
          },
          "quantity": {
            "type": "boolean",
            "description": "Indicates whether the customer can select the quantity to purchase.",
            "example": true
          },
          "cmd_multiplier": {
            "type": "boolean",
            "description": "If quantity is selectable, determines whether commands are multiplied by the chosen quantity.",
            "example": false
          },
          "files": {
            "type": "boolean",
            "description": "Indicates if the product provides downloadable files upon purchase.",
            "example": false
          },
          "subscription": {
            "type": "boolean",
            "description": "Indicates whether the product is a subscription.",
            "example": true
          },
          "disable_giftcard_payments": {
            "type": "boolean",
            "description": "Indicates whether the product can be purchased with a giftcard. If not specified this option will be set to false by default. If set to true a customer won't be able to purchase this product with a giftcard.\n"
          },
          "giftcard": {
            "type": "boolean",
            "description": "Indicates whether the product supports gift cards.",
            "example": false
          },
          "giftcard_expiration": {
            "type": "boolean",
            "description": "Indicates whether the generated gift card will eventually expire.",
            "example": false
          },
          "giftcard_expiration_duration_periodicity": {
            "type": "string",
            "description": "Unit of time for the gift card expiration duration.\n\nPossible values:  \n- `day` – duration in days   - `week` – duration in weeks   - `month` – duration in months   - `year` – duration in years\n\nExample: If `duration_periodicity = month` and `period_num = 3`, the giftcard will expire 3 months after the purchase.\n",
            "example": "month"
          },
          "giftcard_expiration_period_num": {
            "type": "integer",
            "description": "Number of `duration_periodicity` units before the giftcard expires.\nExamples:  \n- Giftcard expires after 3 months  \n- Giftcard expires after 1 year\nExample: `period_num: 3` → charge every 3 months\n",
            "example": 3
          },
          "enable_stock": {
            "type": "boolean",
            "description": "Indicates if stock management is enabled for the product.",
            "example": false
          },
          "subscription_cycle": {
            "type": "string",
            "description": "Determines whether subscriptions are recurring or expire by default. Accepted values:   `each`, `expire`",
            "example": "each"
          },
          "cumul_sub": {
            "type": "boolean",
            "description": "If set to false prevents customers from subscribing to the same product multiple times.",
            "example": false
          },
          "onetime_sub": {
            "type": "boolean",
            "description": "Allows customers to purchase the product for a single billing cycle without subscribing.",
            "example": false
          },
          "enable_trial": {
            "type": "boolean",
            "description": "Indicates whether trial days are enabled.",
            "example": true
          },
          "purchase_limit": {
            "$ref": "#/components/schemas/PurchaseLimit",
            "description": "Rules limiting the number of times a customer can purchase the product."
          },
          "duration_periodicity": {
            "type": "string",
            "description": "Unit of time for the subscription duration.\n\nPossible values:  \n- `day` – duration in days  \n- `week` – duration in weeks  \n- `month` – duration in months  \n- `year` – duration in years\n\nExample: If `duration_periodicity = month` and `period_num = 3`, the subscription lasts 3 months.\n",
            "example": "month"
          },
          "period_num": {
            "type": "number",
            "description": "Number of `duration_periodicity` units before the subscription expires or the next charge occurs.\n\nExamples:  \n- Charge the customer every 3 months  \n- Charge the customer every 1 year\n\nAccepted ranges:  \n- 1–99 for days  \n- 1–52 for weeks  \n- 1–12 for months  \n- 1–1 for years\n\nExample: `period_num: 3` → charge every 3 months\n",
            "example": 3
          },
          "custom_rules": {
            "type": "array",
            "description": "Array of custom rules applied to the product's custom fields.",
            "items": {
              "$ref": "#/components/schemas/CustomRule"
            }
          },
          "custom_fields": {
            "type": "array",
            "description": "Array of custom fields attached to the product.",
            "items": {
              "$ref": "#/components/schemas/CustomField"
            }
          },
          "created_date": {
            "type": "integer",
            "description": "Timestamp of product creation in the store's timezone.",
            "example": 1758563300951
          },
          "last_edited": {
            "type": "integer",
            "description": "Timestamp of the last product modification in the store's timezone.",
            "example": 1758563356951
          },
          "server_options": {
            "type": "array",
            "description": "Array of server options to choose, will be sent if the delivery_method is  `server_choice`.",
            "items": {
              "$ref": "#/components/schemas/ServerChoice"
            }
          },
          "actions": {
            "type": "object",
            "description": "Array of different actions to execute, indexed by it's server ID.",
            "additionalProperties": {
              "$ref": "#/components/schemas/Action"
            },
            "example": {
              "36252": {
                "payment_command": [
                  {
                    "str": "AddPoints {steam_id} 5000",
                    "event": "Must be online"
                  },
                  {
                    "str": "say Thanks {steam_username} for your purchase!",
                    "event": "Execute"
                  }
                ],
                "refund_command": [
                  {
                    "str": "RemovePoints {steam_id} 5000",
                    "event": "Must be online"
                  }
                ]
              }
            }
          },
          "currency": {
            "type": "string",
            "description": "Currency in which all prices are expressed. Matches the requested `currency` parameter, or the store's default currency if not specified.",
            "example": "GBP"
          }
        },
        "required": [
          "id",
          "name",
          "slug",
          "price",
          "status",
          "description",
          "gallery",
          "category",
          "featured",
          "stock",
          "trial",
          "server_choice",
          "delivery_method",
          "quantity",
          "files",
          "subscription",
          "giftcard",
          "enable_stock",
          "cumul_sub",
          "enable_trial",
          "created_date",
          "last_edited",
          "actions"
        ]
      },
      "Action": {
        "type": "object",
        "properties": {
          "payment_command": {
            "type": "array",
            "description": "Commands which are executed when a payment is made.",
            "items": {
              "$ref": "#/components/schemas/SimpleServerCommand"
            }
          },
          "refund_command": {
            "type": "array",
            "description": "Commands which are executed when a payment is made.",
            "items": {
              "$ref": "#/components/schemas/SimpleServerCommand"
            }
          },
          "renewal_command": {
            "type": "array",
            "description": "Commands which are executed when a payment is made.",
            "items": {
              "$ref": "#/components/schemas/SimpleServerCommand"
            }
          },
          "expire_command": {
            "type": "array",
            "description": "Commands which are executed when a payment is made.",
            "items": {
              "$ref": "#/components/schemas/SimpleServerCommand"
            }
          }
        }
      },
      "SimpleServerCommand": {
        "type": "object",
        "properties": {
          "str": {
            "description": "Content of the command to be executed",
            "example": "AddPoints {steam_id} 5000"
          },
          "event": {
            "description": "Event triggering the execution of the command. Can take the following values: `Execute`, `Must be online`",
            "example": "Must be online"
          }
        }
      },
      "ServerChoice": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "description": "Server ID",
            "example": 10
          },
          "name": {
            "type": "string",
            "description": "Server Name",
            "example": "Duster SMP #1"
          }
        },
        "required": [
          "id",
          "name"
        ]
      },
      "PurchaseLimit": {
        "type": "object",
        "properties": {
          "purchase_times": {
            "type": "integer",
            "description": "Maximum number of times the product can be purchased.",
            "example": 2
          },
          "type": {
            "type": "string",
            "description": "Defines when the purchase limit applies.\n\nAccepted values:  \n- `every` → limit purchases to a recurring time period  \n- `only` → limit purchases permanently\n",
            "example": "every"
          },
          "cycle": {
            "type": "integer",
            "description": "Number of time units before the purchase limit resets.\n\nExample:  \n- Limit purchases to 1 time every 1 month  \n- Limit purchases to 1 time every 3 months\n\nAccepted ranges: 1–99 for days, 1–52 for weeks, 1–12 for months, 1–1 for years\n",
            "example": 3
          },
          "periodicity": {
            "type": "string",
            "description": "Unit of time used to define the purchase limit.\n\nAccepted values: `day`, `week`, `month`, `year`\n",
            "example": "month"
          }
        },
        "required": [
          "purchase_times",
          "type",
          "cycle",
          "periodicity"
        ]
      },
      "ServerGeneral": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "format": "int64",
            "description": "Unique identifier of the server.",
            "example": 10200
          },
          "name": {
            "type": "string",
            "description": "Name of the server.",
            "example": "My custom rust server"
          },
          "game_name": {
            "type": "string",
            "description": "Game associated with the server.",
            "example": "rust"
          },
          "connected": {
            "type": "boolean",
            "description": "Indicates whether the server is currently connected.",
            "example": true
          }
        },
        "required": [
          "id",
          "name",
          "game_name",
          "connected"
        ]
      },
      "Server": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "format": "int64",
            "description": "Unique identifier of the server.",
            "example": 10200
          },
          "name": {
            "type": "string",
            "description": "Name of the server.",
            "example": "My custom discord server"
          },
          "game_name": {
            "type": "string",
            "description": "Game associated with the server.",
            "example": "discord"
          },
          "connected": {
            "type": "boolean",
            "description": "Indicates whether the server is currently connected.",
            "example": true
          },
          "auth": {
            "type": "string",
            "description": "Method used by the server to identify its players.  \n\nAccepted values: `steamid`, `discordid`, `eosid`, `username`, `player_id`\n",
            "example": "discordid"
          },
          "discord_id": {
            "type": "integer",
            "format": "int64",
            "description": "Discord server ID if applicable.",
            "example": 1057619727985426400
          }
        },
        "required": [
          "id",
          "name",
          "game_name",
          "auth"
        ]
      },
      "UpdateGiftCard": {
        "properties": {
          "name": {
            "type": "string",
            "description": "Name of the gift card.",
            "example": "$25 Gift Card"
          },
          "initial_credit": {
            "type": "integer",
            "description": "Initial credit value of the gift card in its currency.",
            "example": 25
          },
          "remaining_credit": {
            "type": "integer",
            "description": "Remaining credit on the gift card in its currency",
            "example": 25
          },
          "update_currency": {
            "type": "boolean",
            "description": "Indicate if the gift card currency must be modified to the current store currency.",
            "example": true
          },
          "expiration": {
            "type": "integer",
            "description": "Timestamp of gift card expiration in the store's timezone.\n*(Set this to null, to remove expiration)*\n",
            "example": 1758563356951
          }
        }
      },
      "CreateGiftCard": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "description": "Name of the gift card.",
            "example": "£50 Gift Card"
          },
          "initial_credit": {
            "type": "integer",
            "description": "Initial credit value of the gift card in its currency.",
            "example": 50
          },
          "expiration": {
            "type": "integer",
            "description": "Timestamp of gift card expiration in the store's timezone.\n",
            "example": 1758563356951
          }
        },
        "required": [
          "name",
          "initial_credit"
        ]
      },
      "ResponseGiftCard": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "format": "int64",
            "description": "Unique identifier of the gift card.",
            "example": 334
          },
          "name": {
            "type": "string",
            "description": "Name of the gift card.",
            "example": "£50 Gift Card"
          },
          "creation_date": {
            "type": "integer",
            "description": "Timestamp of gift card creation in the store's timezone.",
            "example": 1758563356951
          },
          "code": {
            "type": "string",
            "description": "Unique code of the gift card.",
            "example": "0M35-HYBA-IYWT-Y280"
          },
          "initial_credit": {
            "type": "integer",
            "description": "Initial credit value of the gift card in its currency.",
            "example": 50
          },
          "remaining_credit": {
            "type": "integer",
            "description": "Remaining credit on the gift card in its currency.",
            "example": 43.47
          },
          "currency": {
            "type": "string",
            "description": "Currency of the gift card.",
            "example": "EUR"
          },
          "expiration": {
            "type": "integer",
            "description": "Timestamp of gift card expiration in the store's timezone.\n",
            "example": 1758563356951
          }
        },
        "required": [
          "id",
          "name",
          "creation_date",
          "code",
          "initial_credit",
          "remaining_credit",
          "currency"
        ]
      },
      "CustomRule": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "format": "int64",
            "description": "Unique identifier of the custom rule.",
            "example": 1
          },
          "order": {
            "type": "integer",
            "format": "int64",
            "description": "Priority order of the custom rule.",
            "example": 1
          },
          "name": {
            "type": "string",
            "description": "Name of the custom rule.",
            "example": "My new rule"
          },
          "type": {
            "type": "string",
            "description": "Type of custom rule. Accepted values: `number_limit`",
            "example": "number_limit"
          },
          "min": {
            "type": "integer",
            "format": "int64",
            "description": "Minimum value if the rule type is `number_limit`."
          },
          "max": {
            "type": "integer",
            "format": "int64",
            "description": "Maximum value if the rule type is `number_limit`."
          },
          "fields": {
            "type": "array",
            "description": "IDs of custom fields affected by this rule.",
            "items": {
              "type": "number",
              "format": "int64"
            },
            "example": [
              1,
              3
            ]
          }
        },
        "required": [
          "id",
          "order",
          "name",
          "type"
        ]
      },
      "CreateCustomRule": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "description": "Name of the custom rule.",
            "example": "My new rule"
          },
          "type": {
            "type": "string",
            "description": "Type of custom rule. Accepted values: `number_limit`",
            "example": "number_limit"
          },
          "min": {
            "type": "integer",
            "format": "int64",
            "description": "Minimum value if the rule type is `number_limit`."
          },
          "max": {
            "type": "integer",
            "format": "int64",
            "description": "Maximum value if the rule type is `number_limit`."
          },
          "fields": {
            "type": "array",
            "description": "IDs of custom fields affected by this rule.",
            "items": {
              "type": "number",
              "format": "int64"
            },
            "example": [
              1,
              3
            ]
          }
        },
        "required": [
          "name",
          "type"
        ]
      },
      "CreateCustomField": {
        "type": "object",
        "properties": {
          "order": {
            "type": "integer",
            "format": "int64",
            "description": "Priority order of the custom field. If no order is provided, this custom field will have the smallest priority.",
            "example": 1
          },
          "name": {
            "type": "string",
            "description": "Name of the custom field.",
            "example": "My custom field"
          },
          "type": {
            "type": "string",
            "description": "Type of custom field. Accepted values: `text`, `checkbox`, `number`, `selection`\n",
            "example": "text"
          },
          "marker": {
            "type": "string",
            "description": "Placeholder marker used in commands.",
            "example": "bonus_points"
          },
          "if_not_filled": {
            "type": "string",
            "description": "Behavior if field is left empty. Accepted values: `do_not_execute`, `remove_marker`, `use_default`"
          },
          "default_value": {
            "type": "string",
            "description": "Default value used if `if_not_filled` is set to `use_default`.",
            "example": 10
          },
          "required": {
            "type": "boolean",
            "description": "Indicates if the custom field is mandatory.",
            "example": true
          },
          "minimum": {
            "type": "integer",
            "description": "Minimum value if field type is `number`.",
            "example": 1
          },
          "maximum": {
            "type": "integer",
            "description": "Maximum value if field type is `number`.",
            "example": 100
          },
          "step": {
            "type": "integer",
            "description": "Increment step if field type is `number`.",
            "example": 1
          },
          "number_type": {
            "type": "string",
            "description": "Specifies number input type. Accepted values: `number`, `range`"
          },
          "price": {
            "type": "integer",
            "description": "Additional price added to product if field is selected.",
            "example": 2.5
          },
          "options": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CreateCustomFieldOption"
            },
            "description": "Options available if field type is `selection`."
          }
        },
        "required": [
          "name",
          "type",
          "required"
        ]
      },
      "CustomField": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "format": "int64",
            "description": "Unique identifier of the custom field.",
            "example": 1
          },
          "order": {
            "type": "integer",
            "format": "int64",
            "description": "Priority order of the custom field.",
            "example": 1
          },
          "name": {
            "type": "string",
            "description": "Name of the custom field.",
            "example": "My custom field"
          },
          "type": {
            "type": "string",
            "description": "Type of custom field. Accepted values: `text`, `checkbox`, `number`, `selection`\n",
            "example": "text"
          },
          "marker": {
            "type": "string",
            "description": "Placeholder marker used in commands.",
            "example": "bonus_points"
          },
          "if_not_filled": {
            "type": "string",
            "description": "Behavior if field is left empty. Accepted values: `do_not_execute`, `remove_marker`, `use_default`"
          },
          "default_value": {
            "type": "string",
            "description": "Default value used if `if_not_filled` is set to `use_default`.",
            "example": 10
          },
          "required": {
            "type": "boolean",
            "description": "Indicates if the custom field is mandatory.",
            "example": true
          },
          "minimum": {
            "type": "integer",
            "description": "Minimum value if field type is `number`.",
            "example": 1
          },
          "maximum": {
            "type": "integer",
            "description": "Maximum value if field type is `number`.",
            "example": 100
          },
          "step": {
            "type": "integer",
            "description": "Increment step if field type is `number`.",
            "example": 1
          },
          "number_type": {
            "type": "string",
            "description": "Specifies number input type. Accepted values: `number`, `range`"
          },
          "price": {
            "type": "integer",
            "description": "Additional price added to product if field is selected.",
            "example": 2.5
          },
          "options": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CustomFieldOption"
            },
            "description": "Options available if field type is `selection`."
          }
        },
        "required": [
          "id",
          "order",
          "name",
          "type",
          "required"
        ]
      },
      "CreateCustomFieldOption": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "description": "Name of the option.",
            "example": "Red"
          },
          "value": {
            "type": "integer",
            "description": "Value corresponding to the option.",
            "example": 3
          },
          "price": {
            "type": "integer",
            "description": "Price adjustment if option is selected.",
            "example": 2.5
          }
        },
        "required": [
          "name",
          "value",
          "price"
        ]
      },
      "CustomFieldOption": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "description": "Unique identifier of the option.",
            "example": 2
          },
          "order": {
            "type": "integer",
            "description": "Priority order of the option.",
            "example": 2
          },
          "name": {
            "type": "string",
            "description": "Name of the option.",
            "example": "Red"
          },
          "value": {
            "type": "integer",
            "description": "Value corresponding to the option.",
            "example": 3
          },
          "price": {
            "type": "integer",
            "description": "Price adjustment if option is selected.",
            "example": 2.5
          }
        },
        "required": [
          "id",
          "order",
          "name",
          "value",
          "price"
        ]
      },
      "Category": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "format": "int64",
            "description": "Unique identifier of the category.",
            "example": 67
          },
          "name": {
            "type": "string",
            "description": "Name of the category.",
            "example": "Perks"
          },
          "description": {
            "type": "string",
            "description": "Description of the category.",
            "example": "In this category, you will find special perks for the Duster Epic Rust server. Ranging from vehicles to epic items."
          },
          "slug": {
            "type": "string",
            "description": "URL-friendly name of the category.",
            "example": "perks"
          },
          "hide": {
            "type": "boolean",
            "description": "Determines if the category is hidden.",
            "example": false
          },
          "main_redirect": {
            "type": "boolean",
            "description": "Redirect to home page if category is accessed.",
            "example": false
          },
          "parent_id": {
            "type": "integer",
            "format": "int64",
            "description": "Parent category ID if this is a sub-category.",
            "example": 1
          }
        },
        "required": [
          "id",
          "name",
          "slug",
          "hide",
          "main_redirect"
        ]
      },
      "SubscriptionGeneral": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "format": "int64",
            "description": "Unique identifier of the subscription.",
            "example": 1
          },
          "name": {
            "type": "string",
            "description": "Name of the subscription.",
            "example": "VIP+ Subscription"
          },
          "status": {
            "type": "string",
            "description": "Status of the subscription. Accepted values: `Processed`, `Paid`, `Expired`, `Expiry`, `Pending`, `Renewal`, `Refused`\n"
          },
          "price": {
            "type": "integer",
            "description": "Subscription price in store currency.",
            "example": 6.49
          },
          "onetime": {
            "type": "boolean",
            "description": "Indicates if subscription is a one-time payment.",
            "example": false
          },
          "username": {
            "type": "string",
            "description": "Username of the subscriber.",
            "example": "Duster"
          },
          "start_date": {
            "type": "integer",
            "description": "Subscription start timestamp in store timezone.",
            "example": 1760980455708
          },
          "next_payment": {
            "type": "integer",
            "description": "If the subscription is a recurring one this indicate the next payment timestamp in store timezone.",
            "example": 1761674734637
          },
          "expire_date": {
            "type": "integer",
            "description": "If the subscription is a one-time payment this indicate the expire date timestamp in store timezone.",
            "example": 1761674734637
          },
          "unsubscribed": {
            "type": "boolean",
            "description": "Indicates if subscription has been cancelled.",
            "example": false
          },
          "duration_periodicity": {
            "type": "string",
            "description": "Time unit for subscription duration. Possible values: `day`, `week`, `month`, `year`",
            "example": "month"
          },
          "period_num": {
            "type": "number",
            "description": "Number of time units before subscription expires or next charge.",
            "example": 3
          },
          "currency": {
            "type": "string",
            "description": "Currency of the subscription.",
            "example": "USD"
          },
          "details_page": {
            "type": "string",
            "description": "View more details about the subscription on this page.",
            "example": "https://tip4serv.com/dashboard/subscription-details?id=1"
          }
        },
        "required": [
          "id",
          "name",
          "status",
          "price",
          "onetime",
          "username",
          "start_date",
          "currency",
          "unsubscribed",
          "details_page"
        ]
      },
      "ResponseDiscount": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "format": "int64",
            "description": "Unique identifier of the discount.",
            "example": 42
          },
          "name": {
            "type": "string",
            "description": "Name of the discount.",
            "example": "Summer Sale"
          },
          "value": {
            "type": "integer",
            "description": "Discount percentage (1-100).",
            "example": 20
          },
          "minimum_spending": {
            "type": "integer",
            "description": "Minimum cart amount (in store currency) required for this discount to apply. Only present when assign is basket_content.",
            "example": 50
          },
          "assign": {
            "type": "string",
            "description": "What the discount applies to.",
            "enum": [
              "all_products",
              "all_subscriptions",
              "all_products_and_subscriptions",
              "selected_products_and_categories",
              "basket_content"
            ],
            "example": "all_products_and_subscriptions"
          },
          "recurring": {
            "type": "boolean",
            "description": "Whether the discount applies to every recurring payment of a subscription.",
            "example": false
          },
          "start_date": {
            "type": "integer",
            "description": "Start date timestamp in store timezone.",
            "example": 1758583356
          },
          "expiration_date": {
            "type": "integer",
            "description": "Expiration date timestamp in store timezone. Only present if an expiration date is set.",
            "example": 1761234717
          },
          "accepted_categories": {
            "type": "array",
            "description": "List of category IDs the discount is assigned to. Empty array means it is not limited to specific categories. Only relevant when assign is selected_products_and_categories.",
            "items": {
              "type": "integer"
            },
            "example": [
              1,
              3
            ]
          },
          "accepted_products": {
            "type": "array",
            "description": "List of product IDs the discount is assigned to. Empty array means it is not limited to specific products. Only relevant when assign is selected_products_and_categories.",
            "items": {
              "type": "integer"
            },
            "example": [
              10,
              25
            ]
          }
        },
        "required": [
          "id",
          "name",
          "value",
          "assign",
          "recurring",
          "accepted_categories",
          "accepted_products",
          "start_date"
        ]
      },
      "UpdateCoupon": {
        "type": "object",
        "properties": {
          "code": {
            "type": "string",
            "description": "Coupon code used by customers",
            "example": "7X2ZZABEF8"
          },
          "type": {
            "type": "string",
            "description": "Type of discount. Accepted values `percentage`, `value`",
            "example": "value"
          },
          "value": {
            "type": "integer",
            "description": "Discount amount (percentage or fixed value depending on `type`).",
            "example": 10
          },
          "limit": {
            "type": "integer",
            "description": "Maximum number of uses allowed for this coupon.",
            "example": 50
          },
          "minimum": {
            "type": "integer",
            "description": "Minimum purchase amount in the store's currency required to use the coupon.",
            "example": 9.99
          },
          "maximum": {
            "type": "integer",
            "description": "Maximum purchase amount in the store's currency allowed to use the coupon.",
            "example": 49.99
          },
          "expiration": {
            "type": "integer",
            "description": "Expiration timestamp of the coupon in store timezone.\n*(Set this to null, to remove expiration)*\n",
            "example": 1758583356951
          },
          "accepted_categories": {
            "type": "array",
            "description": "List of category IDs eligible for the coupon. Empty array means all categories.\nIf omitted this property won't be modified.\n",
            "items": {
              "type": "integer"
            },
            "example": [
              1
            ]
          },
          "accepted_products": {
            "type": "array",
            "description": "List of product IDs eligible for the coupon. Empty array means all products. \nIf omitted this property won't be modified.\n",
            "items": {
              "type": "integer"
            },
            "example": [
              7,
              8
            ]
          }
        }
      },
      "CreateCoupon": {
        "type": "object",
        "properties": {
          "code": {
            "type": "string",
            "description": "Coupon code used by customers. (If not defined a random value will be set)",
            "example": "8H3LLGQXF9"
          },
          "type": {
            "type": "string",
            "description": "Type of discount. Accepted values: `percentage`, `value`",
            "example": "percentage"
          },
          "value": {
            "type": "integer",
            "description": "Discount amount (percentage or fixed value depending on `type`).",
            "example": 30
          },
          "limit": {
            "type": "integer",
            "description": "Maximum number of uses allowed for this coupon.",
            "example": 100
          },
          "minimum": {
            "type": "integer",
            "description": "Minimum purchase amount in the store's currency required to use the coupon.",
            "example": 9.99
          },
          "maximum": {
            "type": "integer",
            "description": "Maximum purchase amount in the store's currency allowed to use the coupon.",
            "example": 49.99
          },
          "expiration": {
            "type": "integer",
            "description": "Expiration timestamp of the coupon in store timezone.",
            "example": 1758583356951
          },
          "accepted_categories": {
            "type": "array",
            "description": "List of category IDs eligible for the coupon. Empty array means all categories.\nIf omitted will accept every category\n",
            "items": {
              "type": "integer"
            },
            "example": [
              0,
              2
            ]
          },
          "accepted_products": {
            "type": "array",
            "description": "List of product IDs eligible for the coupon. Empty array means all products. \nIf omitted will accept every product.\n",
            "items": {
              "type": "integer"
            },
            "example": [
              1,
              2
            ]
          }
        },
        "required": [
          "type",
          "value"
        ]
      },
      "ResponseCoupon": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "format": "int64",
            "description": "Unique identifier of the coupon.",
            "example": 800
          },
          "code": {
            "type": "string",
            "description": "Coupon code used by customers.",
            "example": "8H3LLGQXF9"
          },
          "type": {
            "type": "string",
            "description": "Type of discount. Accepted values: `percentage`, `value`",
            "example": "percentage"
          },
          "value": {
            "type": "integer",
            "description": "Discount amount (percentage or fixed value depending on `type`).",
            "example": 30
          },
          "used": {
            "type": "integer",
            "description": "Number of times this coupon has been used.",
            "example": 10
          },
          "limit": {
            "type": "integer",
            "description": "Maximum number of uses allowed for this coupon.",
            "example": 100
          },
          "minimum": {
            "type": "integer",
            "description": "Minimum purchase amount in the store's currency required to use the coupon.",
            "example": 9.99
          },
          "maximum": {
            "type": "integer",
            "description": "Maximum purchase amount in the store's currency allowed to use the coupon.",
            "example": 49.99
          },
          "expiration": {
            "type": "integer",
            "description": "Expiration timestamp of the coupon in store timezone.",
            "example": 1758583356951
          },
          "accepted_categories": {
            "type": "array",
            "description": "List of category IDs eligible for the coupon. Empty array means all categories.",
            "items": {
              "type": "integer"
            },
            "example": [
              0,
              2
            ]
          },
          "accepted_products": {
            "type": "array",
            "description": "List of product IDs eligible for the coupon. Empty array means all products.",
            "items": {
              "type": "integer"
            },
            "example": [
              1,
              2
            ]
          }
        },
        "required": [
          "id",
          "code",
          "type",
          "value",
          "used",
          "accepted_categories",
          "accepted_products"
        ]
      },
      "Store": {
        "type": "object",
        "properties": {
          "id": {
            "type": "number",
            "description": "Unique identifier of the store.",
            "example": 762
          },
          "owner": {
            "type": "number",
            "description": "Unique ID of the store owner account.",
            "example": 10000
          },
          "title": {
            "type": "string",
            "description": "Title or name of the store.",
            "example": "Epic store"
          },
          "subtitle": {
            "type": "string",
            "description": "Subtitle of the store.",
            "example": "The most epic store you will ever find."
          },
          "description": {
            "type": "string",
            "description": "Description of the store.",
            "example": "The best store in the world!"
          },
          "domain": {
            "type": "string",
            "description": "Subdomain used for the store. Full URL: `<domain>.tip4serv.com`.",
            "example": "epicstore"
          },
          "custom_domain": {
            "type": "string",
            "description": "Custom domain registered for the store, if any.",
            "example": "shop.epicstore.com"
          },
          "logo": {
            "type": "string",
            "description": "URL of the store logo.",
            "example": "https://tip4serv.com/template/images/defaultLogo.jpg"
          },
          "currency": {
            "type": "string",
            "description": "Currency used by the store.",
            "example": "USD"
          },
          "timezone": {
            "type": "string",
            "description": "Timezone in which timestamps for the store are expressed.",
            "example": "Europe/Paris"
          },
          "color": {
            "type": "string",
            "description": "Main theme color of the store.",
            "example": "#5990f1"
          },
          "social_medias": {
            "$ref": "#/components/schemas/SocialMedias"
          },
          "menu_links": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/MenuLink"
            }
          }
        },
        "required": [
          "id",
          "owner",
          "title",
          "description",
          "domain",
          "logo",
          "currency",
          "timezone",
          "color"
        ]
      },
      "MenuLink": {
        "type": "object",
        "properties": {
          "title": {
            "type": "string",
            "description": "Title of the link to be displayed.",
            "example": "Books"
          },
          "url": {
            "type": "string",
            "description": "URL of the link.",
            "example": "https://duster-books.com"
          }
        },
        "required": [
          "title",
          "url"
        ]
      },
      "SocialMedias": {
        "type": "object",
        "properties": {
          "facebook": {
            "type": "string",
            "example": "https://www.facebook.com/zuck/"
          },
          "instagram": {
            "type": "string",
            "example": "https://www.instagram.com/zuck/"
          },
          "tiktok": {
            "type": "string",
            "example": "https://www.tiktok.com/@openai"
          },
          "twitter": {
            "type": "string",
            "example": "https://x.com/X"
          },
          "youtube": {
            "type": "string",
            "example": "https://www.youtube.com/user/PewDiePie"
          },
          "twitch": {
            "type": "string",
            "example": "https://www.twitch.tv/openai"
          },
          "steam": {
            "type": "string",
            "example": "https://steamcommunity.com/profiles/76561198380145423"
          }
        }
      },
      "Theme": {
        "type": "object",
        "properties": {
          "id": {
            "type": "number",
            "description": "Unique identifier of the theme.",
            "example": 2
          },
          "short_name": {
            "type": "string",
            "description": "Short name of the theme.",
            "pattern": "^[a-z0-9_-]+$",
            "example": "neon"
          },
          "name": {
            "type": "string",
            "description": "Name of the theme publicly displayed.",
            "example": "Neon Theme"
          },
          "slug": {
            "type": "object",
            "description": "Sets of slugs, each being an object mapping between their section to their slug.",
            "additionalProperties": {
              "type": "string",
              "pattern": "^[a-z0-9_-]+$",
              "description": "Slug format."
            },
            "example": {
              "product": "product",
              "category": "category"
            }
          },
          "images": {
            "type": "object",
            "description": "Set of image references used in the theme.\nContains a required `favicon`, and any number of modes (e.g., `light`, `dark`),\neach being an object mapping image identifiers to URLs.\n",
            "required": [
              "favicon"
            ],
            "properties": {
              "favicon": {
                "type": "string",
                "description": "Favicon image filename.",
                "example": "8651782c6c560e354f81a5e586939495.jpg"
              },
              "light": {
                "type": "object",
                "description": "Light mode images.",
                "properties": {
                  "logo_header": {
                    "type": "string",
                    "example": "2613ab81ede1995cd1024b542962194a.png"
                  },
                  "logo_footer": {
                    "type": "string",
                    "example": "logo2.png"
                  },
                  "home_cover": {
                    "type": "string",
                    "example": "home_cover_inner.jpg"
                  }
                }
              },
              "dark": {
                "type": "object",
                "description": "Dark mode images.",
                "properties": {
                  "logo_header": {
                    "type": "string",
                    "example": "2613ab81ede1995cd1024b542962194a_dark.png"
                  },
                  "logo_footer": {
                    "type": "string",
                    "example": "logo2_dark.png"
                  },
                  "home_cover": {
                    "type": "string",
                    "example": "home_cover_inner_dark.jpg"
                  }
                }
              }
            }
          },
          "mode": {
            "type": "string",
            "description": "Default mode of the theme (e.g., `light`, `dark`, etc.).",
            "example": "light"
          },
          "widgets": {
            "type": "object",
            "description": "Arbitrary configuration options for widgets. Flexible key-value store where each entry represents a configurable parameter. Values can be strings, numbers, booleans, arrays, or nested objects.\n",
            "additionalProperties": {
              "oneOf": [
                {
                  "type": "string"
                },
                {
                  "type": "number"
                },
                {
                  "type": "boolean"
                },
                {
                  "type": "object"
                },
                {
                  "type": "array"
                }
              ]
            },
            "example": {
              "description": "below_categories_list",
              "top_customer": 1,
              "featured_product": 1,
              "top_product": 1,
              "show_banner": true
            }
          }
        },
        "required": [
          "id",
          "short_name",
          "name",
          "images",
          "mode"
        ]
      },
      "CustomerGeneral": {
        "type": "object",
        "properties": {
          "user_id": {
            "type": "number",
            "description": "Tip4Serv account ID of the customer.",
            "example": 19674
          },
          "username": {
            "type": "string",
            "description": "Username of the customer.",
            "example": "Duster"
          },
          "discord_id": {
            "type": "string",
            "description": "Discord ID of the customer.",
            "example": "274785054121525248"
          },
          "steam_id": {
            "type": "string",
            "description": "Steam ID of the customer.",
            "example": "76561198380145423"
          },
          "minecraft_uuid": {
            "type": "string",
            "description": "Minecraft UUID of the customer.",
            "example": "87ac351717f74762bfcaeff0ddd1a9bd"
          },
          "total_revenue": {
            "type": "number",
            "description": "Total amount spent by the customer, converted to the store's currency.",
            "example": 140.43
          },
          "payments": {
            "type": "number",
            "description": "Total number of payments made by the customer during the period.",
            "example": 5
          },
          "avatar": {
            "type": "string",
            "description": "URL of the customer's avatar.",
            "example": "https://mc-heads.net/head/1eb1416dbf0342728a8301118367cb0b"
          },
          "loyalty_points": {
            "type": "number",
            "description": "Loyalty points posessed by the customer. Is displayed only if loyalty points are set up on your store.",
            "example": 360
          }
        },
        "required": [
          "username",
          "total_revenue",
          "payments"
        ]
      },
      "PaymentGeneral": {
        "type": "object",
        "properties": {
          "id": {
            "type": "number",
            "description": "Unique identifier of the payment.",
            "example": 10203
          },
          "status": {
            "type": "string",
            "description": "Status of the payment. Accepted values: `Processed`, `Paid`, `Refunded`, `Pending`, `Refused`",
            "example": "Paid"
          },
          "cart": {
            "type": "string",
            "description": "The products name which were bought in the payment.",
            "example": "VIP+"
          },
          "sub_id": {
            "type": "number",
            "description": "Eventual subscription id to which the payment is related to.",
            "example": 1
          },
          "date": {
            "type": "number",
            "description": "Payment creation timestamp expressed in your store timezone.",
            "example": 1761234717
          },
          "amount": {
            "type": "number",
            "description": "Amount which was paid by the customer in the payment.",
            "example": 6.49
          },
          "currency": {
            "type": "string",
            "description": "Currency which was used for the payment.",
            "example": "USD"
          },
          "username": {
            "type": "string",
            "description": "Username which was used for the payment.",
            "example": "RandomUser123"
          },
          "identifier": {
            "type": "string",
            "description": "Identifier used for identifying the user. \n**Accepted identifiers:**  \n`email`, `username`, `eosid`, `ue4_id`, `steam_id`, `player_id`,  \n`minecraft_uuid`, `discord_id`,`fivem_citizen_id`, `minecraft_username`.\n",
            "example": "discord_id:274785054121525248"
          },
          "player_id": {
            "type": "string",
            "description": "Raw generic player identifier, without its type prefix.",
            "example": "C84A567"
          },
          "gateway": {
            "type": "string",
            "description": "Gateway used for the payment. Accepted values: `PayPal`, `Stripe\n",
            "example": "PayPal"
          },
          "details_page": {
            "type": "string",
            "description": "View more details about the payment on this page.",
            "example": "https://tip4serv.com/dashboard/payment-details?id=10203"
          }
        },
        "required": [
          "id",
          "status",
          "mode",
          "date",
          "amount",
          "currency",
          "username",
          "identifier",
          "gateway"
        ]
      },
      "Payment": {
        "type": "object",
        "properties": {
          "id": {
            "type": "number",
            "description": "Unique identifier of the payment.",
            "example": 10203
          },
          "status": {
            "type": "string",
            "description": "Status of the payment. Accepted values: `Processed`, `Paid`, `Refunded`, `Pending`, `Refused`",
            "example": "Paid"
          },
          "cart": {
            "type": "string",
            "description": "The products name which were bought in the payment.",
            "example": "VIP+"
          },
          "sub_id": {
            "type": "number",
            "description": "Eventual subscription id to which the payment is related to.",
            "example": 1
          },
          "date": {
            "type": "number",
            "description": "Payment creation timestamp expressed in your store timezone.",
            "example": 1761234717
          },
          "amount": {
            "type": "number",
            "description": "Amount which was paid by the customer in the payment.",
            "example": 6.49
          },
          "currency": {
            "type": "string",
            "description": "Currency which was used for the payment.",
            "example": "USD"
          },
          "username": {
            "type": "string",
            "description": "Username which was used for the payment.",
            "example": "RandomUser123"
          },
          "identifier": {
            "type": "string",
            "description": "Identifier used for identifying the user. \n**Accepted identifiers:**  \n`email`, `username`, `eosid`, `ue4_id`, `steam_id`, `player_id`,  \n`minecraft_uuid`, `discord_id`,`fivem_citizen_id`, `minecraft_username`.\n",
            "example": "discord_id:274785054121525248"
          },
          "gateway": {
            "type": "string",
            "description": "Gateway used for the payment. Accepted values: `PayPal`, `Stripe\n",
            "example": "PayPal"
          },
          "details_page": {
            "type": "string",
            "description": "View more details about the payment on this page.",
            "example": "https://tip4serv.com/dashboard/payment-details?id=10203"
          },
          "server_actions": {
            "type": "array",
            "description": "Server actions which were executed or are left to be executed.",
            "items": {
              "$ref": "#/components/schemas/ServerAction"
            }
          },
          "cart_details": {
            "type": "array",
            "description": "Detailed purchased cart by the user.",
            "items": {
              "$ref": "#/components/schemas/CartRow"
            }
          }
        },
        "required": [
          "id",
          "status",
          "mode",
          "date",
          "amount",
          "currency",
          "username",
          "identifier",
          "gateway",
          "server_actions",
          "cart_details"
        ]
      },
      "CartRow": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "description": "Unique identifier of the product ID.",
            "example": 202
          },
          "name": {
            "type": "string",
            "description": "Name of the product.",
            "example": "MVP+"
          },
          "price": {
            "type": "integer",
            "description": "Price of the product. (expressed in your store currency)",
            "example": 4.99
          },
          "quantity": {
            "type": "integer",
            "description": "Quantity in which the product have been bought.",
            "example": 1
          }
        },
        "required": [
          "id",
          "name",
          "price",
          "quantity"
        ]
      },
      "PaymentDelivery": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Unique identifier of the payment/subscription. Can have the following prefix : `pay_`, `sub_`",
            "example": "pay_71524"
          },
          "player": {
            "type": "string",
            "description": "Player name of the customer.",
            "example": "duster"
          },
          "username": {
            "type": "string",
            "description": "Username of the customer.",
            "example": "Dusterito"
          },
          "minecraft_uuid": {
            "type": "string",
            "description": "Minecraft UUID of the customer.",
            "example": "d4191228d7d247ab88cdb18636f4eecd"
          },
          "steam_id": {
            "type": "string",
            "description": "Steam ID of the customer.",
            "example": 76561198380145420
          },
          "player_id": {
            "type": "string",
            "description": "Raw generic player identifier of the customer.",
            "example": "C84A567"
          },
          "eos_id": {
            "type": "string",
            "description": "EOS ID of the customer.",
            "example": "0002e2f30b1f407cb21880d425a1e5eb"
          },
          "discord_id": {
            "type": "string",
            "description": "Discord ID of the customer.",
            "example": 274785054121525250
          },
          "cmds": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ServerCommand"
            }
          }
        }
      },
      "ServerCommand": {
        "type": "object",
        "properties": {
          "id": {
            "type": "number",
            "description": "Unique Identifier of the server command.",
            "example": 1
          },
          "state": {
            "type": "string",
            "description": "State of the command. Can take the following values : `Execute`,`Must be online`.",
            "enum": [
              "Execute",
              "Must be online"
            ],
            "example": "Execute"
          },
          "str": {
            "type": "string",
            "description": "The command string to execute on the server.",
            "example": "inventory.giveto 76561198380145423 scientist 5"
          }
        }
      },
      "DeliveredServerCommands": {
        "type": "object",
        "description": "Map of payment IDs to their executed commands.",
        "additionalProperties": {
          "type": "object",
          "required": [
            "action",
            "cmds"
          ],
          "properties": {
            "action": {
              "description": "Status of the payment. Can take the following values: `payment`,`paypalchargeback`,`renewal`,`expire`.",
              "type": "string",
              "enum": [
                "payment",
                "renewal",
                "paypalchargeback",
                "expire"
              ]
            },
            "cmds": {
              "type": "object",
              "description": "Map of command IDs and their execution status.",
              "additionalProperties": {
                "type": "string",
                "enum": [
                  "Executed",
                  "Not Executed"
                ]
              }
            }
          }
        },
        "example": {
          "pay_71565": {
            "action": "payment",
            "cmds": {
              "0": "Executed",
              "1": "Executed"
            }
          },
          "pay_71566": {
            "action": "renewal",
            "cmds": {
              "0": "Executed",
              "1": "Not Executed"
            }
          }
        }
      },
      "ServerAction": {
        "type": "object",
        "properties": {
          "id": {
            "type": "number",
            "description": "Unique Identifier of the server action.",
            "example": 1
          },
          "state": {
            "type": "string",
            "description": "State of the command. Can take the following values : `Execute`,`Must be online`.",
            "enum": [
              "Execute",
              "Must be online"
            ],
            "example": "Execute"
          },
          "str": {
            "type": "string",
            "description": "The command string to execute on the server. \n⚠ Not preprocessed, do not execute this command on a server. If you want to execute a command\nuse the /commands route.\n",
            "example": "inventory.giveto 76561198380145423 scientist 5"
          },
          "product_id": {
            "type": "number",
            "description": "Unique Identifier of the product ID.",
            "example": 14
          },
          "server_id": {
            "type": "number",
            "description": "Unique Identifier of the product ID.",
            "example": 23
          }
        },
        "required": [
          "id",
          "state",
          "str",
          "product_id",
          "server_id"
        ]
      },
      "CheckoutRequest": {
        "type": "object",
        "required": [
          "products"
        ],
        "properties": {
          "products": {
            "type": "array",
            "description": "The list of products to purchase.",
            "items": {
              "$ref": "#/components/schemas/CheckoutProduct"
            }
          },
          "currency": {
            "type": "string",
            "description": "Display currency code (optional). Supported currencies: GBP, USD, EUR, CAD, AUD, CHF. If omitted, prices are displayed in store currency. Converts all product prices (price, old_price, min_donation) and custom field prices.",
            "example": "USD"
          },
          "user": {
            "$ref": "#/components/schemas/CheckoutUser"
          },
          "redirect_success_checkout": {
            "type": "string",
            "description": "This optional parameter allows you to redirect your users to a specific URL after the payment was processed successfully.\n",
            "example": "https://mywebsite.com/page/success"
          },
          "redirect_canceled_checkout": {
            "type": "string",
            "description": "This optional parameter allows you to redirect your users to a specific URL if the user want to return back.\n",
            "example": "https://mywebsite.com/page/cancel"
          },
          "redirect_pending_checkout": {
            "type": "string",
            "description": "This optional parameter allows you to redirect your users to a specific URL after the payment was processed successfully but is still being verified.\n",
            "example": "https://mywebsite.com/page/pending"
          }
        }
      },
      "CheckoutUser": {
        "type": "object",
        "description": "This parameter is optional, if you wish to handle User authentication you must submit this parameter. Otherwise we'll handle it for you.\n\n\nUser identifiers used to validate the purchase.\nIf a field is required for a product, the API will return an error.\nRequired fields can be found using the /checkout/identifiers route.\n",
        "properties": {
          "email": {
            "type": "string",
            "description": "The customer email.",
            "example": "duster@example.com"
          },
          "minecraft_username": {
            "type": "string",
            "description": "The Minecraft username.",
            "example": "Notch"
          },
          "steam_id": {
            "type": "string",
            "description": "The SteamID64 (17 digits).",
            "example": "76561198000000000"
          },
          "discord_id": {
            "type": "string",
            "description": "The Discord ID of the user.",
            "example": 274785054121525250
          },
          "epic_id": {
            "type": "string",
            "description": "The Epic ID.",
            "example": "1234567890123456789"
          },
          "eos_id": {
            "type": "string",
            "description": "The EOSID.",
            "example": "0123456789abcdef0123456789abcdef"
          },
          "fivem_citizen_id": {
            "type": "string",
            "description": "The FiveM citizen id.",
            "example": "abc123"
          },
          "ingame_username": {
            "type": "string",
            "description": "The in-game username.",
            "example": "PlayerOne"
          },
          "rust_username": {
            "type": "string",
            "description": "The Rust username.",
            "example": "RustPlayer"
          }
        },
        "required": [
          "email"
        ]
      },
      "ProductFile": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "description": "Unique ID of the uploaded product file.",
            "example": 1
          },
          "file_name": {
            "type": "string",
            "description": "Display name of the uploaded file.",
            "example": "vip-pack.zip"
          },
          "expiration": {
            "type": "integer",
            "description": "Number of days the file remains available after purchase.\n`-1` means the file never expires.\n",
            "example": -1
          },
          "url": {
            "type": "string",
            "format": "uri",
            "description": "Internal or signed URL used to download the file.",
            "example": "https://api.tip4serv.com/v1/store/product/123/file/42/download"
          },
          "created_at": {
            "type": "integer",
            "description": "Unix timestamp when the file was uploaded.",
            "example": 1761234717
          }
        },
        "required": [
          "id",
          "file_name",
          "expiration",
          "created_at"
        ]
      },
      "CheckoutProduct": {
        "type": "object",
        "properties": {
          "product_id": {
            "type": "integer",
            "description": "The product ID. Make sure that at least `product_id` is defined or `product_slug`.",
            "example": 12
          },
          "product_slug": {
            "type": "string",
            "description": "Slug of the product. Make sure that at least `product_id` is defined or `product_slug`.",
            "example": "product-1"
          },
          "type": {
            "type": "string",
            "description": "The product purchase type. Can take the following values: `addtocart`, `subscribe`.\n(If you specify `addtocart` for a subscription-based product, the subscription will be bought as a one-time payment instead of a recurring subscription).\n\nIf no type is specified, here are the default values:\n- Simple products: `addtocart`\n- Subscriptions: `subscribe`\n",
            "example": "addtocart"
          },
          "quantity": {
            "type": "integer",
            "description": "The quantity to purchase.",
            "example": 1,
            "default": 1
          },
          "donation_amount": {
            "type": "number",
            "description": "The donation amount for \"free_price\" products, expressed in the store currency.",
            "example": 10.5
          },
          "server_selection": {
            "type": "integer",
            "description": "The selected server ID (if required by the product).",
            "example": 12
          },
          "custom_fields": {
            "type": "object",
            "description": "The custom fields values.\nFormat: custom_field_id: selected_value.\n",
            "additionalProperties": true,
            "example": {
              "2": 1,
              "3": 3,
              "4": "wooden_sword"
            }
          }
        }
      }
    }
  }
}