{
  "openapi" : "3.0.1",
  "info" : {
    "contact" : {
      "url" : "https://metacopier.io"
    },
    "description" : "Explore the power of the MetaCopier API! Our RESTful API offers scalable and secure access to accounts, projects, and more. Get started quickly with authentication, explore endpoints, and access code samples in various languages.<br/><br/>All dates are in ISO 8601<br/><br/>This API is not designed for real-time communication purposes. For instance, continuously polling account information such as open positions every second is not recommended.<br/><br/>Our frontend uses this API, so you can look at the requests on our frontend for examples.",
    "title" : "MetaCopier API",
    "version" : "1.2.6"
  },
  "servers" : [ {
    "url" : "https://api.metacopier.io",
    "description" : "Generated server url"
  } ],
  "security" : [ {
    "ApiKeyAuth" : [ ]
  } ],
  "tags" : [ {
    "description" : "To simplify the API, we combined the pending orders and positions into the 'positions' endpoint.\n\n## Regional API URLs\n\nUse the regional API URL where your account is deployed **for Trading API endpoints only**:\n\n```\nhttps://{region}.metacopier.io/rest/api/v1/accounts/{accountId}/positions\n```\n\n| Region | Host |\n|--------|------|\n| New York | `api-newyork` |\n| London | `api-london` |\n| Berlin | `api-berlin` |\n| Singapore | `api-singapore` |\n| Global | `api` |\n\n> **Recommended**: Use the regional URL for best performance. The global URL works but may have higher latency.\n\n> **Note**: For all other API endpoints (non-trading), always use the Global URL: `https://api.metacopier.io`",
    "name" : "Trading API"
  }, {
    "description" : "## Regional API URLs\n\nUse the regional API URL where your account is deployed **for TradingView Webhook endpoints**:\n\n```\nhttps://{region}.metacopier.io/rest/api/v1/webhooks/tradingview/{webhookId}\n```\n\n| Region | Host |\n|--------|------|\n| New York | `api-newyork` |\n| London | `api-london` |\n| Berlin | `api-berlin` |\n| Singapore | `api-singapore` |\n| Global | `api` |\n\n> **Recommended**: Use the regional URL for best performance. The global URL works but may have higher latency.\n\n> **Note**: For all other API endpoints (non-trading), always use the Global URL: `https://api.metacopier.io`",
    "name" : "TradingView Webhook API"
  } ],
  "paths" : {
    "/rest/api/v1/accounts" : {
      "get" : {
        "operationId" : "getAccounts",
        "parameters" : [ {
          "description" : "Filter by account type ID (1=MT5, 2=MT4, 3=DXtrade, 4=cTrader, 5=TradeLocker, 6=MatchTrader, 7=Binance, 8=Bybit, 9=Bitget, 10=BloFin, 11=OKX, 12=TradeStation, 13=Tradovate, 14=Alpaca, 15=Gate.io, 16=Bitunix, 17=Hyperliquid)",
          "example" : 1,
          "in" : "query",
          "name" : "accountTypeId",
          "required" : false,
          "schema" : {
            "type" : "integer",
            "format" : "int32"
          }
        }, {
          "description" : "Filter by login server (case-insensitive partial match anywhere in the server name, e.g., ICMarketsSC-MT5-4, dxtrade.instantfunding.io, live.ctraderapi.com:5035)",
          "example" : "ICMarketsSC",
          "in" : "query",
          "name" : "loginServer",
          "required" : false,
          "schema" : {
            "type" : "string"
          }
        }, {
          "description" : "Filter by login account number (case-insensitive partial match anywhere in the account number)",
          "example" : 12345,
          "in" : "query",
          "name" : "loginAccountNumber",
          "required" : false,
          "schema" : {
            "type" : "string"
          }
        }, {
          "description" : "Filter by account alias (case-insensitive partial match anywhere in the alias)",
          "example" : "Trading",
          "in" : "query",
          "name" : "alias",
          "required" : false,
          "schema" : {
            "type" : "string"
          }
        }, {
          "description" : "Filter by region ID (1=New York, 2=London, 3=Singapore, 4=Berlin)",
          "example" : 1,
          "in" : "query",
          "name" : "regionId",
          "required" : false,
          "schema" : {
            "type" : "integer",
            "format" : "int32"
          }
        }, {
          "description" : "Filter by account status ID (1=New, 2=Active, 3=Stopped, 4=Deleted)",
          "example" : 2,
          "in" : "query",
          "name" : "accountStatusId",
          "required" : false,
          "schema" : {
            "type" : "integer",
            "format" : "int32"
          }
        }, {
          "description" : "Maximum number of accounts to return",
          "example" : 100,
          "in" : "query",
          "name" : "limit",
          "required" : false,
          "schema" : {
            "type" : "integer",
            "format" : "int32"
          }
        }, {
          "description" : "Number of accounts to skip for pagination",
          "example" : 0,
          "in" : "query",
          "name" : "offset",
          "required" : false,
          "schema" : {
            "type" : "integer",
            "format" : "int32"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "type" : "array",
                  "items" : {
                    "$ref" : "#/components/schemas/AccountDTO"
                  }
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Get all accounts",
        "tags" : [ "Account API" ]
      },
      "post" : {
        "description" : "Creates a new account. If a callbackUrl is provided in the request body, the account creation is processed asynchronously: the API returns 202 Accepted immediately with a requestId, and POSTs the result to the callback URL once done. Only one account creation per project is processed at a time; additional async requests are queued and processed sequentially.",
        "operationId" : "createAccount",
        "requestBody" : {
          "content" : {
            "application/json" : {
              "schema" : {
                "$ref" : "#/components/schemas/AccountDTO"
              }
            }
          },
          "required" : true
        },
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "type" : "object"
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Create an account",
        "tags" : [ "Account API" ]
      }
    },
    "/rest/api/v1/accounts/activateAllCopiers" : {
      "post" : {
        "operationId" : "activateAllCopiers",
        "responses" : {
          "204" : {
            "description" : "No Content"
          }
        },
        "summary" : "Activate all copiers across all accounts",
        "tags" : [ "Account API" ]
      }
    },
    "/rest/api/v1/accounts/async" : {
      "get" : {
        "description" : "Returns all tracked asynchronous account creation requests and their current statuses. Statuses are retained for 1 hour after completion.",
        "operationId" : "getAllAsyncAccountCreationStatuses",
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "type" : "array",
                  "items" : {
                    "$ref" : "#/components/schemas/AsyncAccountCreationResponseDTO"
                  }
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Get all async account creation requests",
        "tags" : [ "Account API" ]
      }
    },
    "/rest/api/v1/accounts/async/{requestId}" : {
      "get" : {
        "description" : "Returns the current status of an asynchronous account creation request. Status values: QUEUED (waiting to be processed), PROCESSING (currently being created), COMPLETED (success, includes the account), FAILED (includes error message). Statuses are retained for 1 hour after completion.",
        "operationId" : "getAsyncAccountCreationStatus",
        "parameters" : [ {
          "description" : "The requestId returned by the async POST /accounts call",
          "example" : "acc_a1b2c3d4e5f67890",
          "in" : "path",
          "name" : "requestId",
          "required" : true,
          "schema" : {
            "type" : "string"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/AsyncAccountCreationResponseDTO"
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Get async account creation status",
        "tags" : [ "Account API" ]
      }
    },
    "/rest/api/v1/accounts/configurationSummary" : {
      "get" : {
        "description" : "Returns the same accounts as GET /accounts, but each AccountDTO has its copiers, riskLimits and features collections populated.",
        "operationId" : "getAccountsConfigurationSummary",
        "parameters" : [ {
          "description" : "Filter by account type ID",
          "in" : "query",
          "name" : "accountTypeId",
          "required" : false,
          "schema" : {
            "type" : "integer",
            "format" : "int32"
          }
        }, {
          "description" : "Filter by login server (case-insensitive partial match)",
          "in" : "query",
          "name" : "loginServer",
          "required" : false,
          "schema" : {
            "type" : "string"
          }
        }, {
          "description" : "Filter by login account number (case-insensitive partial match)",
          "in" : "query",
          "name" : "loginAccountNumber",
          "required" : false,
          "schema" : {
            "type" : "string"
          }
        }, {
          "description" : "Filter by account alias (case-insensitive partial match)",
          "in" : "query",
          "name" : "alias",
          "required" : false,
          "schema" : {
            "type" : "string"
          }
        }, {
          "description" : "Filter by region ID",
          "in" : "query",
          "name" : "regionId",
          "required" : false,
          "schema" : {
            "type" : "integer",
            "format" : "int32"
          }
        }, {
          "description" : "Filter by account status ID",
          "in" : "query",
          "name" : "accountStatusId",
          "required" : false,
          "schema" : {
            "type" : "integer",
            "format" : "int32"
          }
        }, {
          "description" : "Maximum number of accounts to return",
          "in" : "query",
          "name" : "limit",
          "required" : false,
          "schema" : {
            "type" : "integer",
            "format" : "int32"
          }
        }, {
          "description" : "Number of accounts to skip for pagination",
          "in" : "query",
          "name" : "offset",
          "required" : false,
          "schema" : {
            "type" : "integer",
            "format" : "int32"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "type" : "array",
                  "items" : {
                    "$ref" : "#/components/schemas/AccountDTO"
                  }
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Get all accounts with their copiers, risk limits and features populated in a single call",
        "tags" : [ "Account API" ]
      }
    },
    "/rest/api/v1/accounts/deactivateAllCopiers" : {
      "post" : {
        "operationId" : "deactivateAllCopiers",
        "responses" : {
          "204" : {
            "description" : "No Content"
          }
        },
        "summary" : "Deactivate all copiers across all accounts",
        "tags" : [ "Account API" ]
      }
    },
    "/rest/api/v1/accounts/masters" : {
      "get" : {
        "description" : "Returns every account that currently has at least one slave copying from it, either through a direct account-to-account copier or through a strategy of that account. This is the bulk alternative to calling GET /accounts/{accountId}/slaves per account: each entry contains the master account, its slave accounts (same payload as the per-account endpoint) and the slave count. Only direct slaves are listed, there is no transitive expansion: in a chain A -> B -> C you get one entry for A with slave B and one entry for B with slave C, so an intermediate account appears both as a master and as a slave. Deleted master and slave accounts are excluded, so an empty result means no account is acting as a master.",
        "operationId" : "getMasterAccounts",
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "type" : "array",
                  "items" : {
                    "$ref" : "#/components/schemas/MasterAccountSummaryDTO"
                  }
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Get all master accounts with their slaves in a single call",
        "tags" : [ "Account API" ]
      }
    },
    "/rest/api/v1/accounts/monitorOnlyAllCopiers" : {
      "post" : {
        "operationId" : "monitorOnlyAllCopiers",
        "responses" : {
          "204" : {
            "description" : "No Content"
          }
        },
        "summary" : "Set all copiers across all accounts to monitor-only mode",
        "tags" : [ "Account API" ]
      }
    },
    "/rest/api/v1/accounts/{accountId}" : {
      "delete" : {
        "operationId" : "deleteAccount",
        "parameters" : [ {
          "in" : "path",
          "name" : "accountId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "responses" : {
          "200" : {
            "description" : "OK"
          }
        },
        "summary" : "Delete an account",
        "tags" : [ "Account API" ]
      },
      "get" : {
        "operationId" : "getAccount",
        "parameters" : [ {
          "in" : "path",
          "name" : "accountId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/AccountDTO"
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Get an account",
        "tags" : [ "Account API" ]
      },
      "put" : {
        "operationId" : "updateAccount",
        "parameters" : [ {
          "in" : "path",
          "name" : "accountId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "requestBody" : {
          "content" : {
            "application/json" : {
              "schema" : {
                "$ref" : "#/components/schemas/AccountDTO"
              }
            }
          },
          "required" : true
        },
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/AccountDTO"
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Update an account",
        "tags" : [ "Account API" ]
      }
    },
    "/rest/api/v1/accounts/{accountId}/actions/closeAllPositions" : {
      "post" : {
        "operationId" : "closeAllPositions",
        "parameters" : [ {
          "in" : "path",
          "name" : "accountId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "responses" : {
          "204" : {
            "description" : "No Content"
          }
        },
        "summary" : "Close all account positions",
        "tags" : [ "Trading API" ]
      }
    },
    "/rest/api/v1/accounts/{accountId}/actions/reconnect" : {
      "post" : {
        "description" : "Triggers a fast internal reconnect to the broker without restarting the account. Limited to once every 30 minutes per account.",
        "operationId" : "reconnectAccount",
        "parameters" : [ {
          "in" : "path",
          "name" : "accountId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "responses" : {
          "204" : {
            "description" : "No Content"
          }
        },
        "summary" : "Reconnect an account",
        "tags" : [ "Account API" ]
      }
    },
    "/rest/api/v1/accounts/{accountId}/actions/start" : {
      "post" : {
        "operationId" : "startAccount",
        "parameters" : [ {
          "in" : "path",
          "name" : "accountId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/AccountDTO"
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Start an account (connect)",
        "tags" : [ "Account API" ]
      }
    },
    "/rest/api/v1/accounts/{accountId}/actions/stop" : {
      "post" : {
        "operationId" : "stopAccount",
        "parameters" : [ {
          "in" : "path",
          "name" : "accountId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/AccountDTO"
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Stop an account (disconnect)",
        "tags" : [ "Account API" ]
      }
    },
    "/rest/api/v1/accounts/{accountId}/activateSlavesCopier" : {
      "post" : {
        "operationId" : "activateSlavesCopier",
        "parameters" : [ {
          "in" : "path",
          "name" : "accountId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "responses" : {
          "204" : {
            "description" : "No Content"
          }
        },
        "summary" : "Activate all copiers of all slave accounts",
        "tags" : [ "Account API" ]
      }
    },
    "/rest/api/v1/accounts/{accountId}/apiKeys" : {
      "get" : {
        "operationId" : "getAccountApiKeys",
        "parameters" : [ {
          "in" : "path",
          "name" : "accountId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "type" : "array",
                  "items" : {
                    "$ref" : "#/components/schemas/ApiKeyDTO"
                  }
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Get all API keys for an account",
        "tags" : [ "Account API" ]
      }
    },
    "/rest/api/v1/accounts/{accountId}/appliedTemplate" : {
      "put" : {
        "description" : "Sets or clears the three apply-marker columns on the account (accountTemplate1, appliedTemplateRevision, appliedTemplateMeta). Pass an empty body / null templateId to clear the link.",
        "operationId" : "setAppliedTemplate",
        "parameters" : [ {
          "in" : "path",
          "name" : "accountId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "requestBody" : {
          "content" : {
            "application/json" : {
              "schema" : {
                "$ref" : "#/components/schemas/AppliedTemplateDTO"
              }
            }
          },
          "required" : true
        },
        "responses" : {
          "204" : {
            "description" : "No Content"
          }
        },
        "summary" : "Set or clear the applied-template marker for an account",
        "tags" : [ "Account API" ]
      }
    },
    "/rest/api/v1/accounts/{accountId}/approvals" : {
      "post" : {
        "operationId" : "createAccountApproval",
        "parameters" : [ {
          "in" : "path",
          "name" : "accountId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "requestBody" : {
          "content" : {
            "application/json" : {
              "schema" : {
                "$ref" : "#/components/schemas/ApprovalDTO"
              }
            }
          },
          "required" : true
        },
        "responses" : {
          "204" : {
            "description" : "No Content"
          }
        },
        "summary" : "Create an approval",
        "tags" : [ "Account API" ]
      }
    },
    "/rest/api/v1/accounts/{accountId}/auditLogs" : {
      "get" : {
        "description" : "Retrieves audit logs for all API modifications made to a specific account.",
        "operationId" : "getAccountAuditLogs",
        "parameters" : [ {
          "in" : "path",
          "name" : "accountId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "description" : "Maximum number of logs to return",
          "in" : "query",
          "name" : "limit",
          "required" : false,
          "schema" : {
            "type" : "integer",
            "format" : "int32"
          }
        }, {
          "description" : "Number of logs to skip for pagination",
          "in" : "query",
          "name" : "offset",
          "required" : false,
          "schema" : {
            "type" : "integer",
            "format" : "int32"
          }
        }, {
          "description" : "Start date filter (ISO-8601 format)",
          "in" : "query",
          "name" : "startDate",
          "required" : false,
          "schema" : {
            "type" : "string"
          }
        }, {
          "description" : "End date filter (ISO-8601 format)",
          "in" : "query",
          "name" : "endDate",
          "required" : false,
          "schema" : {
            "type" : "string"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "type" : "array",
                  "items" : {
                    "$ref" : "#/components/schemas/AuditLogDTO"
                  }
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Get audit logs for a specific account",
        "tags" : [ "Account API" ]
      }
    },
    "/rest/api/v1/accounts/{accountId}/copiers" : {
      "get" : {
        "operationId" : "getCopiers",
        "parameters" : [ {
          "in" : "path",
          "name" : "accountId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "type" : "array",
                  "items" : {
                    "$ref" : "#/components/schemas/CopierDTO"
                  }
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Get account copiers",
        "tags" : [ "Account API" ]
      },
      "post" : {
        "operationId" : "createCopier",
        "parameters" : [ {
          "in" : "path",
          "name" : "accountId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "requestBody" : {
          "content" : {
            "application/json" : {
              "schema" : {
                "$ref" : "#/components/schemas/CopierDTO"
              }
            }
          },
          "required" : true
        },
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/CopierDTO"
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Create an account copier",
        "tags" : [ "Account API" ]
      }
    },
    "/rest/api/v1/accounts/{accountId}/copiers/{copierId}" : {
      "delete" : {
        "operationId" : "deleteCopier",
        "parameters" : [ {
          "in" : "path",
          "name" : "accountId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "path",
          "name" : "copierId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "responses" : {
          "200" : {
            "description" : "OK"
          }
        },
        "summary" : "Delete an account copier",
        "tags" : [ "Account API" ]
      },
      "get" : {
        "operationId" : "getCopier",
        "parameters" : [ {
          "in" : "path",
          "name" : "accountId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "path",
          "name" : "copierId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/CopierDTO"
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Get account copier",
        "tags" : [ "Account API" ]
      },
      "put" : {
        "operationId" : "updateCopier",
        "parameters" : [ {
          "in" : "path",
          "name" : "accountId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "path",
          "name" : "copierId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "requestBody" : {
          "content" : {
            "application/json" : {
              "schema" : {
                "$ref" : "#/components/schemas/CopierDTO"
              }
            }
          },
          "required" : true
        },
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/CopierDTO"
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Update an account copier",
        "tags" : [ "Account API" ]
      }
    },
    "/rest/api/v1/accounts/{accountId}/copiers/{copierId}/features" : {
      "get" : {
        "operationId" : "getCopierFeatures",
        "parameters" : [ {
          "in" : "path",
          "name" : "accountId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "path",
          "name" : "copierId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "type" : "array",
                  "items" : {
                    "$ref" : "#/components/schemas/FeatureDTO"
                  }
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Get all copier features",
        "tags" : [ "Account API" ]
      },
      "post" : {
        "operationId" : "createCopierFeature",
        "parameters" : [ {
          "in" : "path",
          "name" : "accountId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "path",
          "name" : "copierId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "requestBody" : {
          "content" : {
            "application/json" : {
              "schema" : {
                "$ref" : "#/components/schemas/FeatureDTO"
              }
            }
          },
          "required" : true
        },
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/FeatureDTO"
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Create a copier feature",
        "tags" : [ "Account API" ]
      }
    },
    "/rest/api/v1/accounts/{accountId}/copiers/{copierId}/features/{featureId}" : {
      "delete" : {
        "operationId" : "deleteCopierFeature",
        "parameters" : [ {
          "in" : "path",
          "name" : "accountId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "path",
          "name" : "copierId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "path",
          "name" : "featureId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "responses" : {
          "200" : {
            "description" : "OK"
          }
        },
        "summary" : "Delete a copier feature",
        "tags" : [ "Account API" ]
      },
      "get" : {
        "operationId" : "getCopierFeature",
        "parameters" : [ {
          "in" : "path",
          "name" : "accountId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "path",
          "name" : "copierId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "path",
          "name" : "featureId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/FeatureDTO"
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Get a copier feature",
        "tags" : [ "Account API" ]
      },
      "put" : {
        "operationId" : "updateCopierFeature",
        "parameters" : [ {
          "in" : "path",
          "name" : "accountId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "path",
          "name" : "copierId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "path",
          "name" : "featureId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "requestBody" : {
          "content" : {
            "application/json" : {
              "schema" : {
                "$ref" : "#/components/schemas/FeatureDTO"
              }
            }
          },
          "required" : true
        },
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/FeatureDTO"
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Update a copier feature",
        "tags" : [ "Account API" ]
      }
    },
    "/rest/api/v1/accounts/{accountId}/copiers/{copierId}/resync" : {
      "post" : {
        "description" : "Resynchronize with the master account. If a position was closed on the slave account but remains open on the master, this operation will reopen the position on the slave to match the master's state.",
        "operationId" : "resyncCopier",
        "parameters" : [ {
          "in" : "path",
          "name" : "accountId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "path",
          "name" : "copierId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "responses" : {
          "204" : {
            "description" : "No Content"
          }
        },
        "summary" : "Resynchronize copier with master",
        "tags" : [ "Account API" ]
      }
    },
    "/rest/api/v1/accounts/{accountId}/copiers/{copierId}/symbolMappings/current" : {
      "get" : {
        "operationId" : "getAccountCopierCurrentSymbolMappings",
        "parameters" : [ {
          "in" : "path",
          "name" : "accountId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "path",
          "name" : "copierId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "type" : "array",
                  "items" : {
                    "$ref" : "#/components/schemas/SymbolMappingDTO"
                  }
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Get account copier current symbol mappings",
        "tags" : [ "Account API" ]
      }
    },
    "/rest/api/v1/accounts/{accountId}/dataCollector" : {
      "get" : {
        "description" : "Retrieves equity, balance, and floating PnL time-series data collected for advanced analytics, drawdown monitoring, and equity curve construction.",
        "operationId" : "getAccountDataCollectorRecords",
        "parameters" : [ {
          "in" : "path",
          "name" : "accountId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "description" : "Maximum number of records to return (default: 10000, use -1 for all records)",
          "in" : "query",
          "name" : "limit",
          "required" : false,
          "schema" : {
            "type" : "integer",
            "format" : "int32"
          }
        }, {
          "description" : "Start date filter (ISO-8601 format)",
          "example" : "2023-01-01T00:00:00Z",
          "in" : "query",
          "name" : "startTime",
          "required" : false,
          "schema" : {
            "type" : "string"
          }
        }, {
          "description" : "End date filter (ISO-8601 format)",
          "example" : "2023-12-31T23:59:59Z",
          "in" : "query",
          "name" : "endTime",
          "required" : false,
          "schema" : {
            "type" : "string"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "type" : "array",
                  "items" : {
                    "$ref" : "#/components/schemas/DataCollectorRecordDTO"
                  }
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Get data collector records for a specific account",
        "tags" : [ "Account API" ]
      }
    },
    "/rest/api/v1/accounts/{accountId}/deactivateSlavesCopier" : {
      "post" : {
        "operationId" : "deactivateSlavesCopier",
        "parameters" : [ {
          "in" : "path",
          "name" : "accountId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "responses" : {
          "204" : {
            "description" : "No Content"
          }
        },
        "summary" : "Deactivate all copiers of all slave accounts",
        "tags" : [ "Account API" ]
      }
    },
    "/rest/api/v1/accounts/{accountId}/features" : {
      "get" : {
        "operationId" : "getAccountFeatures",
        "parameters" : [ {
          "in" : "path",
          "name" : "accountId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "type" : "array",
                  "items" : {
                    "$ref" : "#/components/schemas/FeatureDTO"
                  }
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Get all account features",
        "tags" : [ "Account API" ]
      },
      "post" : {
        "operationId" : "createAccountFeature",
        "parameters" : [ {
          "in" : "path",
          "name" : "accountId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "requestBody" : {
          "content" : {
            "application/json" : {
              "schema" : {
                "$ref" : "#/components/schemas/FeatureDTO"
              }
            }
          },
          "required" : true
        },
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/FeatureDTO"
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Create an account feature",
        "tags" : [ "Account API" ]
      }
    },
    "/rest/api/v1/accounts/{accountId}/features/{featureId}" : {
      "delete" : {
        "operationId" : "deleteAccountFeature",
        "parameters" : [ {
          "in" : "path",
          "name" : "accountId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "path",
          "name" : "featureId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "responses" : {
          "200" : {
            "description" : "OK"
          }
        },
        "summary" : "Delete an account feature",
        "tags" : [ "Account API" ]
      },
      "get" : {
        "operationId" : "getAccountFeature",
        "parameters" : [ {
          "in" : "path",
          "name" : "accountId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "path",
          "name" : "featureId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/FeatureDTO"
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Get an account feature",
        "tags" : [ "Account API" ]
      },
      "put" : {
        "operationId" : "updateAccountFeature",
        "parameters" : [ {
          "in" : "path",
          "name" : "accountId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "path",
          "name" : "featureId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "requestBody" : {
          "content" : {
            "application/json" : {
              "schema" : {
                "$ref" : "#/components/schemas/FeatureDTO"
              }
            }
          },
          "required" : true
        },
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/FeatureDTO"
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Update an account feature",
        "tags" : [ "Account API" ]
      }
    },
    "/rest/api/v1/accounts/{accountId}/history/positions" : {
      "get" : {
        "description" : "The history is not updated in real-time. There may be a delay of up to 3 minutes",
        "operationId" : "getHistoryPositions",
        "parameters" : [ {
          "in" : "path",
          "name" : "accountId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "description" : "ISO 8601",
          "example" : "2023-07-28T14:32:07+07:00",
          "in" : "query",
          "name" : "start",
          "required" : true,
          "schema" : {
            "type" : "string"
          }
        }, {
          "description" : "ISO 8601",
          "example" : "2023-12-25T16:05:06+07:00",
          "in" : "query",
          "name" : "stop",
          "required" : true,
          "schema" : {
            "type" : "string"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "type" : "array",
                  "items" : {
                    "$ref" : "#/components/schemas/PositionDTO"
                  }
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Get account history positions",
        "tags" : [ "Trading API" ]
      }
    },
    "/rest/api/v1/accounts/{accountId}/information" : {
      "get" : {
        "operationId" : "getInformation",
        "parameters" : [ {
          "in" : "path",
          "name" : "accountId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/AccountInformationDTO"
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Get account information",
        "tags" : [ "Trading API" ]
      }
    },
    "/rest/api/v1/accounts/{accountId}/logs" : {
      "get" : {
        "operationId" : "getAccountLogs",
        "parameters" : [ {
          "in" : "path",
          "name" : "accountId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "description" : "Get the last logs: e.g. 100 means the last 100 logs",
          "example" : 100,
          "in" : "query",
          "name" : "limit",
          "required" : false,
          "schema" : {
            "type" : "integer",
            "format" : "int32"
          }
        }, {
          "description" : "You can set an offset. Offset 100 means 101-200",
          "example" : 0,
          "in" : "query",
          "name" : "offset",
          "required" : false,
          "schema" : {
            "type" : "integer",
            "format" : "int32"
          }
        }, {
          "description" : "ISO 8601",
          "example" : "2023-07-28T14:32:07+07:00",
          "in" : "query",
          "name" : "start",
          "required" : false,
          "schema" : {
            "type" : "string"
          }
        }, {
          "description" : "ISO 8601",
          "example" : "2023-12-25T16:05:06+07:00",
          "in" : "query",
          "name" : "stop",
          "required" : false,
          "schema" : {
            "type" : "string"
          }
        }, {
          "description" : "Filter logs by log level type ID. If you choose 3 = Info, then all logs with a lower level are returned. The levels are: 1 = Error, 2 = Warning, 3 = Info.",
          "example" : 1,
          "in" : "query",
          "name" : "logTypeId",
          "required" : false,
          "schema" : {
            "type" : "integer",
            "format" : "int32"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "type" : "array",
                  "items" : {
                    "$ref" : "#/components/schemas/LogDTO"
                  }
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Get account logs",
        "tags" : [ "Account API" ]
      }
    },
    "/rest/api/v1/accounts/{accountId}/masaniello/{masanielloFeatureId}/reset" : {
      "put" : {
        "description" : "Resets the Masaniello money management series. If symbol is provided, only that symbol's series is reset. Otherwise, all symbol series are reset.",
        "operationId" : "resetMasaniello",
        "parameters" : [ {
          "in" : "path",
          "name" : "accountId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "path",
          "name" : "masanielloFeatureId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "description" : "Optional symbol to reset. If not provided, all symbols are reset.",
          "example" : "BTCUSD",
          "in" : "query",
          "name" : "symbol",
          "required" : false,
          "schema" : {
            "type" : "string"
          }
        } ],
        "responses" : {
          "200" : {
            "description" : "OK"
          }
        },
        "summary" : "Reset Masaniello series",
        "tags" : [ "Account API" ]
      }
    },
    "/rest/api/v1/accounts/{accountId}/monitorOnlySlavesCopier" : {
      "post" : {
        "operationId" : "monitorOnlySlavesCopier",
        "parameters" : [ {
          "in" : "path",
          "name" : "accountId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "responses" : {
          "204" : {
            "description" : "No Content"
          }
        },
        "summary" : "Set all copiers of all slave accounts to monitor-only mode",
        "tags" : [ "Account API" ]
      }
    },
    "/rest/api/v1/accounts/{accountId}/orders" : {
      "post" : {
        "description" : "Places an order and returns immediately. The endpoint does not wait for the trade to be executed and therefore does not confirm whether the execution was successful or not. To open positions, use the /positions endpoint.",
        "operationId" : "sendOrder",
        "parameters" : [ {
          "in" : "path",
          "name" : "accountId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "requestBody" : {
          "content" : {
            "application/json" : {
              "schema" : {
                "$ref" : "#/components/schemas/PositionRequestDTO"
              }
            }
          },
          "required" : true
        },
        "responses" : {
          "204" : {
            "description" : "No Content"
          }
        },
        "summary" : "Send an account order",
        "tags" : [ "Trading API" ]
      }
    },
    "/rest/api/v1/accounts/{accountId}/performanceMetrics" : {
      "get" : {
        "operationId" : "getAccountPerformanceMetrics",
        "parameters" : [ {
          "in" : "path",
          "name" : "accountId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "description" : "Start date filter (ISO-8601 format, e.g. 2024-01-01T00:00:00Z)",
          "in" : "query",
          "name" : "startDate",
          "required" : false,
          "schema" : {
            "type" : "string"
          }
        }, {
          "description" : "End date filter (ISO-8601 format, e.g. 2024-12-31T23:59:59Z)",
          "in" : "query",
          "name" : "endDate",
          "required" : false,
          "schema" : {
            "type" : "string"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/PerformanceMetricsDTO"
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Get an account performance metrics",
        "tags" : [ "Account API" ]
      }
    },
    "/rest/api/v1/accounts/{accountId}/positions" : {
      "get" : {
        "operationId" : "getPositions",
        "parameters" : [ {
          "in" : "path",
          "name" : "accountId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "type" : "array",
                  "items" : {
                    "$ref" : "#/components/schemas/PositionDTO"
                  }
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Get account positions",
        "tags" : [ "Trading API" ]
      },
      "post" : {
        "operationId" : "openPosition",
        "parameters" : [ {
          "in" : "path",
          "name" : "accountId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "requestBody" : {
          "content" : {
            "application/json" : {
              "schema" : {
                "$ref" : "#/components/schemas/PositionRequestDTO"
              }
            }
          },
          "required" : true
        },
        "responses" : {
          "204" : {
            "description" : "No Content"
          }
        },
        "summary" : "Open an account position",
        "tags" : [ "Trading API" ]
      }
    },
    "/rest/api/v1/accounts/{accountId}/positions/{positionId}" : {
      "delete" : {
        "description" : "By default closes the position (works for both live positions and pending orders). Set `pendingOnly=true` to cancel the order ONLY if it is still a pending (unfilled) order; if it has already filled into a live position it is left untouched (safe no-op). Use this to safely cancel pending orders on expiry without risking closing a filled position.",
        "operationId" : "closePosition",
        "parameters" : [ {
          "in" : "path",
          "name" : "accountId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "path",
          "name" : "positionId",
          "required" : true,
          "schema" : {
            "type" : "string"
          }
        }, {
          "description" : "If true, only cancel when the id is still a pending (unfilled) order; a live (filled) position is not closed (no-op).",
          "in" : "query",
          "name" : "pendingOnly",
          "required" : false,
          "schema" : {
            "type" : "boolean",
            "default" : false
          }
        } ],
        "responses" : {
          "204" : {
            "description" : "No Content"
          }
        },
        "summary" : "Close an account position or cancel a pending order",
        "tags" : [ "Trading API" ]
      },
      "put" : {
        "description" : "For partial close you can use this endpoint. Only volume, open price, take profit, and stop loss can be modified.",
        "operationId" : "modifyPosition",
        "parameters" : [ {
          "in" : "path",
          "name" : "accountId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "path",
          "name" : "positionId",
          "required" : true,
          "schema" : {
            "type" : "string"
          }
        } ],
        "requestBody" : {
          "content" : {
            "application/json" : {
              "schema" : {
                "$ref" : "#/components/schemas/PositionRequestDTO"
              }
            }
          },
          "required" : true
        },
        "responses" : {
          "204" : {
            "description" : "No Content"
          }
        },
        "summary" : "Modify an account position",
        "tags" : [ "Trading API" ]
      }
    },
    "/rest/api/v1/accounts/{accountId}/profitTargets/{profitTargetFeatureId}/reset" : {
      "put" : {
        "description" : "If the profit target (e.g., daily) is hit, no trades will be copied for the remainder of the day. To resume trading on the same day, you can utilize this operation to unlock the profit target",
        "operationId" : "resetProfitTarget",
        "parameters" : [ {
          "in" : "path",
          "name" : "accountId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "path",
          "name" : "profitTargetFeatureId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "responses" : {
          "200" : {
            "description" : "OK"
          }
        },
        "summary" : "Reset an account profit target",
        "tags" : [ "Account API" ]
      }
    },
    "/rest/api/v1/accounts/{accountId}/quote/{symbol}" : {
      "get" : {
        "description" : "Fetches the current bid price, ask price, and timestamp for a specific trading symbol. Note: Not all platforms support real-time quote fetching. If there is no response or an error is returned, it means the platform does not support this feature.\n\nSet `includeSymbolInfo=true` to also receive the symbol details (points, digits, volume limits) in the same response, which avoids a second call to `/accounts/{accountId}/symbols/{symbol}`.",
        "operationId" : "getQuote",
        "parameters" : [ {
          "in" : "path",
          "name" : "accountId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "description" : "Symbol name (e.g., EURUSD, GBPJPY)",
          "example" : "EURUSD",
          "in" : "path",
          "name" : "symbol",
          "required" : true,
          "schema" : {
            "type" : "string"
          }
        }, {
          "description" : "If true, the response additionally contains the symbol details (points, digits, volume limits) in the 'symbolInfo' field.",
          "in" : "query",
          "name" : "includeSymbolInfo",
          "required" : false,
          "schema" : {
            "type" : "boolean",
            "default" : false
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/MarketQuoteDTO"
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Get market quote for a symbol",
        "tags" : [ "Trading API" ]
      }
    },
    "/rest/api/v1/accounts/{accountId}/riskLimits" : {
      "get" : {
        "operationId" : "getRiskLimits",
        "parameters" : [ {
          "in" : "path",
          "name" : "accountId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "type" : "array",
                  "items" : {
                    "$ref" : "#/components/schemas/RiskLimitDTO"
                  }
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Get account risk limits",
        "tags" : [ "Account API" ]
      },
      "post" : {
        "operationId" : "createRiskLimit",
        "parameters" : [ {
          "in" : "path",
          "name" : "accountId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "requestBody" : {
          "content" : {
            "application/json" : {
              "schema" : {
                "$ref" : "#/components/schemas/RiskLimitDTO"
              }
            }
          },
          "required" : true
        },
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/RiskLimitDTO"
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Create an account risk limit",
        "tags" : [ "Account API" ]
      }
    },
    "/rest/api/v1/accounts/{accountId}/riskLimits/{riskLimitId}" : {
      "delete" : {
        "operationId" : "deleteRiskLimit",
        "parameters" : [ {
          "in" : "path",
          "name" : "accountId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "path",
          "name" : "riskLimitId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "responses" : {
          "200" : {
            "description" : "OK"
          }
        },
        "summary" : "Delete an account risk limit",
        "tags" : [ "Account API" ]
      },
      "get" : {
        "operationId" : "getRiskLimit",
        "parameters" : [ {
          "in" : "path",
          "name" : "accountId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "path",
          "name" : "riskLimitId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/RiskLimitDTO"
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Get an account risk limit",
        "tags" : [ "Account API" ]
      },
      "put" : {
        "operationId" : "updateRiskLimit",
        "parameters" : [ {
          "in" : "path",
          "name" : "accountId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "path",
          "name" : "riskLimitId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "requestBody" : {
          "content" : {
            "application/json" : {
              "schema" : {
                "$ref" : "#/components/schemas/RiskLimitDTO"
              }
            }
          },
          "required" : true
        },
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/RiskLimitDTO"
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Update an account risk limit",
        "tags" : [ "Account API" ]
      }
    },
    "/rest/api/v1/accounts/{accountId}/riskLimits/{riskLimitId}/reset" : {
      "put" : {
        "description" : "If the risk limit (e.g., daily) is hit, no trades will be copied for the remainder of the day. To resume trading on the same day, you can utilize this operation to unlock the risk limit",
        "operationId" : "resetRiskLimit",
        "parameters" : [ {
          "in" : "path",
          "name" : "accountId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "path",
          "name" : "riskLimitId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "responses" : {
          "200" : {
            "description" : "OK"
          }
        },
        "summary" : "Reset an account risk limit",
        "tags" : [ "Account API" ]
      }
    },
    "/rest/api/v1/accounts/{accountId}/signalFollowers/{signalFollowerId}/features" : {
      "get" : {
        "description" : "Get all copier features attached to a Signal Follower feature",
        "operationId" : "getSignalFollowerFeatures",
        "parameters" : [ {
          "in" : "path",
          "name" : "accountId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "path",
          "name" : "signalFollowerId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "type" : "array",
                  "items" : {
                    "$ref" : "#/components/schemas/FeatureDTO"
                  }
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Get all Signal Follower features",
        "tags" : [ "Account API" ]
      },
      "post" : {
        "description" : "Create a copier feature attached to a Signal Follower feature",
        "operationId" : "createSignalFollowerFeature",
        "parameters" : [ {
          "in" : "path",
          "name" : "accountId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "path",
          "name" : "signalFollowerId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "requestBody" : {
          "content" : {
            "application/json" : {
              "schema" : {
                "$ref" : "#/components/schemas/FeatureDTO"
              }
            }
          },
          "required" : true
        },
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/FeatureDTO"
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Create a Signal Follower feature",
        "tags" : [ "Account API" ]
      }
    },
    "/rest/api/v1/accounts/{accountId}/signalFollowers/{signalFollowerId}/features/{featureId}" : {
      "delete" : {
        "description" : "Delete a copier feature attached to a Signal Follower feature",
        "operationId" : "deleteSignalFollowerFeature",
        "parameters" : [ {
          "in" : "path",
          "name" : "accountId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "path",
          "name" : "signalFollowerId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "path",
          "name" : "featureId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "responses" : {
          "200" : {
            "description" : "OK"
          }
        },
        "summary" : "Delete a Signal Follower feature",
        "tags" : [ "Account API" ]
      },
      "get" : {
        "description" : "Get a copier feature attached to a Signal Follower feature",
        "operationId" : "getSignalFollowerFeature",
        "parameters" : [ {
          "in" : "path",
          "name" : "accountId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "path",
          "name" : "signalFollowerId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "path",
          "name" : "featureId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/FeatureDTO"
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Get a Signal Follower feature",
        "tags" : [ "Account API" ]
      },
      "put" : {
        "description" : "Update a copier feature attached to a Signal Follower feature",
        "operationId" : "updateSignalFollowerFeature",
        "parameters" : [ {
          "in" : "path",
          "name" : "accountId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "path",
          "name" : "signalFollowerId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "path",
          "name" : "featureId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "requestBody" : {
          "content" : {
            "application/json" : {
              "schema" : {
                "$ref" : "#/components/schemas/FeatureDTO"
              }
            }
          },
          "required" : true
        },
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/FeatureDTO"
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Update a Signal Follower feature",
        "tags" : [ "Account API" ]
      }
    },
    "/rest/api/v1/accounts/{accountId}/slaves" : {
      "get" : {
        "operationId" : "getSlaveAccounts",
        "parameters" : [ {
          "in" : "path",
          "name" : "accountId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "type" : "array",
                  "items" : {
                    "$ref" : "#/components/schemas/AccountDTO"
                  }
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Get all slave accounts that are copying from this master account",
        "tags" : [ "Account API" ]
      }
    },
    "/rest/api/v1/accounts/{accountId}/symbolMappings" : {
      "post" : {
        "operationId" : "getAccountSymbolMappings",
        "parameters" : [ {
          "in" : "path",
          "name" : "accountId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "requestBody" : {
          "content" : {
            "application/json" : {
              "schema" : {
                "$ref" : "#/components/schemas/RequestSymbolMappingsDTO"
              }
            }
          },
          "required" : true
        },
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "type" : "array",
                  "items" : {
                    "$ref" : "#/components/schemas/SymbolMappingDTO"
                  }
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Get account symbol mappings for given symbols",
        "tags" : [ "Account API" ]
      }
    },
    "/rest/api/v1/accounts/{accountId}/symbols" : {
      "get" : {
        "operationId" : "getSymbols",
        "parameters" : [ {
          "in" : "path",
          "name" : "accountId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "type" : "array",
                  "items" : {
                    "$ref" : "#/components/schemas/SymbolDTO"
                  }
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Get account symbols",
        "tags" : [ "Trading API" ]
      }
    },
    "/rest/api/v1/accounts/{accountId}/symbols/{symbol}" : {
      "get" : {
        "operationId" : "getSymbol",
        "parameters" : [ {
          "in" : "path",
          "name" : "accountId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "description" : "Symbol name (e.g., EURUSD, GBPJPY)",
          "example" : "EURUSD",
          "in" : "path",
          "name" : "symbol",
          "required" : true,
          "schema" : {
            "type" : "string"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/SymbolDTO"
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Get a specific account symbol",
        "tags" : [ "Trading API" ]
      }
    },
    "/rest/api/v1/apiKeys/current" : {
      "get" : {
        "description" : "Returns the key that authenticated this call, including its permission type and access policy, so a caller can tell what it may do before attempting it. The key value itself is never returned. Requires an API key; a session-authenticated call has no key to describe.",
        "operationId" : "getCurrentApiKey",
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/ApiKeyDTO"
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Describe the API key used for this request",
        "tags" : [ "Key Management API" ]
      }
    },
    "/rest/api/v1/brokers/{brokerType}/all" : {
      "get" : {
        "description" : "Returns a list of all available broker names for the specified broker type (mt4 or mt5).",
        "operationId" : "getAllBrokers",
        "parameters" : [ {
          "description" : "The broker type. Allowed values: mt4, mt5",
          "in" : "path",
          "name" : "brokerType",
          "required" : true,
          "schema" : {
            "type" : "string"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "type" : "array",
                  "items" : {
                    "type" : "string"
                  }
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Get all brokers",
        "tags" : [ "Broker API" ]
      }
    },
    "/rest/api/v1/investorProgram/traders" : {
      "get" : {
        "description" : "Returns a list of all traders with ACTIVE status",
        "operationId" : "getAllTraders",
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "type" : "array",
                  "items" : {
                    "$ref" : "#/components/schemas/FeatureDTO"
                  }
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Get all approved traders in the investor program",
        "tags" : [ "Investor Program API" ]
      }
    },
    "/rest/api/v1/investorProgram/traders/{traderId}" : {
      "get" : {
        "description" : "Returns detailed information about a specific approved trader",
        "operationId" : "getTrader",
        "parameters" : [ {
          "in" : "path",
          "name" : "traderId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/FeatureDTO"
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Get a specific approved trader by ID",
        "tags" : [ "Investor Program API" ]
      }
    },
    "/rest/api/v1/investorProgram/traders/{traderId}/history/positions" : {
      "get" : {
        "description" : "Returns historical trading positions for an approved trader so investors can see their trading history. The history is not updated in real-time. There may be a delay of up to 3 minutes.",
        "operationId" : "getTraderHistoryPositions",
        "parameters" : [ {
          "in" : "path",
          "name" : "traderId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "description" : "ISO 8601",
          "example" : "2023-07-28T14:32:07+07:00",
          "in" : "query",
          "name" : "start",
          "required" : true,
          "schema" : {
            "type" : "string"
          }
        }, {
          "description" : "ISO 8601",
          "example" : "2023-12-25T16:05:06+07:00",
          "in" : "query",
          "name" : "stop",
          "required" : true,
          "schema" : {
            "type" : "string"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "type" : "array",
                  "items" : {
                    "$ref" : "#/components/schemas/PositionDTO"
                  }
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Get trader historical positions",
        "tags" : [ "Investor Program API" ]
      }
    },
    "/rest/api/v1/investorProgram/traders/{traderId}/performanceMetrics" : {
      "get" : {
        "description" : "Returns performance analytics for an approved trader's account",
        "operationId" : "getTraderPerformanceMetrics",
        "parameters" : [ {
          "in" : "path",
          "name" : "traderId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/PerformanceMetricsDTO"
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Get trader performance metrics",
        "tags" : [ "Investor Program API" ]
      }
    },
    "/rest/api/v1/marketplace" : {
      "get" : {
        "operationId" : "getMarketplace",
        "parameters" : [ {
          "in" : "header",
          "name" : "X-User-Email",
          "required" : false,
          "schema" : {
            "type" : "string"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/MarketplaceDTO"
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Get marketplace data",
        "tags" : [ "Marketplace API" ]
      }
    },
    "/rest/api/v1/projects/{projectId}" : {
      "get" : {
        "operationId" : "getProject",
        "parameters" : [ {
          "in" : "path",
          "name" : "projectId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/ProjectDTO"
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Get a project",
        "tags" : [ "Project API" ]
      },
      "put" : {
        "operationId" : "updateProject",
        "parameters" : [ {
          "in" : "path",
          "name" : "projectId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "requestBody" : {
          "content" : {
            "application/json" : {
              "schema" : {
                "$ref" : "#/components/schemas/ProjectDTO"
              }
            }
          },
          "required" : true
        },
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/ProjectDTO"
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Update a project",
        "tags" : [ "Project API" ]
      }
    },
    "/rest/api/v1/projects/{projectId}/apiKeys/availableEndpoints" : {
      "get" : {
        "description" : "Returns a list of all REST endpoints with their HTTP methods that can be controlled via API key access policy. Endpoints annotated with @Hidden are excluded.",
        "operationId" : "getAvailableEndpoints",
        "parameters" : [ {
          "in" : "path",
          "name" : "projectId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "type" : "array",
                  "items" : {
                    "$ref" : "#/components/schemas/RestEndpointMetadataDTO"
                  }
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Get available REST endpoints",
        "tags" : [ "Key Management API" ]
      }
    },
    "/rest/api/v1/projects/{projectId}/apiKeys/availableFields" : {
      "get" : {
        "description" : "Returns a list of all visible fields in AccountDTO, AccountInformationDTO and CopierDTO that can be controlled via API key access policy. Fields annotated with @Hidden or @Schema(hidden=true) are excluded.",
        "operationId" : "getAvailableFields",
        "parameters" : [ {
          "in" : "path",
          "name" : "projectId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "type" : "array",
                  "items" : {
                    "$ref" : "#/components/schemas/FieldMetadataDTO"
                  }
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Get available DTO fields for access policy",
        "tags" : [ "Key Management API" ]
      }
    },
    "/rest/api/v1/projects/{projectId}/apiKeys/availableFrontendFeatures" : {
      "get" : {
        "description" : "Returns a list of all frontend features that can be hidden via API key access policy.",
        "operationId" : "getAvailableFrontendFeatures",
        "parameters" : [ {
          "in" : "path",
          "name" : "projectId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "type" : "array",
                  "items" : {
                    "$ref" : "#/components/schemas/FrontendFeatureDTO"
                  }
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Get available frontend features",
        "tags" : [ "Key Management API" ]
      }
    },
    "/rest/api/v1/projects/{projectId}/auditLogs" : {
      "get" : {
        "description" : "Retrieves audit logs for all API modifications made to the project. Only includes POST, PUT, and DELETE operations.",
        "operationId" : "getProjectAuditLogs",
        "parameters" : [ {
          "in" : "path",
          "name" : "projectId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "description" : "Maximum number of logs to return",
          "in" : "query",
          "name" : "limit",
          "required" : false,
          "schema" : {
            "type" : "integer",
            "format" : "int32"
          }
        }, {
          "description" : "Number of logs to skip for pagination",
          "in" : "query",
          "name" : "offset",
          "required" : false,
          "schema" : {
            "type" : "integer",
            "format" : "int32"
          }
        }, {
          "description" : "Start date filter (ISO-8601 format)",
          "in" : "query",
          "name" : "startDate",
          "required" : false,
          "schema" : {
            "type" : "string"
          }
        }, {
          "description" : "End date filter (ISO-8601 format)",
          "in" : "query",
          "name" : "endDate",
          "required" : false,
          "schema" : {
            "type" : "string"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "type" : "array",
                  "items" : {
                    "$ref" : "#/components/schemas/AuditLogDTO"
                  }
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Get audit logs for a project",
        "tags" : [ "Project API" ]
      }
    },
    "/rest/api/v1/projects/{projectId}/bankHolidays" : {
      "get" : {
        "description" : "Imported weekly from Nager.Date. The trading filter itself runs off the calendar's own holiday rows, this is the official second source that makes a missing holiday visible. Defaults to the next 30 days.",
        "operationId" : "getBankHolidays",
        "parameters" : [ {
          "in" : "path",
          "name" : "projectId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "description" : "Start of the range (ISO-8601 date)",
          "example" : "2026-01-15",
          "in" : "query",
          "name" : "from",
          "required" : false,
          "schema" : {
            "type" : "string"
          }
        }, {
          "description" : "End of the range (ISO-8601 date)",
          "example" : "2026-02-15",
          "in" : "query",
          "name" : "to",
          "required" : false,
          "schema" : {
            "type" : "string"
          }
        }, {
          "description" : "Comma separated ISO-2 country codes",
          "example" : "US,DE",
          "in" : "query",
          "name" : "countries",
          "required" : false,
          "schema" : {
            "type" : "string"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "type" : "array",
                  "items" : {
                    "$ref" : "#/components/schemas/BankHolidayDTO"
                  }
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Official bank holidays",
        "tags" : [ "News API" ]
      }
    },
    "/rest/api/v1/projects/{projectId}/calendarAlertRules" : {
      "get" : {
        "operationId" : "getCalendarAlertRules",
        "parameters" : [ {
          "in" : "path",
          "name" : "projectId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "type" : "array",
                  "items" : {
                    "$ref" : "#/components/schemas/CalendarAlertRuleDTO"
                  }
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "List the standing calendar alert rules of the project",
        "tags" : [ "News API" ]
      },
      "post" : {
        "description" : "A rule such as \"notify me 30 minutes before every HIGH impact USD event\". The 30 minute calendar sync turns it into ordinary alerts, so a change takes effect on the next sync and any alert the previous version had already materialised is dropped.",
        "operationId" : "saveCalendarAlertRule",
        "parameters" : [ {
          "in" : "path",
          "name" : "projectId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "requestBody" : {
          "content" : {
            "application/json" : {
              "schema" : {
                "$ref" : "#/components/schemas/CalendarAlertRuleDTO"
              }
            }
          },
          "required" : true
        },
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/CalendarAlertRuleDTO"
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Create or update a standing calendar alert rule",
        "tags" : [ "News API" ]
      }
    },
    "/rest/api/v1/projects/{projectId}/calendarAlertRules/{ruleId}" : {
      "delete" : {
        "operationId" : "deleteCalendarAlertRule",
        "parameters" : [ {
          "in" : "path",
          "name" : "projectId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "path",
          "name" : "ruleId",
          "required" : true,
          "schema" : {
            "type" : "string"
          }
        } ],
        "responses" : {
          "200" : {
            "description" : "OK"
          }
        },
        "summary" : "Delete a standing calendar alert rule and its pending alerts",
        "tags" : [ "News API" ]
      }
    },
    "/rest/api/v1/projects/{projectId}/calendarAlerts" : {
      "get" : {
        "description" : "Contains the manually armed bells as well as the advance warnings materialised from the news features.",
        "operationId" : "getCalendarAlerts",
        "parameters" : [ {
          "in" : "path",
          "name" : "projectId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "type" : "array",
                  "items" : {
                    "$ref" : "#/components/schemas/CalendarAlertDTO"
                  }
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "List the pending calendar alerts of the project",
        "tags" : [ "News API" ]
      },
      "post" : {
        "description" : "The alert belongs to the project, not to the logged in user, because delivery goes through channels the project shares. Arming the same event twice with the same lead time updates the existing row instead of creating a second one.",
        "operationId" : "createCalendarAlert",
        "parameters" : [ {
          "in" : "path",
          "name" : "projectId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "requestBody" : {
          "content" : {
            "application/json" : {
              "schema" : {
                "$ref" : "#/components/schemas/CalendarAlertDTO"
              }
            }
          },
          "required" : true
        },
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/CalendarAlertDTO"
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Arm a reminder for one calendar event",
        "tags" : [ "News API" ]
      }
    },
    "/rest/api/v1/projects/{projectId}/calendarAlerts/{alertId}" : {
      "delete" : {
        "operationId" : "deleteCalendarAlert",
        "parameters" : [ {
          "in" : "path",
          "name" : "projectId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "path",
          "name" : "alertId",
          "required" : true,
          "schema" : {
            "type" : "string"
          }
        } ],
        "responses" : {
          "200" : {
            "description" : "OK"
          }
        },
        "summary" : "Disarm a calendar alert",
        "tags" : [ "News API" ]
      },
      "put" : {
        "description" : "Only a bell can be edited. Warnings of a news feature and rows materialised from a rule follow their source.",
        "operationId" : "updateCalendarAlert",
        "parameters" : [ {
          "in" : "path",
          "name" : "projectId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "path",
          "name" : "alertId",
          "required" : true,
          "schema" : {
            "type" : "string"
          }
        } ],
        "requestBody" : {
          "content" : {
            "application/json" : {
              "schema" : {
                "$ref" : "#/components/schemas/CalendarAlertDTO"
              }
            }
          },
          "required" : true
        },
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/CalendarAlertDTO"
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Change the lead time or the channels of a pending reminder",
        "tags" : [ "News API" ]
      }
    },
    "/rest/api/v1/projects/{projectId}/calendarSubscriptions" : {
      "get" : {
        "description" : "A subscription belongs to the project, so everyone with access to it sees the same list. The token itself is never returned again, a lost URL has to be revoked and recreated.",
        "operationId" : "getCalendarSubscriptions",
        "parameters" : [ {
          "in" : "path",
          "name" : "projectId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "type" : "array",
                  "items" : {
                    "$ref" : "#/components/schemas/CalendarSubscriptionDTO"
                  }
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "List the iCal subscriptions of this project",
        "tags" : [ "News API" ]
      },
      "post" : {
        "description" : "The response carries the full feed URL including the token. It is shown once and only its hash is stored.",
        "operationId" : "createCalendarSubscription",
        "parameters" : [ {
          "in" : "path",
          "name" : "projectId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "requestBody" : {
          "content" : {
            "application/json" : {
              "schema" : {
                "$ref" : "#/components/schemas/CalendarSubscriptionDTO"
              }
            }
          },
          "required" : true
        },
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/CalendarSubscriptionDTO"
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Create an iCal subscription",
        "tags" : [ "News API" ]
      }
    },
    "/rest/api/v1/projects/{projectId}/calendarSubscriptions/{subscriptionId}" : {
      "delete" : {
        "description" : "The row is deleted, so the URL stops working immediately and cannot be re-enabled.",
        "operationId" : "deleteCalendarSubscription",
        "parameters" : [ {
          "in" : "path",
          "name" : "projectId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "path",
          "name" : "subscriptionId",
          "required" : true,
          "schema" : {
            "type" : "string"
          }
        } ],
        "responses" : {
          "200" : {
            "description" : "OK"
          }
        },
        "summary" : "Revoke an iCal subscription",
        "tags" : [ "News API" ]
      }
    },
    "/rest/api/v1/projects/{projectId}/closeAllPositions" : {
      "post" : {
        "operationId" : "closeAllPositionsInAllAccounts",
        "parameters" : [ {
          "in" : "path",
          "name" : "projectId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "responses" : {
          "204" : {
            "description" : "No Content"
          }
        },
        "summary" : "Close all open positions in all accounts",
        "tags" : [ "Project API" ]
      }
    },
    "/rest/api/v1/projects/{projectId}/costs/forecast" : {
      "get" : {
        "operationId" : "getForecastCost",
        "parameters" : [ {
          "in" : "path",
          "name" : "projectId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/ForecastDTO"
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Retrieve forecast cost for a specific project",
        "tags" : [ "Project API" ]
      }
    },
    "/rest/api/v1/projects/{projectId}/dashboards" : {
      "get" : {
        "operationId" : "getAllDashboards",
        "parameters" : [ {
          "in" : "path",
          "name" : "projectId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/DashboardStorageDTO"
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Get all dashboards",
        "tags" : [ "Dashboard API" ]
      },
      "post" : {
        "operationId" : "createDashboard",
        "parameters" : [ {
          "in" : "path",
          "name" : "projectId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "requestBody" : {
          "content" : {
            "application/json" : {
              "schema" : {
                "$ref" : "#/components/schemas/UserDashboardConfigDTO"
              }
            }
          },
          "required" : true
        },
        "responses" : {
          "201" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/UserDashboardConfigDTO"
                }
              }
            },
            "description" : "Created"
          }
        },
        "summary" : "Create a dashboard",
        "tags" : [ "Dashboard API" ]
      }
    },
    "/rest/api/v1/projects/{projectId}/dashboards/bulk" : {
      "put" : {
        "operationId" : "bulkSaveDashboards",
        "parameters" : [ {
          "in" : "path",
          "name" : "projectId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "requestBody" : {
          "content" : {
            "application/json" : {
              "schema" : {
                "$ref" : "#/components/schemas/DashboardStorageDTO"
              }
            }
          },
          "required" : true
        },
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/DashboardStorageDTO"
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Bulk save dashboards",
        "tags" : [ "Dashboard API" ]
      }
    },
    "/rest/api/v1/projects/{projectId}/dashboards/reorder" : {
      "put" : {
        "operationId" : "reorderDashboards",
        "parameters" : [ {
          "in" : "path",
          "name" : "projectId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "requestBody" : {
          "content" : {
            "application/json" : {
              "schema" : {
                "$ref" : "#/components/schemas/ReorderDashboardsRequestDTO"
              }
            }
          },
          "required" : true
        },
        "responses" : {
          "204" : {
            "description" : "No Content"
          }
        },
        "summary" : "Reorder dashboards",
        "tags" : [ "Dashboard API" ]
      }
    },
    "/rest/api/v1/projects/{projectId}/dashboards/{dashboardId}" : {
      "delete" : {
        "operationId" : "deleteDashboard",
        "parameters" : [ {
          "in" : "path",
          "name" : "projectId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "path",
          "name" : "dashboardId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "responses" : {
          "204" : {
            "description" : "No Content"
          }
        },
        "summary" : "Delete a dashboard",
        "tags" : [ "Dashboard API" ]
      },
      "get" : {
        "operationId" : "getDashboard",
        "parameters" : [ {
          "in" : "path",
          "name" : "projectId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "path",
          "name" : "dashboardId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/UserDashboardConfigDTO"
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Get a dashboard",
        "tags" : [ "Dashboard API" ]
      },
      "patch" : {
        "operationId" : "patchDashboard",
        "parameters" : [ {
          "in" : "path",
          "name" : "projectId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "path",
          "name" : "dashboardId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "requestBody" : {
          "content" : {
            "application/json" : {
              "schema" : {
                "$ref" : "#/components/schemas/UserDashboardConfigDTO"
              }
            }
          },
          "required" : true
        },
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/UserDashboardConfigDTO"
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Partially update a dashboard",
        "tags" : [ "Dashboard API" ]
      },
      "put" : {
        "operationId" : "updateDashboard",
        "parameters" : [ {
          "in" : "path",
          "name" : "projectId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "path",
          "name" : "dashboardId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "requestBody" : {
          "content" : {
            "application/json" : {
              "schema" : {
                "$ref" : "#/components/schemas/UserDashboardConfigDTO"
              }
            }
          },
          "required" : true
        },
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/UserDashboardConfigDTO"
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Update a dashboard",
        "tags" : [ "Dashboard API" ]
      }
    },
    "/rest/api/v1/projects/{projectId}/dashboards/{dashboardId}/duplicate" : {
      "post" : {
        "operationId" : "duplicateDashboard",
        "parameters" : [ {
          "in" : "path",
          "name" : "projectId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "path",
          "name" : "dashboardId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "requestBody" : {
          "content" : {
            "application/json" : {
              "schema" : {
                "$ref" : "#/components/schemas/DuplicateDashboardRequestDTO"
              }
            }
          }
        },
        "responses" : {
          "201" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/UserDashboardConfigDTO"
                }
              }
            },
            "description" : "Created"
          }
        },
        "summary" : "Duplicate a dashboard",
        "tags" : [ "Dashboard API" ]
      }
    },
    "/rest/api/v1/projects/{projectId}/economicCalendar" : {
      "get" : {
        "description" : "The calendar is global and identical for every project. Without from/to the current day plus seven days is returned.",
        "operationId" : "getEconomicCalendar",
        "parameters" : [ {
          "in" : "path",
          "name" : "projectId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "description" : "Start of the range (ISO-8601 UTC)",
          "example" : "2026-01-15T00:00:00Z",
          "in" : "query",
          "name" : "from",
          "required" : false,
          "schema" : {
            "type" : "string"
          }
        }, {
          "description" : "End of the range (ISO-8601 UTC)",
          "example" : "2026-01-22T00:00:00Z",
          "in" : "query",
          "name" : "to",
          "required" : false,
          "schema" : {
            "type" : "string"
          }
        }, {
          "description" : "Comma separated currency codes",
          "example" : "USD,EUR",
          "in" : "query",
          "name" : "currencies",
          "required" : false,
          "schema" : {
            "type" : "string"
          }
        }, {
          "description" : "Comma separated ISO-2 country codes",
          "example" : "US,DE",
          "in" : "query",
          "name" : "countries",
          "required" : false,
          "schema" : {
            "type" : "string"
          }
        }, {
          "description" : "Minimum impact: HOLIDAY, LOW, MEDIUM or HIGH",
          "example" : "HIGH",
          "in" : "query",
          "name" : "impact",
          "required" : false,
          "schema" : {
            "type" : "string"
          }
        }, {
          "description" : "Case insensitive substring of the event title",
          "example" : "Non-Farm",
          "in" : "query",
          "name" : "search",
          "required" : false,
          "schema" : {
            "type" : "string"
          }
        }, {
          "description" : "Zero based page index",
          "example" : 0,
          "in" : "query",
          "name" : "page",
          "required" : false,
          "schema" : {
            "type" : "integer",
            "format" : "int32"
          }
        }, {
          "description" : "Page size, maximum 100",
          "example" : 25,
          "in" : "query",
          "name" : "size",
          "required" : false,
          "schema" : {
            "type" : "integer",
            "format" : "int32"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/CalendarEventPageDTO"
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Get economic calendar events",
        "tags" : [ "News API" ]
      }
    },
    "/rest/api/v1/projects/{projectId}/economicCalendar.ics" : {
      "get" : {
        "description" : "Authenticated by its own revocable token in the query string, because a calendar client cannot send headers. Personal use only: the range is limited and the feed is rate limited per subscription.",
        "operationId" : "getCalendarFeed",
        "parameters" : [ {
          "in" : "path",
          "name" : "projectId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "description" : "Subscription token, shown once when the subscription is created",
          "in" : "query",
          "name" : "token",
          "required" : true,
          "schema" : {
            "type" : "string"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "text/calendar;charset=UTF-8" : {
                "schema" : {
                  "type" : "string"
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "iCal subscription feed",
        "tags" : [ "News API" ]
      }
    },
    "/rest/api/v1/projects/{projectId}/economicCalendar/exposure" : {
      "get" : {
        "description" : "Open positions live on the node, so this costs one round trip to the account and is deliberately account scoped and user triggered rather than part of a page load. A symbol listed under unresolvedSymbols is a symbol the news filter would not protect either.",
        "operationId" : "getExposure",
        "parameters" : [ {
          "in" : "path",
          "name" : "projectId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "description" : "Account to read the open positions from",
          "in" : "query",
          "name" : "accountId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "description" : "Days to look ahead, default 3, maximum 14",
          "example" : 3,
          "in" : "query",
          "name" : "days",
          "required" : false,
          "schema" : {
            "type" : "integer",
            "format" : "int32"
          }
        }, {
          "description" : "Minimum impact, default HIGH",
          "example" : "HIGH",
          "in" : "query",
          "name" : "impact",
          "required" : false,
          "schema" : {
            "type" : "string"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/CalendarExposureDTO"
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Which upcoming releases hit the open positions",
        "tags" : [ "News API" ]
      }
    },
    "/rest/api/v1/projects/{projectId}/economicCalendar/rateOutlook" : {
      "get" : {
        "description" : "The current rate comes from the last released decision in our own archive, so every major currency is covered; for EUR the ECB open data value overrides it. Without the currencies parameter all eight majors are returned.",
        "operationId" : "getRateOutlook",
        "parameters" : [ {
          "in" : "path",
          "name" : "projectId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "description" : "Comma separated currency codes",
          "example" : "USD,EUR",
          "in" : "query",
          "name" : "currencies",
          "required" : false,
          "schema" : {
            "type" : "string"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "type" : "array",
                  "items" : {
                    "$ref" : "#/components/schemas/RateOutlookDTO"
                  }
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Policy rate and next decision per currency",
        "tags" : [ "News API" ]
      }
    },
    "/rest/api/v1/projects/{projectId}/economicCalendar/riskHeatmap" : {
      "get" : {
        "description" : "Impact weighted count, HIGH counts three and MEDIUM one, normalised against the busiest cell in the same range. It answers when the week is dangerous, not how the week compares with last year.",
        "operationId" : "getRiskHeatmap",
        "parameters" : [ {
          "in" : "path",
          "name" : "projectId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "description" : "ISO instant, default now",
          "example" : "2026-08-11T00:00:00Z",
          "in" : "query",
          "name" : "from",
          "required" : false,
          "schema" : {
            "type" : "string"
          }
        }, {
          "description" : "ISO instant, default seven days after from",
          "example" : "2026-08-18T00:00:00Z",
          "in" : "query",
          "name" : "to",
          "required" : false,
          "schema" : {
            "type" : "string"
          }
        }, {
          "description" : "Comma separated currency codes",
          "example" : "USD,EUR",
          "in" : "query",
          "name" : "currencies",
          "required" : false,
          "schema" : {
            "type" : "string"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/RiskHeatmapDTO"
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Event load per day and currency",
        "tags" : [ "News API" ]
      }
    },
    "/rest/api/v1/projects/{projectId}/economicCalendar/surpriseIndex" : {
      "get" : {
        "description" : "Whether a currency's data has been beating or missing expectations lately. The sign is direction corrected, so a rise in unemployment counts as a miss and not as a beat.",
        "operationId" : "getSurpriseIndex",
        "parameters" : [ {
          "in" : "path",
          "name" : "projectId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "description" : "Comma separated currency codes",
          "example" : "USD,EUR",
          "in" : "query",
          "name" : "currencies",
          "required" : false,
          "schema" : {
            "type" : "string"
          }
        }, {
          "description" : "Days to look back, default 90, maximum 365",
          "example" : 90,
          "in" : "query",
          "name" : "days",
          "required" : false,
          "schema" : {
            "type" : "integer",
            "format" : "int32"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/SurpriseIndexDTO"
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Rolling surprise index per currency",
        "tags" : [ "News API" ]
      }
    },
    "/rest/api/v1/projects/{projectId}/economicCalendar/{eventId}" : {
      "get" : {
        "operationId" : "getEconomicCalendarEvent",
        "parameters" : [ {
          "in" : "path",
          "name" : "projectId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "path",
          "name" : "eventId",
          "required" : true,
          "schema" : {
            "type" : "string"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/CalendarEventDTO"
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Get a single economic calendar event including its revision history",
        "tags" : [ "News API" ]
      }
    },
    "/rest/api/v1/projects/{projectId}/economicCalendar/{eventId}/history" : {
      "get" : {
        "description" : "Actual against forecast for the last releases of this indicator, oldest first so the list can be charted directly. The sigma of each row is measured against the releases that came before it, and it stays null while the history is too thin to standardise against.",
        "operationId" : "getIndicatorHistory",
        "parameters" : [ {
          "in" : "path",
          "name" : "projectId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "path",
          "name" : "eventId",
          "required" : true,
          "schema" : {
            "type" : "string"
          }
        }, {
          "description" : "Releases to return, default 12, maximum 60",
          "example" : 12,
          "in" : "query",
          "name" : "limit",
          "required" : false,
          "schema" : {
            "type" : "integer",
            "format" : "int32"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/IndicatorHistoryDTO"
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Past releases of the same indicator",
        "tags" : [ "News API" ]
      }
    },
    "/rest/api/v1/projects/{projectId}/features" : {
      "get" : {
        "operationId" : "getProjectFeatures",
        "parameters" : [ {
          "in" : "path",
          "name" : "projectId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "type" : "array",
                  "items" : {
                    "$ref" : "#/components/schemas/FeatureDTO"
                  }
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Get all project features",
        "tags" : [ "Project API" ]
      },
      "post" : {
        "operationId" : "createProjectFeature",
        "parameters" : [ {
          "in" : "path",
          "name" : "projectId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "requestBody" : {
          "content" : {
            "application/json" : {
              "schema" : {
                "$ref" : "#/components/schemas/FeatureDTO"
              }
            }
          },
          "required" : true
        },
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/FeatureDTO"
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Create a project feature",
        "tags" : [ "Project API" ]
      }
    },
    "/rest/api/v1/projects/{projectId}/features/{featureId}" : {
      "delete" : {
        "operationId" : "deleteProjectFeature",
        "parameters" : [ {
          "in" : "path",
          "name" : "projectId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "path",
          "name" : "featureId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "responses" : {
          "200" : {
            "description" : "OK"
          }
        },
        "summary" : "Delete a project feature",
        "tags" : [ "Project API" ]
      },
      "get" : {
        "operationId" : "getProjectFeature",
        "parameters" : [ {
          "in" : "path",
          "name" : "projectId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "path",
          "name" : "featureId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/FeatureDTO"
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Get a project feature",
        "tags" : [ "Project API" ]
      },
      "put" : {
        "operationId" : "updateProjectFeature",
        "parameters" : [ {
          "in" : "path",
          "name" : "projectId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "path",
          "name" : "featureId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "requestBody" : {
          "content" : {
            "application/json" : {
              "schema" : {
                "$ref" : "#/components/schemas/FeatureDTO"
              }
            }
          },
          "required" : true
        },
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/FeatureDTO"
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Update a project feature",
        "tags" : [ "Project API" ]
      }
    },
    "/rest/api/v1/projects/{projectId}/features/{featureId}/whitelabel/customers/block" : {
      "put" : {
        "operationId" : "blockWhiteLabelCustomer",
        "parameters" : [ {
          "in" : "path",
          "name" : "projectId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "path",
          "name" : "featureId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "requestBody" : {
          "content" : {
            "application/json" : {
              "schema" : {
                "$ref" : "#/components/schemas/BlockCustomerRequestDTO"
              }
            }
          },
          "required" : true
        },
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/BlockCustomerResponseDTO"
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Block a white-label customer across every project of this white-label that they own (identified by email)",
        "tags" : [ "Project API" ]
      }
    },
    "/rest/api/v1/projects/{projectId}/features/{featureId}/whitelabel/customers/{customerId}/invoices" : {
      "get" : {
        "operationId" : "listWhiteLabelCustomerInvoices",
        "parameters" : [ {
          "in" : "path",
          "name" : "projectId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "path",
          "name" : "featureId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "path",
          "name" : "customerId",
          "required" : true,
          "schema" : {
            "type" : "integer",
            "format" : "int32"
          }
        }, {
          "description" : "Filter by status: OPEN, PAID, VOID, ALL (default ALL)",
          "in" : "query",
          "name" : "status",
          "required" : false,
          "schema" : {
            "type" : "string"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "type" : "array",
                  "items" : {
                    "$ref" : "#/components/schemas/InvoiceDTO"
                  }
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "List invoices for a single WhiteLabel customer across all projects of the WhiteLabel",
        "tags" : [ "Project API" ]
      }
    },
    "/rest/api/v1/projects/{projectId}/features/{featureId}/whitelabel/customers/{customerId}/invoices/paid" : {
      "put" : {
        "operationId" : "markAllWhiteLabelCustomerInvoicesPaid",
        "parameters" : [ {
          "in" : "path",
          "name" : "projectId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "path",
          "name" : "featureId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "path",
          "name" : "customerId",
          "required" : true,
          "schema" : {
            "type" : "integer",
            "format" : "int32"
          }
        } ],
        "requestBody" : {
          "content" : {
            "application/json" : {
              "schema" : {
                "$ref" : "#/components/schemas/MarkInvoicePaidRequestDTO"
              }
            }
          }
        },
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "type" : "array",
                  "items" : {
                    "$ref" : "#/components/schemas/InvoiceDTO"
                  }
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Bulk mark all OPEN manual-collection invoices of a single customer as paid",
        "tags" : [ "Project API" ]
      }
    },
    "/rest/api/v1/projects/{projectId}/features/{featureId}/whitelabel/dashboard" : {
      "get" : {
        "operationId" : "getWhiteLabelDashboard",
        "parameters" : [ {
          "in" : "path",
          "name" : "projectId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "path",
          "name" : "featureId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/WhiteLabelDashboardDTO"
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Get WhiteLabel dashboard",
        "tags" : [ "Project API" ]
      }
    },
    "/rest/api/v1/projects/{projectId}/features/{featureId}/whitelabel/invoices/{invoiceNumber}/paid" : {
      "put" : {
        "operationId" : "markWhiteLabelInvoicePaid",
        "parameters" : [ {
          "in" : "path",
          "name" : "projectId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "path",
          "name" : "featureId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "path",
          "name" : "invoiceNumber",
          "required" : true,
          "schema" : {
            "type" : "string"
          }
        } ],
        "requestBody" : {
          "content" : {
            "application/json" : {
              "schema" : {
                "$ref" : "#/components/schemas/MarkInvoicePaidRequestDTO"
              }
            }
          }
        },
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/InvoiceDTO"
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Mark a single OPEN manual-collection invoice as paid (WhiteLabel owner action)",
        "tags" : [ "Project API" ]
      }
    },
    "/rest/api/v1/projects/{projectId}/features/{featureId}/whitelabel/invoices/{invoiceNumber}/void" : {
      "put" : {
        "operationId" : "voidWhiteLabelInvoice",
        "parameters" : [ {
          "in" : "path",
          "name" : "projectId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "path",
          "name" : "featureId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "path",
          "name" : "invoiceNumber",
          "required" : true,
          "schema" : {
            "type" : "string"
          }
        } ],
        "requestBody" : {
          "content" : {
            "application/json" : {
              "schema" : {
                "$ref" : "#/components/schemas/RefundInvoiceRequestDTO"
              }
            }
          }
        },
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/InvoiceDTO"
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Void an OPEN invoice or refund a PAID invoice of a white-label customer (WhiteLabel owner action)",
        "tags" : [ "Project API" ]
      }
    },
    "/rest/api/v1/projects/{projectId}/invoices" : {
      "get" : {
        "operationId" : "getInvoices",
        "parameters" : [ {
          "in" : "path",
          "name" : "projectId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "type" : "array",
                  "items" : {
                    "$ref" : "#/components/schemas/InvoiceDTO"
                  }
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Get all invoices",
        "tags" : [ "Project API" ]
      }
    },
    "/rest/api/v1/projects/{projectId}/invoices/{invoiceNumber}/details" : {
      "get" : {
        "operationId" : "getInvoiceDetails",
        "parameters" : [ {
          "in" : "path",
          "name" : "projectId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "path",
          "name" : "invoiceNumber",
          "required" : true,
          "schema" : {
            "type" : "string"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "type" : "object"
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Get invoice calculation details",
        "tags" : [ "Project API" ]
      }
    },
    "/rest/api/v1/projects/{projectId}/labels" : {
      "get" : {
        "operationId" : "getAvailableLabels",
        "parameters" : [ {
          "in" : "path",
          "name" : "projectId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "type" : "array",
                  "items" : {
                    "type" : "string"
                  }
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Get available labels (for account)",
        "tags" : [ "Project API" ]
      }
    },
    "/rest/api/v1/projects/{projectId}/logs" : {
      "get" : {
        "operationId" : "getProjectLogs",
        "parameters" : [ {
          "in" : "path",
          "name" : "projectId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "description" : "Get the last logs: e.g. 100 means the last 100 logs",
          "example" : 100,
          "in" : "query",
          "name" : "limit",
          "required" : false,
          "schema" : {
            "type" : "integer",
            "format" : "int32"
          }
        }, {
          "description" : "You can set an offset. Offset 100 means 101-200",
          "example" : 0,
          "in" : "query",
          "name" : "offset",
          "required" : false,
          "schema" : {
            "type" : "integer",
            "format" : "int32"
          }
        }, {
          "description" : "Filter logs by log level type ID. If you choose 3 = Info, then all logs with a lower level are returned. The levels are: 1 = Error, 2 = Warning, 3 = Info.",
          "example" : 1,
          "in" : "query",
          "name" : "logTypeId",
          "required" : false,
          "schema" : {
            "type" : "integer",
            "format" : "int32"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "type" : "array",
                  "items" : {
                    "$ref" : "#/components/schemas/LogDTO"
                  }
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Get project logs",
        "tags" : [ "Project API" ]
      }
    },
    "/rest/api/v1/projects/{projectId}/logs/acknowledge/bulk" : {
      "put" : {
        "operationId" : "acknowledgeLogsBulk",
        "parameters" : [ {
          "in" : "path",
          "name" : "projectId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "requestBody" : {
          "content" : {
            "application/json" : {
              "schema" : {
                "type" : "array",
                "items" : {
                  "type" : "integer",
                  "format" : "int32"
                }
              }
            }
          },
          "required" : true
        },
        "responses" : {
          "200" : {
            "description" : "OK"
          }
        },
        "tags" : [ "Project API" ]
      }
    },
    "/rest/api/v1/projects/{projectId}/logs/acknowledgeAll" : {
      "put" : {
        "operationId" : "acknowledgeAllLogs",
        "parameters" : [ {
          "in" : "path",
          "name" : "projectId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "responses" : {
          "200" : {
            "description" : "OK"
          }
        },
        "summary" : "Acknowledge all logs",
        "tags" : [ "Project API" ]
      }
    },
    "/rest/api/v1/projects/{projectId}/logs/{id}/acknowledge" : {
      "put" : {
        "operationId" : "acknowledgeLog",
        "parameters" : [ {
          "in" : "path",
          "name" : "projectId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "path",
          "name" : "id",
          "required" : true,
          "schema" : {
            "type" : "integer",
            "format" : "int32"
          }
        } ],
        "responses" : {
          "200" : {
            "description" : "OK"
          }
        },
        "summary" : "Acknowledge a log",
        "tags" : [ "Project API" ]
      }
    },
    "/rest/api/v1/projects/{projectId}/marketNews" : {
      "get" : {
        "description" : "Headline and summary are written by MetaCopier from the source article, the publisher's own text is never served. Articles that have not been summarised yet are not returned at all.",
        "operationId" : "getMarketNews",
        "parameters" : [ {
          "in" : "path",
          "name" : "projectId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "description" : "Feed category: forex, markets, crypto, indicators or general",
          "example" : "forex",
          "in" : "query",
          "name" : "category",
          "required" : false,
          "schema" : {
            "type" : "string"
          }
        }, {
          "description" : "Minimum impact: LOW, MEDIUM or HIGH",
          "example" : "HIGH",
          "in" : "query",
          "name" : "impact",
          "required" : false,
          "schema" : {
            "type" : "string"
          }
        }, {
          "description" : "BEARISH, NEUTRAL or BULLISH",
          "example" : "BULLISH",
          "in" : "query",
          "name" : "sentiment",
          "required" : false,
          "schema" : {
            "type" : "string"
          }
        }, {
          "description" : "Comma separated currency codes",
          "example" : "USD,EUR",
          "in" : "query",
          "name" : "currencies",
          "required" : false,
          "schema" : {
            "type" : "string"
          }
        }, {
          "description" : "Case insensitive substring of the headline or summary",
          "example" : "inflation",
          "in" : "query",
          "name" : "search",
          "required" : false,
          "schema" : {
            "type" : "string"
          }
        }, {
          "description" : "Only the articles this project has bookmarked",
          "example" : true,
          "in" : "query",
          "name" : "bookmarked",
          "required" : false,
          "schema" : {
            "type" : "boolean"
          }
        }, {
          "description" : "Zero based page index",
          "example" : 0,
          "in" : "query",
          "name" : "page",
          "required" : false,
          "schema" : {
            "type" : "integer",
            "format" : "int32"
          }
        }, {
          "description" : "Page size, maximum 100",
          "example" : 25,
          "in" : "query",
          "name" : "size",
          "required" : false,
          "schema" : {
            "type" : "integer",
            "format" : "int32"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/MarketNewsPageDTO"
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Get market news articles",
        "tags" : [ "News API" ]
      }
    },
    "/rest/api/v1/projects/{projectId}/newsBookmarks" : {
      "get" : {
        "description" : "Ids only, so the news list can render the saved state without one call per row. The articles themselves come from the news endpoint with bookmarked=true.",
        "operationId" : "getNewsBookmarks",
        "parameters" : [ {
          "in" : "path",
          "name" : "projectId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "type" : "array",
                  "items" : {
                    "type" : "string"
                  }
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Ids of the bookmarked articles",
        "tags" : [ "News API" ]
      }
    },
    "/rest/api/v1/projects/{projectId}/newsBookmarks/{articleId}" : {
      "delete" : {
        "operationId" : "deleteNewsBookmark",
        "parameters" : [ {
          "in" : "path",
          "name" : "projectId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "path",
          "name" : "articleId",
          "required" : true,
          "schema" : {
            "type" : "string"
          }
        } ],
        "responses" : {
          "200" : {
            "description" : "OK"
          }
        },
        "summary" : "Remove a bookmark",
        "tags" : [ "News API" ]
      },
      "post" : {
        "description" : "Bookmarks belong to the project, not to the individual member, which is the same scope every other news setting has. Saving an already saved article is not an error.",
        "operationId" : "addNewsBookmark",
        "parameters" : [ {
          "in" : "path",
          "name" : "projectId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "path",
          "name" : "articleId",
          "required" : true,
          "schema" : {
            "type" : "string"
          }
        } ],
        "responses" : {
          "200" : {
            "description" : "OK"
          }
        },
        "summary" : "Bookmark a market news article",
        "tags" : [ "News API" ]
      }
    },
    "/rest/api/v1/projects/{projectId}/newsFilter/backtest" : {
      "post" : {
        "description" : "Answers \"would this configuration have cost me money?\". Mode A only: the outcome of a skipped trade is already known, whereas a Mode B re-entry price is not stored anywhere. The blackout decision uses the same evaluator the node runs, so the answer cannot drift from the live filter.",
        "operationId" : "backtestNewsFilter",
        "parameters" : [ {
          "in" : "path",
          "name" : "projectId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "requestBody" : {
          "content" : {
            "application/json" : {
              "schema" : {
                "$ref" : "#/components/schemas/NewsFilterBacktestRequestDTO"
              }
            }
          },
          "required" : true
        },
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/NewsFilterBacktestDTO"
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Replay a news filter configuration over the account's own closed trades",
        "tags" : [ "News API" ]
      }
    },
    "/rest/api/v1/projects/{projectId}/newsFilter/preview" : {
      "get" : {
        "description" : "Answers \"will my mapping actually fire?\" before the configuration is saved. Returns the resolved currencies per symbol plus every blackout window in the range. The backend has no broker symbol data, so the mapping is resolved by name only; a node can additionally use the broker base and quote currency.",
        "operationId" : "previewNewsFilter",
        "parameters" : [ {
          "in" : "path",
          "name" : "projectId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "description" : "Comma separated symbols, at most 20",
          "example" : "EURCHF,XAUUSD,US30",
          "in" : "query",
          "name" : "symbols",
          "required" : true,
          "schema" : {
            "type" : "string"
          }
        }, {
          "description" : "Minimum impact: HOLIDAY, LOW, MEDIUM or HIGH",
          "example" : "HIGH",
          "in" : "query",
          "name" : "impact",
          "required" : false,
          "schema" : {
            "type" : "string"
          }
        }, {
          "description" : "Blackout minutes before the release, default 15",
          "example" : 15,
          "in" : "query",
          "name" : "before",
          "required" : false,
          "schema" : {
            "type" : "integer",
            "format" : "int32"
          }
        }, {
          "description" : "Blackout minutes after the release, default 15",
          "example" : 15,
          "in" : "query",
          "name" : "after",
          "required" : false,
          "schema" : {
            "type" : "integer",
            "format" : "int32"
          }
        }, {
          "description" : "Include bank holidays",
          "example" : false,
          "in" : "query",
          "name" : "includeHolidays",
          "required" : false,
          "schema" : {
            "type" : "boolean"
          }
        }, {
          "description" : "Include global events (currency ALL)",
          "example" : true,
          "in" : "query",
          "name" : "includeGlobalEvents",
          "required" : false,
          "schema" : {
            "type" : "boolean"
          }
        }, {
          "description" : "Days to look ahead, default 7, maximum 14",
          "example" : 7,
          "in" : "query",
          "name" : "days",
          "required" : false,
          "schema" : {
            "type" : "integer",
            "format" : "int32"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/NewsFilterPreviewDTO"
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Dry run of a news filter mapping",
        "tags" : [ "News API" ]
      }
    },
    "/rest/api/v1/projects/{projectId}/newsFilter/symbolMapping" : {
      "get" : {
        "description" : "The cheap half of the filter preview, meant for a live form field. The backend has no broker symbol data, so the mapping is resolved by name only; a node can additionally use the broker base and quote currency.",
        "operationId" : "getSymbolMapping",
        "parameters" : [ {
          "in" : "path",
          "name" : "projectId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "description" : "Comma separated symbols, at most 20",
          "example" : "EURCHF,XAUUSD,US30",
          "in" : "query",
          "name" : "symbols",
          "required" : true,
          "schema" : {
            "type" : "string"
          }
        }, {
          "description" : "Include global events (currency ALL)",
          "example" : true,
          "in" : "query",
          "name" : "includeGlobalEvents",
          "required" : false,
          "schema" : {
            "type" : "boolean"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "type" : "array",
                  "items" : {
                    "$ref" : "#/components/schemas/NewsFilterPreviewSymbolDTO"
                  }
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Which currencies a symbol maps to",
        "tags" : [ "News API" ]
      }
    },
    "/rest/api/v1/projects/{projectId}/notificationChannels" : {
      "get" : {
        "description" : "Derived from the notification channel features of the project, nothing here is stored. Use featureId and an optional recipient key to fill notificationTargets on a feature.",
        "operationId" : "getNotificationChannels",
        "parameters" : [ {
          "in" : "path",
          "name" : "projectId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "description" : "Also list the channels attached to this account",
          "in" : "query",
          "name" : "accountId",
          "required" : false,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "type" : "array",
                  "items" : {
                    "$ref" : "#/components/schemas/NotificationChannelDTO"
                  }
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "List the notification targets a feature can address",
        "tags" : [ "News API" ]
      }
    },
    "/rest/api/v1/projects/{projectId}/signals" : {
      "get" : {
        "operationId" : "getProjectAvailableSignalsToFollow",
        "parameters" : [ {
          "in" : "path",
          "name" : "projectId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "type" : "array",
                  "items" : {
                    "$ref" : "#/components/schemas/FeatureDTO"
                  }
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Get available signals",
        "tags" : [ "Project API" ]
      }
    },
    "/rest/api/v1/projects/{projectId}/strategies" : {
      "get" : {
        "operationId" : "getProjectStrategies",
        "parameters" : [ {
          "in" : "path",
          "name" : "projectId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "type" : "array",
                  "items" : {
                    "$ref" : "#/components/schemas/StrategyDTO"
                  }
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Get all strategies",
        "tags" : [ "Project API" ]
      },
      "post" : {
        "operationId" : "createProjectStrategy",
        "parameters" : [ {
          "in" : "path",
          "name" : "projectId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "requestBody" : {
          "content" : {
            "application/json" : {
              "schema" : {
                "$ref" : "#/components/schemas/StrategyDTO"
              }
            }
          },
          "required" : true
        },
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/StrategyDTO"
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Create a strategy",
        "tags" : [ "Project API" ]
      }
    },
    "/rest/api/v1/projects/{projectId}/strategies/{strategyId}" : {
      "delete" : {
        "operationId" : "deleteProjectStrategy",
        "parameters" : [ {
          "in" : "path",
          "name" : "projectId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "path",
          "name" : "strategyId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "responses" : {
          "200" : {
            "description" : "OK"
          }
        },
        "summary" : "Delete a strategy",
        "tags" : [ "Project API" ]
      },
      "get" : {
        "operationId" : "getProjectStrategy",
        "parameters" : [ {
          "in" : "path",
          "name" : "projectId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "path",
          "name" : "strategyId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/StrategyDTO"
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Get a strategy",
        "tags" : [ "Project API" ]
      },
      "put" : {
        "operationId" : "updateProjectStrategy",
        "parameters" : [ {
          "in" : "path",
          "name" : "projectId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "path",
          "name" : "strategyId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "requestBody" : {
          "content" : {
            "application/json" : {
              "schema" : {
                "$ref" : "#/components/schemas/StrategyDTO"
              }
            }
          },
          "required" : true
        },
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/StrategyDTO"
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Update a strategy",
        "tags" : [ "Project API" ]
      }
    },
    "/rest/api/v1/projects/{projectId}/strategies/{strategyId}/copiers" : {
      "get" : {
        "operationId" : "getProjectStrategyCopiers",
        "parameters" : [ {
          "in" : "path",
          "name" : "projectId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "path",
          "name" : "strategyId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "type" : "array",
                  "items" : {
                    "$ref" : "#/components/schemas/CopierDTO"
                  }
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Get strategy copiers",
        "tags" : [ "Project API" ]
      },
      "post" : {
        "operationId" : "createProjectStrategyCopier",
        "parameters" : [ {
          "in" : "path",
          "name" : "projectId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "path",
          "name" : "strategyId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "requestBody" : {
          "content" : {
            "application/json" : {
              "schema" : {
                "$ref" : "#/components/schemas/CopierDTO"
              }
            }
          },
          "required" : true
        },
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/CopierDTO"
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Create a strategy copier",
        "tags" : [ "Project API" ]
      }
    },
    "/rest/api/v1/projects/{projectId}/strategies/{strategyId}/copiers/{copierId}" : {
      "delete" : {
        "operationId" : "deleteProjectStrategyCopier",
        "parameters" : [ {
          "in" : "path",
          "name" : "projectId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "path",
          "name" : "strategyId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "path",
          "name" : "copierId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "responses" : {
          "200" : {
            "description" : "OK"
          }
        },
        "summary" : "Delete a strategy copier",
        "tags" : [ "Project API" ]
      },
      "get" : {
        "operationId" : "getProjectStrategyCopier",
        "parameters" : [ {
          "in" : "path",
          "name" : "projectId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "path",
          "name" : "strategyId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "path",
          "name" : "copierId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/CopierDTO"
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Get strategy copier",
        "tags" : [ "Project API" ]
      },
      "put" : {
        "operationId" : "updateProjectStrategyCopier",
        "parameters" : [ {
          "in" : "path",
          "name" : "projectId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "path",
          "name" : "strategyId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "path",
          "name" : "copierId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "requestBody" : {
          "content" : {
            "application/json" : {
              "schema" : {
                "$ref" : "#/components/schemas/CopierDTO"
              }
            }
          },
          "required" : true
        },
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/CopierDTO"
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Update a strategy copier",
        "tags" : [ "Project API" ]
      }
    },
    "/rest/api/v1/projects/{projectId}/strategies/{strategyId}/copiers/{copierId}/features" : {
      "get" : {
        "operationId" : "getProjectStrategyCopierFeatures",
        "parameters" : [ {
          "in" : "path",
          "name" : "projectId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "path",
          "name" : "strategyId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "path",
          "name" : "copierId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "type" : "array",
                  "items" : {
                    "$ref" : "#/components/schemas/FeatureDTO"
                  }
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Get all strategy copier features",
        "tags" : [ "Project API" ]
      },
      "post" : {
        "operationId" : "createProjectStrategyCopierFeature",
        "parameters" : [ {
          "in" : "path",
          "name" : "projectId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "path",
          "name" : "strategyId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "path",
          "name" : "copierId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "requestBody" : {
          "content" : {
            "application/json" : {
              "schema" : {
                "$ref" : "#/components/schemas/FeatureDTO"
              }
            }
          },
          "required" : true
        },
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/FeatureDTO"
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Create a strategy copier feature",
        "tags" : [ "Project API" ]
      }
    },
    "/rest/api/v1/projects/{projectId}/strategies/{strategyId}/copiers/{copierId}/features/{featureId}" : {
      "delete" : {
        "operationId" : "deleteProjectStrategyCopierFeature",
        "parameters" : [ {
          "in" : "path",
          "name" : "projectId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "path",
          "name" : "strategyId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "path",
          "name" : "copierId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "path",
          "name" : "featureId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "responses" : {
          "200" : {
            "description" : "OK"
          }
        },
        "summary" : "Delete a strategy copier feature",
        "tags" : [ "Project API" ]
      },
      "get" : {
        "operationId" : "getProjectStrategyCopierFeature",
        "parameters" : [ {
          "in" : "path",
          "name" : "projectId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "path",
          "name" : "strategyId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "path",
          "name" : "copierId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "path",
          "name" : "featureId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/FeatureDTO"
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Get a strategy copier feature",
        "tags" : [ "Project API" ]
      },
      "put" : {
        "operationId" : "updateProjectStrategyCopierFeature",
        "parameters" : [ {
          "in" : "path",
          "name" : "projectId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "path",
          "name" : "strategyId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "path",
          "name" : "copierId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "path",
          "name" : "featureId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "requestBody" : {
          "content" : {
            "application/json" : {
              "schema" : {
                "$ref" : "#/components/schemas/FeatureDTO"
              }
            }
          },
          "required" : true
        },
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/FeatureDTO"
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Update a strategy copier feature",
        "tags" : [ "Project API" ]
      }
    },
    "/rest/api/v1/projects/{projectId}/strategies/{strategyId}/copiers/{copierId}/resync" : {
      "post" : {
        "description" : "Resynchronize with the master account. If a position was closed on the slave account but remains open on the master, this operation will reopen the position on the slave to match the master's state.",
        "operationId" : "resyncStrategyCopier",
        "parameters" : [ {
          "in" : "path",
          "name" : "projectId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "path",
          "name" : "strategyId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "path",
          "name" : "copierId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "responses" : {
          "204" : {
            "description" : "No Content"
          }
        },
        "summary" : "Resync copier with master",
        "tags" : [ "Project API" ]
      }
    },
    "/rest/api/v1/projects/{projectId}/symbolMappings" : {
      "get" : {
        "operationId" : "getProjectSymbolMappings",
        "parameters" : [ {
          "in" : "path",
          "name" : "projectId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "type" : "array",
                  "items" : {
                    "$ref" : "#/components/schemas/SymbolMappingDTO"
                  }
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Get symbol mappings",
        "tags" : [ "Project API" ]
      },
      "post" : {
        "operationId" : "createProjectSymbolMapping",
        "parameters" : [ {
          "in" : "path",
          "name" : "projectId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "requestBody" : {
          "content" : {
            "application/json" : {
              "schema" : {
                "$ref" : "#/components/schemas/SymbolMappingDTO"
              }
            }
          },
          "required" : true
        },
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/SymbolMappingDTO"
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Create a symbol mapping",
        "tags" : [ "Project API" ]
      }
    },
    "/rest/api/v1/projects/{projectId}/symbolMappings/{symbolMappingId}" : {
      "delete" : {
        "operationId" : "deleteProjectSymbolMapping",
        "parameters" : [ {
          "in" : "path",
          "name" : "projectId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "path",
          "name" : "symbolMappingId",
          "required" : true,
          "schema" : {
            "type" : "integer",
            "format" : "int32"
          }
        } ],
        "responses" : {
          "200" : {
            "description" : "OK"
          }
        },
        "summary" : "Delete a symbol mapping",
        "tags" : [ "Project API" ]
      },
      "get" : {
        "operationId" : "getProjectSymbolMapping",
        "parameters" : [ {
          "in" : "path",
          "name" : "projectId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "path",
          "name" : "symbolMappingId",
          "required" : true,
          "schema" : {
            "type" : "integer",
            "format" : "int32"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/SymbolMappingDTO"
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Get a symbol mapping",
        "tags" : [ "Project API" ]
      },
      "put" : {
        "operationId" : "updateProjectSymbolMapping",
        "parameters" : [ {
          "in" : "path",
          "name" : "projectId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "path",
          "name" : "symbolMappingId",
          "required" : true,
          "schema" : {
            "type" : "integer",
            "format" : "int32"
          }
        } ],
        "requestBody" : {
          "content" : {
            "application/json" : {
              "schema" : {
                "$ref" : "#/components/schemas/SymbolMappingDTO"
              }
            }
          },
          "required" : true
        },
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/SymbolMappingDTO"
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Update a symbol mapping",
        "tags" : [ "Project API" ]
      }
    },
    "/rest/api/v1/projects/{projectId}/templates" : {
      "get" : {
        "operationId" : "getAccountTemplates",
        "parameters" : [ {
          "in" : "path",
          "name" : "projectId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "type" : "array",
                  "items" : {
                    "$ref" : "#/components/schemas/AccountTemplateSummaryDTO"
                  }
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "List account templates for a project (compact view without payload)",
        "tags" : [ "Account Template API" ]
      },
      "post" : {
        "operationId" : "createAccountTemplate",
        "parameters" : [ {
          "in" : "path",
          "name" : "projectId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "requestBody" : {
          "content" : {
            "application/json" : {
              "schema" : {
                "$ref" : "#/components/schemas/AccountTemplateDTO"
              }
            }
          },
          "required" : true
        },
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/AccountTemplateDTO"
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Create an account template",
        "tags" : [ "Account Template API" ]
      }
    },
    "/rest/api/v1/projects/{projectId}/templates/{templateId}" : {
      "delete" : {
        "operationId" : "deleteAccountTemplate",
        "parameters" : [ {
          "in" : "path",
          "name" : "projectId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "path",
          "name" : "templateId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "query",
          "name" : "force",
          "required" : false,
          "schema" : {
            "type" : "boolean",
            "default" : false
          }
        } ],
        "responses" : {
          "204" : {
            "description" : "No Content"
          }
        },
        "summary" : "Delete an account template. Pass force=true to also unlink any accounts currently linked to it.",
        "tags" : [ "Account Template API" ]
      },
      "get" : {
        "operationId" : "getAccountTemplate",
        "parameters" : [ {
          "in" : "path",
          "name" : "projectId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "path",
          "name" : "templateId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/AccountTemplateDTO"
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Get a single account template with its full payload",
        "tags" : [ "Account Template API" ]
      },
      "put" : {
        "operationId" : "updateAccountTemplate",
        "parameters" : [ {
          "in" : "path",
          "name" : "projectId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "path",
          "name" : "templateId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "requestBody" : {
          "content" : {
            "application/json" : {
              "schema" : {
                "$ref" : "#/components/schemas/AccountTemplateDTO"
              }
            }
          },
          "required" : true
        },
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/AccountTemplateDTO"
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Update an account template. The request body must include `expectedRevision`; mismatch with the current revision returns HTTP 409.",
        "tags" : [ "Account Template API" ]
      }
    },
    "/rest/api/v1/projects/{projectId}/templates/{templateId}/linkedAccounts" : {
      "get" : {
        "operationId" : "getAccountTemplateLinkedAccounts",
        "parameters" : [ {
          "in" : "path",
          "name" : "projectId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "path",
          "name" : "templateId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "type" : "array",
                  "items" : {
                    "$ref" : "#/components/schemas/LinkedAccountSummaryDTO"
                  }
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "List accounts currently linked to this template",
        "tags" : [ "Account Template API" ]
      }
    },
    "/rest/api/v1/projects/{projectId}/templates/{templateId}/revisions" : {
      "get" : {
        "operationId" : "getAccountTemplateRevisions",
        "parameters" : [ {
          "in" : "path",
          "name" : "projectId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "path",
          "name" : "templateId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "query",
          "name" : "limit",
          "required" : false,
          "schema" : {
            "type" : "integer",
            "format" : "int32"
          }
        }, {
          "in" : "query",
          "name" : "offset",
          "required" : false,
          "schema" : {
            "type" : "integer",
            "format" : "int32"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "type" : "array",
                  "items" : {
                    "$ref" : "#/components/schemas/AccountTemplateRevisionSummaryDTO"
                  }
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "List revision history for a template, newest first",
        "tags" : [ "Account Template API" ]
      }
    },
    "/rest/api/v1/projects/{projectId}/templates/{templateId}/revisions/{revision}" : {
      "get" : {
        "operationId" : "getAccountTemplateRevision",
        "parameters" : [ {
          "in" : "path",
          "name" : "projectId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "path",
          "name" : "templateId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "path",
          "name" : "revision",
          "required" : true,
          "schema" : {
            "type" : "integer",
            "format" : "int64"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/AccountTemplateRevisionDTO"
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Get the payload of one historical revision",
        "tags" : [ "Account Template API" ]
      }
    },
    "/rest/api/v1/projects/{projectId}/traders" : {
      "get" : {
        "description" : "Returns a list of all trader features with ACTIVE status from all accounts in the specified project",
        "operationId" : "getProjectTraders",
        "parameters" : [ {
          "in" : "path",
          "name" : "projectId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "type" : "array",
                  "items" : {
                    "$ref" : "#/components/schemas/FeatureTraderDTO"
                  }
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Get all approved traders configured in the project",
        "tags" : [ "Project API" ]
      }
    },
    "/rest/api/v1/projects/{projectId}/transactions" : {
      "get" : {
        "operationId" : "getProjectTransactions",
        "parameters" : [ {
          "in" : "path",
          "name" : "projectId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "type" : "array",
                  "items" : {
                    "$ref" : "#/components/schemas/TransactionDTO"
                  }
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Get project transactions",
        "tags" : [ "Project API" ]
      }
    },
    "/rest/api/v1/projects/{projectId}/whitelabel/dns" : {
      "get" : {
        "description" : "Reports every required CNAME / TXT record individually so a failed [CHECK_DNS] can be diagnosed. Once the WhiteLabel exists its persisted subdomain is used and the parameter is ignored.",
        "operationId" : "checkWhiteLabelDns",
        "parameters" : [ {
          "in" : "path",
          "name" : "projectId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "description" : "Subdomain to verify, required before the WhiteLabel is created",
          "example" : "trade.example.com",
          "in" : "query",
          "name" : "subdomain",
          "required" : false,
          "schema" : {
            "type" : "string"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/DnsCheckResultDTO"
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Verify the DNS records of a WhiteLabel domain",
        "tags" : [ "Project API" ]
      }
    },
    "/rest/api/v1/reports/performance" : {
      "post" : {
        "operationId" : "createReportPerformance",
        "requestBody" : {
          "content" : {
            "application/json" : {
              "schema" : {
                "$ref" : "#/components/schemas/ReportPerformanceParametersDTO"
              }
            }
          },
          "required" : true
        },
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/ReportPerformanceDTO"
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Create a performance report ",
        "tags" : [ "Report API" ]
      }
    },
    "/rest/api/v1/signals/{signalProviderId}/accounts" : {
      "get" : {
        "operationId" : "getSignalFollowerAccounts",
        "parameters" : [ {
          "in" : "path",
          "name" : "signalProviderId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "type" : "array",
                  "items" : {
                    "$ref" : "#/components/schemas/AccountDTO"
                  }
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Get all signal follower accounts",
        "tags" : [ "Signal API" ]
      }
    },
    "/rest/api/v1/signals/{signalProviderId}/accounts/{accountId}/actions/closeAllPositions" : {
      "post" : {
        "operationId" : "closeSignalFollowerAllPositions",
        "parameters" : [ {
          "in" : "path",
          "name" : "signalProviderId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "path",
          "name" : "accountId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "responses" : {
          "204" : {
            "description" : "No Content"
          }
        },
        "summary" : "Close all signal follower account positions",
        "tags" : [ "Signal API" ]
      }
    },
    "/rest/api/v1/signals/{signalProviderId}/accounts/{accountId}/auditLogs" : {
      "get" : {
        "description" : "Retrieves audit logs for all API modifications made to a specific signal follower account.",
        "operationId" : "getSignalFollowerAccountAuditLogs",
        "parameters" : [ {
          "in" : "path",
          "name" : "signalProviderId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "path",
          "name" : "accountId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "description" : "Maximum number of logs to return",
          "in" : "query",
          "name" : "limit",
          "required" : false,
          "schema" : {
            "type" : "integer",
            "format" : "int32"
          }
        }, {
          "description" : "Number of logs to skip for pagination",
          "in" : "query",
          "name" : "offset",
          "required" : false,
          "schema" : {
            "type" : "integer",
            "format" : "int32"
          }
        }, {
          "description" : "Start date filter (ISO-8601 format)",
          "in" : "query",
          "name" : "startDate",
          "required" : false,
          "schema" : {
            "type" : "string"
          }
        }, {
          "description" : "End date filter (ISO-8601 format)",
          "in" : "query",
          "name" : "endDate",
          "required" : false,
          "schema" : {
            "type" : "string"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "type" : "array",
                  "items" : {
                    "$ref" : "#/components/schemas/AuditLogDTO"
                  }
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Get signal follower account audit logs",
        "tags" : [ "Signal API" ]
      }
    },
    "/rest/api/v1/signals/{signalProviderId}/accounts/{accountId}/followerFeature" : {
      "delete" : {
        "description" : "Deletes the signal follower feature. This is only possible if there are no open positions on the signal provider's source account.",
        "operationId" : "removeFollower",
        "parameters" : [ {
          "in" : "path",
          "name" : "signalProviderId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "path",
          "name" : "accountId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "responses" : {
          "204" : {
            "description" : "No Content"
          }
        },
        "summary" : "Remove a follower from the signal provider",
        "tags" : [ "Signal API" ]
      },
      "get" : {
        "operationId" : "getFollowerFeature",
        "parameters" : [ {
          "in" : "path",
          "name" : "signalProviderId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "path",
          "name" : "accountId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/FeatureDTO"
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Get follower feature",
        "tags" : [ "Signal API" ]
      },
      "put" : {
        "operationId" : "updateFollowerFeature",
        "parameters" : [ {
          "in" : "path",
          "name" : "signalProviderId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "path",
          "name" : "accountId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "requestBody" : {
          "content" : {
            "application/json" : {
              "schema" : {
                "$ref" : "#/components/schemas/FeatureDTO"
              }
            }
          },
          "required" : true
        },
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/FeatureDTO"
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Update follower feature",
        "tags" : [ "Signal API" ]
      }
    },
    "/rest/api/v1/signals/{signalProviderId}/accounts/{accountId}/history/positions" : {
      "get" : {
        "description" : "The history is not updated in real-time. There may be a delay of up to 3 minutes",
        "operationId" : "getSignalFollowerAccountHistoryPositions",
        "parameters" : [ {
          "in" : "path",
          "name" : "signalProviderId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "path",
          "name" : "accountId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "description" : "ISO 8601",
          "example" : "2023-07-28T14:32:07+07:00",
          "in" : "query",
          "name" : "start",
          "required" : true,
          "schema" : {
            "type" : "string"
          }
        }, {
          "description" : "ISO 8601",
          "example" : "2023-12-25T16:05:06+07:00",
          "in" : "query",
          "name" : "stop",
          "required" : true,
          "schema" : {
            "type" : "string"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "type" : "array",
                  "items" : {
                    "$ref" : "#/components/schemas/PositionDTO"
                  }
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Get signal follower account history positions",
        "tags" : [ "Signal API" ]
      }
    },
    "/rest/api/v1/signals/{signalProviderId}/accounts/{accountId}/logs" : {
      "get" : {
        "operationId" : "getSignalFollowerAccountLogs",
        "parameters" : [ {
          "in" : "path",
          "name" : "signalProviderId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "path",
          "name" : "accountId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "description" : "Get the last logs: e.g. 100 means the last 100 logs",
          "example" : 100,
          "in" : "query",
          "name" : "limit",
          "required" : false,
          "schema" : {
            "type" : "integer",
            "format" : "int32"
          }
        }, {
          "description" : "You can set an offset. Offset 100 means 101-200",
          "example" : 0,
          "in" : "query",
          "name" : "offset",
          "required" : false,
          "schema" : {
            "type" : "integer",
            "format" : "int32"
          }
        }, {
          "description" : "ISO 8601",
          "example" : "2023-07-28T14:32:07+07:00",
          "in" : "query",
          "name" : "start",
          "required" : false,
          "schema" : {
            "type" : "string"
          }
        }, {
          "description" : "ISO 8601",
          "example" : "2023-12-25T16:05:06+07:00",
          "in" : "query",
          "name" : "stop",
          "required" : false,
          "schema" : {
            "type" : "string"
          }
        }, {
          "description" : "Filter logs by log level type ID. If you choose 3 = Info, then all logs with a lower level are returned. The levels are: 1 = Error, 2 = Warning, 3 = Info.",
          "example" : 1,
          "in" : "query",
          "name" : "logTypeId",
          "required" : false,
          "schema" : {
            "type" : "integer",
            "format" : "int32"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "type" : "array",
                  "items" : {
                    "$ref" : "#/components/schemas/LogDTO"
                  }
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Get signal follower account logs",
        "tags" : [ "Signal API" ]
      }
    },
    "/rest/api/v1/signals/{signalProviderId}/accounts/{accountId}/performanceMetrics" : {
      "get" : {
        "operationId" : "getSignalFollowerAccountPerformanceMetrics",
        "parameters" : [ {
          "in" : "path",
          "name" : "signalProviderId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "path",
          "name" : "accountId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/PerformanceMetricsDTO"
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Get signal follower account performance metrics",
        "tags" : [ "Signal API" ]
      }
    },
    "/rest/api/v1/signals/{signalProviderId}/accounts/{accountId}/positions" : {
      "get" : {
        "operationId" : "getSignalFollowerAccountPositions",
        "parameters" : [ {
          "in" : "path",
          "name" : "signalProviderId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "path",
          "name" : "accountId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "type" : "array",
                  "items" : {
                    "$ref" : "#/components/schemas/PositionDTO"
                  }
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Get signal follower account positions",
        "tags" : [ "Signal API" ]
      }
    },
    "/rest/api/v1/signals/{signalProviderId}/accounts/{accountId}/positions/{positionId}" : {
      "delete" : {
        "operationId" : "closeSignalFollowerPosition",
        "parameters" : [ {
          "in" : "path",
          "name" : "signalProviderId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "path",
          "name" : "accountId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "path",
          "name" : "positionId",
          "required" : true,
          "schema" : {
            "type" : "string"
          }
        } ],
        "responses" : {
          "204" : {
            "description" : "No Content"
          }
        },
        "summary" : "Close an signal follower account position",
        "tags" : [ "Signal API" ]
      }
    },
    "/rest/api/v1/signals/{signalProviderId}/accounts/{accountId}/symbols" : {
      "get" : {
        "operationId" : "getSignalSymbols",
        "parameters" : [ {
          "in" : "path",
          "name" : "signalProviderId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "path",
          "name" : "accountId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "type" : "array",
                  "items" : {
                    "$ref" : "#/components/schemas/SymbolDTO"
                  }
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Get signal follower account symbols",
        "tags" : [ "Signal API" ]
      }
    },
    "/rest/api/v1/signals/{signalProviderId}/closeAllPositions" : {
      "post" : {
        "operationId" : "closeAllPositionsInAllFollowerAccounts",
        "parameters" : [ {
          "in" : "path",
          "name" : "signalProviderId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "responses" : {
          "204" : {
            "description" : "No Content"
          }
        },
        "summary" : "Close all open positions in all accounts (followers)",
        "tags" : [ "Signal API" ]
      }
    },
    "/rest/api/v1/signals/{signalProviderId}/earnings" : {
      "get" : {
        "description" : "Returns earnings breakdown for a signal provider including gross/net amounts, per-follower charge details, and monthly breakdown. Includes PAID, OPEN, and VOID invoices. If month and year are not provided, returns all-time earnings.",
        "operationId" : "getSignalProviderEarnings",
        "parameters" : [ {
          "in" : "path",
          "name" : "signalProviderId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "description" : "Month (1-12). If omitted, returns all months.",
          "in" : "query",
          "name" : "month",
          "required" : false,
          "schema" : {
            "type" : "integer",
            "format" : "int32"
          }
        }, {
          "description" : "Year (e.g. 2026). If omitted, returns all years.",
          "in" : "query",
          "name" : "year",
          "required" : false,
          "schema" : {
            "type" : "integer",
            "format" : "int32"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/SignalProviderEarningsDTO"
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Get signal provider earnings breakdown",
        "tags" : [ "Signal API" ]
      }
    },
    "/rest/api/v1/signals/{signalProviderId}/followerCosts" : {
      "get" : {
        "description" : "Returns what the signal provider paid for each of its followers, per month. Only applies when the signal provider covers follower costs; otherwise the result is empty. Followers that cost nothing, for example because they exceed the per-project cap, are not listed. If month and year are not provided, all months are returned.",
        "operationId" : "getSignalProviderFollowerCosts",
        "parameters" : [ {
          "in" : "path",
          "name" : "signalProviderId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "description" : "Month (1-12). If omitted, returns all months.",
          "in" : "query",
          "name" : "month",
          "required" : false,
          "schema" : {
            "type" : "integer",
            "format" : "int32"
          }
        }, {
          "description" : "Year (e.g. 2026). If omitted, returns all years.",
          "in" : "query",
          "name" : "year",
          "required" : false,
          "schema" : {
            "type" : "integer",
            "format" : "int32"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/SignalFollowerCostDTO"
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Get covered follower costs",
        "tags" : [ "Signal API" ]
      }
    },
    "/rest/api/v1/signals/{signalProviderId}/history/positions" : {
      "get" : {
        "operationId" : "getSignalProviderHistoryPositions",
        "parameters" : [ {
          "in" : "path",
          "name" : "signalProviderId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "description" : "ISO 8601",
          "example" : "2023-07-28T14:32:07+07:00",
          "in" : "query",
          "name" : "start",
          "required" : true,
          "schema" : {
            "type" : "string"
          }
        }, {
          "description" : "ISO 8601",
          "example" : "2023-12-25T16:05:06+07:00",
          "in" : "query",
          "name" : "stop",
          "required" : true,
          "schema" : {
            "type" : "string"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "type" : "array",
                  "items" : {
                    "$ref" : "#/components/schemas/PositionDTO"
                  }
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Get signal provider historical positions",
        "tags" : [ "Signal API" ]
      }
    },
    "/rest/api/v1/types/accountTypes" : {
      "get" : {
        "operationId" : "getAccountTypes",
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "type" : "array",
                  "items" : {
                    "$ref" : "#/components/schemas/AccountTypeDTO"
                  }
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Get account type enum",
        "tags" : [ "Type API" ]
      }
    },
    "/rest/api/v1/types/copierSettings/availableFields" : {
      "get" : {
        "operationId" : "getAvailableCopierSettingFields",
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "type" : "array",
                  "items" : {
                    "$ref" : "#/components/schemas/CopierSettingFieldDTO"
                  }
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Get available copier setting fields",
        "tags" : [ "Type API" ]
      }
    },
    "/rest/api/v1/types/currencyTypes" : {
      "get" : {
        "operationId" : "getCurrencyTypes",
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "type" : "array",
                  "items" : {
                    "$ref" : "#/components/schemas/CurrencyTypeDTO"
                  }
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Get currency type enum",
        "tags" : [ "Type API" ]
      }
    },
    "/rest/api/v1/types/featureTypes" : {
      "get" : {
        "operationId" : "getFeatureTypes",
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "type" : "array",
                  "items" : {
                    "$ref" : "#/components/schemas/FeatureTypeDTO"
                  }
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Get feature type enum",
        "tags" : [ "Type API" ]
      }
    },
    "/rest/api/v1/types/logTypes" : {
      "get" : {
        "operationId" : "getLogTypes",
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "type" : "array",
                  "items" : {
                    "$ref" : "#/components/schemas/LogTypeDTO"
                  }
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Get log type enum",
        "tags" : [ "Type API" ]
      }
    },
    "/rest/api/v1/types/notificationCategoryTypes" : {
      "get" : {
        "operationId" : "getNotificationCategoryTypes",
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "type" : "array",
                  "items" : {
                    "$ref" : "#/components/schemas/NotificationCategoryTypeDTO"
                  }
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Get notification category type enum",
        "tags" : [ "Type API" ]
      }
    },
    "/rest/api/v1/types/proxyRegions" : {
      "get" : {
        "operationId" : "getProxyRegions",
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "type" : "array",
                  "items" : {
                    "$ref" : "#/components/schemas/ProxyRegionDTO"
                  }
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Get proxy region enum",
        "tags" : [ "Type API" ]
      }
    },
    "/rest/api/v1/types/regions" : {
      "get" : {
        "operationId" : "getRegions",
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "type" : "array",
                  "items" : {
                    "$ref" : "#/components/schemas/RegionDTO"
                  }
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Get region enum",
        "tags" : [ "Type API" ]
      }
    },
    "/rest/api/v1/types/riskTypes" : {
      "get" : {
        "operationId" : "getRiskTypes",
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "type" : "array",
                  "items" : {
                    "$ref" : "#/components/schemas/RiskTypeDTO"
                  }
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Get risk type enum",
        "tags" : [ "Type API" ]
      }
    },
    "/rest/api/v1/types/scaleTypes" : {
      "get" : {
        "operationId" : "getScaleTypes",
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "type" : "array",
                  "items" : {
                    "$ref" : "#/components/schemas/ScaleTypeDTO"
                  }
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Get scale type enum",
        "tags" : [ "Type API" ]
      }
    },
    "/rest/api/v1/webhooks/tradingview/accounts/{accountId}" : {
      "post" : {
        "description" : "Receives webhook alerts from TradingView and queues them for asynchronous processing. Returns 202 Accepted with a requestId that can be used to check status.",
        "operationId" : "handleWebhook",
        "parameters" : [ {
          "in" : "path",
          "name" : "accountId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        } ],
        "requestBody" : {
          "content" : {
            "application/json" : {
              "schema" : {
                "type" : "string"
              }
            },
            "text/plain" : {
              "schema" : {
                "type" : "string"
              }
            }
          },
          "required" : true
        },
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/TradingViewWebhookResponseDTO"
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Handle TradingView webhook",
        "tags" : [ "TradingView Webhook API" ]
      }
    },
    "/rest/api/v1/webhooks/tradingview/accounts/{accountId}/data" : {
      "get" : {
        "description" : "Retrieve data stored via the 'store' webhook action.",
        "operationId" : "getStoredData",
        "parameters" : [ {
          "in" : "path",
          "name" : "accountId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "query",
          "name" : "limit",
          "required" : false,
          "schema" : {
            "type" : "integer",
            "format" : "int32",
            "default" : 50
          }
        }, {
          "in" : "query",
          "name" : "skip",
          "required" : false,
          "schema" : {
            "type" : "integer",
            "format" : "int32",
            "default" : 0
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "type" : "object"
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "List stored TradingView data",
        "tags" : [ "TradingView Webhook API" ]
      }
    },
    "/rest/api/v1/webhooks/tradingview/accounts/{accountId}/data/{dataId}" : {
      "delete" : {
        "description" : "Delete specific stored data by ID.",
        "operationId" : "deleteStoredData",
        "parameters" : [ {
          "in" : "path",
          "name" : "accountId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "path",
          "name" : "dataId",
          "required" : true,
          "schema" : {
            "type" : "string"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "type" : "object"
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Delete stored data",
        "tags" : [ "TradingView Webhook API" ]
      },
      "get" : {
        "description" : "Retrieve specific stored data by ID.",
        "operationId" : "getStoredDataById",
        "parameters" : [ {
          "in" : "path",
          "name" : "accountId",
          "required" : true,
          "schema" : {
            "type" : "string",
            "format" : "uuid"
          }
        }, {
          "in" : "path",
          "name" : "dataId",
          "required" : true,
          "schema" : {
            "type" : "string"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "type" : "object"
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Get specific stored data",
        "tags" : [ "TradingView Webhook API" ]
      }
    },
    "/rest/api/v1/webhooks/tradingview/requests/{requestId}/status" : {
      "get" : {
        "description" : "Check the processing status of a queued webhook request.",
        "operationId" : "getRequestStatus",
        "parameters" : [ {
          "in" : "path",
          "name" : "requestId",
          "required" : true,
          "schema" : {
            "type" : "string"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/TradingViewWebhookResponseDTO"
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Get webhook request status",
        "tags" : [ "TradingView Webhook API" ]
      }
    }
  },
  "components" : {
    "schemas" : {
      "AccountDTO" : {
        "required" : [ "loginAccountPassword", "loginServer", "region", "type" ],
        "type" : "object",
        "properties" : {
          "accountInformation" : {
            "$ref" : "#/components/schemas/AccountInformationDTO"
          },
          "alias" : {
            "maxLength" : 255,
            "minLength" : 0,
            "type" : "string"
          },
          "callbackUrl" : {
            "type" : "string",
            "description" : "Optional callback URL for async account creation. When provided, the API returns 202 Accepted immediately and POSTs the result (AccountDTO or error) to this URL once processing completes. Only 1 account creation per project is processed at a time; additional requests are queued.",
            "example" : "https://example.com/webhook/account-created"
          },
          "closeUnmanagedPositions" : {
            "type" : "boolean",
            "description" : "When enabled, any open positions on the account that were originally opened by MetaCopier but are no longer managed, due to technical issues, will be automatically closed. However, this mechanism can occasionally result in false positives. If disabled, such unmanaged positions will remain open, and a notification will be sent to the notification center or to Telegram (if configured). In this case, manual intervention is required. We recommend keeping this option disabled to avoid accidental closures.",
            "example" : false,
            "default" : false
          },
          "created" : {
            "type" : "string",
            "description" : "ISO 8601",
            "format" : "date-time",
            "readOnly" : true
          },
          "ctraderClientId" : {
            "type" : "string"
          },
          "ctraderClientSecret" : {
            "type" : "string"
          },
          "dedicatedIp" : {
            "$ref" : "#/components/schemas/FeatureDedicatedIpDTO"
          },
          "deleted" : {
            "type" : "string",
            "description" : "ISO 8601",
            "format" : "date-time",
            "readOnly" : true
          },
          "failIfAccountExistsInProject" : {
            "type" : "boolean",
            "description" : "If true, the create-account call fails when the account already exists in the project"
          },
          "hasActiveCopiers" : {
            "type" : "boolean",
            "description" : "Indicates whether this account has any active copiers. Returns true if at least one copier has active=true, false otherwise.",
            "readOnly" : true
          },
          "hasDisabledCopiers" : {
            "type" : "boolean",
            "description" : "Indicates whether this account has any disabled only copiers. Returns true if at least one copier has active=false, false otherwise.",
            "readOnly" : true
          },
          "hasMonitorOnlyCopiers" : {
            "type" : "boolean",
            "description" : "Indicates whether this account has any monitor-only copiers. Returns true if at least one copier is in monitor only mode (monitoring without copying trades), false otherwise.",
            "readOnly" : true
          },
          "id" : {
            "type" : "string",
            "format" : "uuid",
            "readOnly" : true
          },
          "labels" : {
            "type" : "array",
            "description" : "Set labels for your account. If null, this field will not add, update, or delete anything. To delete all labels, set this field to an empty list.",
            "items" : {
              "type" : "string",
              "description" : "Set labels for your account. If null, this field will not add, update, or delete anything. To delete all labels, set this field to an empty list."
            }
          },
          "loginAccountNumber" : {
            "maxLength" : 255,
            "minLength" : 0,
            "type" : "string",
            "description" : "For Binance, Bybit, Bitget, BloFin, OKX, Tradovate and Alpaca leave it empty"
          },
          "loginAccountPassword" : {
            "maxLength" : 2000,
            "minLength" : 0,
            "type" : "string",
            "description" : "For cTrader 'token|refreshToken'. For TradeStation 'token|refreshToken'. For Binance and Bybit 'apiKey|secretKey'. For Bitget, BloFin and OKX 'apiKey|secretKey|passphrase'. For Tradovate and Alpaca 'apiKey|secretKey'. Only fill this field if you want to update the password or at account creation. When updating the account, you can leave this field empty \"\" - you don't have to send the password every time."
          },
          "loginServer" : {
            "maxLength" : 255,
            "minLength" : 0,
            "type" : "string",
            "description" : "Enter the server address, for example, ICMarketsSC-MT5-4 for MetaTrader, or the URL such as dxtrade.instantfunding.io for DXtrade or mtr-demo-prod.match-trader.com MatchTrader. For CTrader, live.ctraderapi.com:5035 or demo.ctraderapi.com:5035. For TradeLocker, live.tradelocker.com or demo.tradelocker.com. For Binance, Bybit, Bitget, BloFin and OKX 'live', 'testnet' or 'demo'. For TradeStation 'sim' or 'live'. For Tradovate 'demo' or 'live'. For Alpaca 'paper' or 'live'."
          },
          "myHomeIp" : {
            "$ref" : "#/components/schemas/FeatureMyHomeIpDTO"
          },
          "nativeMode" : {
            "type" : "boolean",
            "description" : "Indicates whether the integration runs in native mode (applies only to MetaTrader 4/5 connectors). If true, the solution operates via the official MetaTrader terminal (native). If false, it connects directly to the server without using the terminal (non-native). Non-native mode can achieve lower latency for high-frequency trading (HFT) strategies, but for 99% of typical use cases native mode is sufficiently fast. If the non-native mode fails or becomes unavailable, the system will automatically fall back to native mode. For all other connectors, the integration is always native.",
            "example" : false,
            "default" : false
          },
          "propFirm" : {
            "type" : "boolean",
            "description" : "Indicates whether this is a prop firm account.",
            "example" : false,
            "default" : false
          },
          "region" : {
            "$ref" : "#/components/schemas/RegionDTO"
          },
          "skipCredentialCheck" : {
            "type" : "boolean",
            "description" : "When set to true, skips credential validation during account creation. Use with caution, the account will be created without verifying login credentials.",
            "example" : false,
            "default" : false
          },
          "status" : {
            "$ref" : "#/components/schemas/AccountStatusDTO"
          },
          "statusMessage" : {
            "type" : "string",
            "readOnly" : true
          },
          "tradingDisabled" : {
            "type" : "boolean",
            "description" : "When enabled, puts the account in read-only mode, preventing any new trades from being opened or existing trades from being modified or closed. Use this when you want to use the account as a read-only master.",
            "example" : false,
            "default" : false
          },
          "type" : {
            "$ref" : "#/components/schemas/AccountTypeDTO"
          }
        }
      },
      "AccountInformationDTO" : {
        "type" : "object",
        "properties" : {
          "accountDuplicationInProjectDetected" : {
            "type" : "boolean",
            "description" : "Indicates whether an account duplication has been detected in this project",
            "readOnly" : true
          },
          "accountMode" : {
            "type" : "string",
            "description" : "Account margin mode: HEDGING, NETTING, or EXCHANGE",
            "readOnly" : true,
            "enum" : [ "NETTING", "HEDGING", "EXCHANGE" ]
          },
          "avgDrawdown" : {
            "type" : "number",
            "description" : "Average drawdown percentage during trading period (%)",
            "readOnly" : true
          },
          "balance" : {
            "type" : "number",
            "readOnly" : true
          },
          "brokeTimeOffsetToUtc" : {
            "type" : "integer",
            "format" : "int32",
            "readOnly" : true
          },
          "configuredProxy" : {
            "$ref" : "#/components/schemas/ProxyDTO"
          },
          "connected" : {
            "type" : "boolean",
            "readOnly" : true
          },
          "credit" : {
            "type" : "number",
            "description" : "Only for MT4/MT5",
            "readOnly" : true
          },
          "currency" : {
            "type" : "string",
            "readOnly" : true
          },
          "drawdown" : {
            "type" : "number",
            "description" : "The drawdown percentage of the account",
            "readOnly" : true
          },
          "environment" : {
            "type" : "string",
            "description" : "Indicates the account environment: LIVE or DEMO. Testnet/sim/paper environments are reported as DEMO. Null if detection is not supported for this broker type",
            "readOnly" : true,
            "enum" : [ "LIVE", "DEMO" ]
          },
          "equity" : {
            "type" : "number",
            "readOnly" : true
          },
          "fallbackMode" : {
            "type" : "boolean",
            "description" : "The fallback mode is active (This means something is not working properly, and the system switches to the fallback mode)",
            "readOnly" : true
          },
          "freeMargin" : {
            "type" : "number",
            "readOnly" : true
          },
          "historyDeactivated" : {
            "type" : "boolean",
            "description" : "Indicates if history fetching has been deactivated for this account",
            "readOnly" : true
          },
          "isHyperactive" : {
            "type" : "boolean",
            "description" : "Indicates if the account is performing excessive trading activity. When true, history fetching may be disabled to reduce broker load",
            "readOnly" : true
          },
          "isInvestorPassword" : {
            "type" : "boolean",
            "readOnly" : true
          },
          "isNative" : {
            "type" : "boolean",
            "description" : "Indicates if the account is using native mode",
            "readOnly" : true
          },
          "latencyInMs" : {
            "type" : "integer",
            "description" : "Latency to the broker's access server",
            "format" : "int64",
            "readOnly" : true
          },
          "leverage" : {
            "type" : "integer",
            "format" : "int32",
            "readOnly" : true
          },
          "maxDrawdown" : {
            "type" : "number",
            "description" : "Maximum drawdown percentage - worst peak-to-trough decline (%)",
            "readOnly" : true
          },
          "missingSymbolMappings" : {
            "type" : "array",
            "description" : "List of missing symbol mappings for this account",
            "readOnly" : true,
            "items" : {
              "$ref" : "#/components/schemas/MissingSymbolMappingDTO"
            }
          },
          "openPositions" : {
            "type" : "boolean",
            "description" : "True if there is an open position (buy or sell)",
            "readOnly" : true
          },
          "openPositionsCount" : {
            "type" : "integer",
            "description" : "Number of open positions (buy or sell)",
            "format" : "int32",
            "readOnly" : true
          },
          "pendingApprovals" : {
            "type" : "array",
            "readOnly" : true,
            "items" : {
              "$ref" : "#/components/schemas/ApprovalDTO"
            }
          },
          "pendingOrders" : {
            "type" : "boolean",
            "description" : "True if there is a pending order (buy limit, sell limit, etc",
            "readOnly" : true
          },
          "pendingOrdersCount" : {
            "type" : "integer",
            "description" : "Number of pending orders (buy limit, sell limit, etc)",
            "format" : "int32",
            "readOnly" : true
          },
          "positionMismatch" : {
            "type" : "boolean",
            "description" : "Indicates that the open positions between the master and slave accounts are not synchronized due to failed open or close operations",
            "readOnly" : true
          },
          "profitTargetsStatus" : {
            "type" : "array",
            "readOnly" : true,
            "items" : {
              "$ref" : "#/components/schemas/ProfitTargetStatusDTO"
            }
          },
          "profitThisMonth" : {
            "type" : "number",
            "readOnly" : true
          },
          "profitThisWeek" : {
            "type" : "number",
            "readOnly" : true
          },
          "profitToday" : {
            "type" : "number",
            "readOnly" : true
          },
          "proxy" : {
            "$ref" : "#/components/schemas/ProxyDTO"
          },
          "riskLimitsStatus" : {
            "type" : "array",
            "readOnly" : true,
            "items" : {
              "$ref" : "#/components/schemas/RiskLimitStatusDTO"
            }
          },
          "status" : {
            "type" : "string",
            "readOnly" : true
          },
          "unrealizedProfit" : {
            "type" : "number",
            "readOnly" : true
          },
          "usedMargin" : {
            "type" : "number",
            "readOnly" : true
          },
          "walletBalances" : {
            "type" : "array",
            "readOnly" : true,
            "items" : {
              "$ref" : "#/components/schemas/WalletDTO"
            }
          },
          "wrongCredentials" : {
            "type" : "boolean",
            "readOnly" : true
          }
        },
        "description" : "Is synced every minute",
        "readOnly" : true
      },
      "AccountPerformanceDTO" : {
        "type" : "object",
        "properties" : {
          "accountId" : {
            "type" : "string",
            "description" : "Unique identifier of the account.",
            "format" : "uuid",
            "readOnly" : true
          },
          "balance" : {
            "type" : "number",
            "description" : "Account's balance as recorded at 00:00 UTC.",
            "readOnly" : true
          },
          "currency" : {
            "type" : "string",
            "description" : "Currency in which the account balance and equity are denominated.",
            "readOnly" : true
          },
          "currentDrawdown" : {
            "type" : "number",
            "description" : "Drawdown at 00:00 UTC, indicating the peak-to-trough loss as of the recorded time.",
            "readOnly" : true
          },
          "customerEmail" : {
            "type" : "string",
            "description" : "Customer's email",
            "readOnly" : true
          },
          "date" : {
            "type" : "string",
            "description" : "Date of the performance record, reflecting the 00:00 UTC data capture time.",
            "format" : "date-time",
            "readOnly" : true
          },
          "deleted" : {
            "type" : "boolean",
            "description" : "Indicates whether the account is marked as deleted.",
            "readOnly" : true
          },
          "equity" : {
            "type" : "number",
            "description" : "Account's equity as recorded at 00:00 UTC, reflecting current unrealized profits/losses at that time.",
            "readOnly" : true
          },
          "history" : {
            "type" : "array",
            "description" : "List of historical positions relevant to the account's performance as of the recorded date.",
            "readOnly" : true,
            "items" : {
              "$ref" : "#/components/schemas/PositionDTO"
            }
          },
          "netProfits" : {
            "type" : "object",
            "additionalProperties" : {
              "type" : "object",
              "additionalProperties" : {
                "type" : "number",
                "description" : "Monthly net profit data, where the key is the month (as an integer starting at 1 for January) and the value is the net profit earned in that month.",
                "readOnly" : true
              },
              "description" : "Monthly net profit data, where the key is the month (as an integer starting at 1 for January) and the value is the net profit earned in that month.",
              "readOnly" : true
            },
            "description" : "Monthly net profit data, where the key is the month (as an integer starting at 1 for January) and the value is the net profit earned in that month.",
            "readOnly" : true
          }
        },
        "description" : "Contains daily performance metrics for an account, updated at 00:00 UTC.",
        "readOnly" : true
      },
      "AccountStatusDTO" : {
        "required" : [ "id" ],
        "type" : "object",
        "properties" : {
          "id" : {
            "type" : "integer",
            "format" : "int32",
            "readOnly" : true
          },
          "name" : {
            "type" : "string",
            "readOnly" : true
          }
        },
        "description" : "Read only",
        "readOnly" : true
      },
      "AccountTemplateDTO" : {
        "required" : [ "name", "payload", "projectId" ],
        "type" : "object",
        "properties" : {
          "attentionReason" : {
            "type" : "string",
            "description" : "Short human-readable explanation of why needsAttention is set.",
            "readOnly" : true
          },
          "blocks" : {
            "type" : "array",
            "description" : "Content blocks this template carries.",
            "items" : {
              "type" : "string",
              "description" : "Account-Template content block name. One of: riskLimits, copiers, accountFeatures, copierFeatures.",
              "enum" : [ "riskLimits", "copiers", "accountFeatures", "copierFeatures" ]
            }
          },
          "compatibility" : {
            "type" : "string",
            "description" : "Payload compatibility marker: CURRENT, AUTO_MIGRATED, or REVIEW_NEEDED.",
            "readOnly" : true
          },
          "created" : {
            "type" : "string",
            "format" : "date-time",
            "readOnly" : true
          },
          "createdBy" : {
            "type" : "string",
            "readOnly" : true
          },
          "description" : {
            "maxLength" : 4096,
            "minLength" : 0,
            "type" : "string"
          },
          "expectedRevision" : {
            "type" : "integer",
            "description" : "Required on update. The server compares this against the current revision and returns HTTP 409 on mismatch.",
            "format" : "int64"
          },
          "id" : {
            "type" : "string",
            "format" : "uuid",
            "readOnly" : true
          },
          "linkedCount" : {
            "type" : "integer",
            "description" : "Number of accounts currently linked to this template.",
            "format" : "int32",
            "readOnly" : true
          },
          "metadataUpdated" : {
            "type" : "string",
            "format" : "date-time",
            "readOnly" : true
          },
          "name" : {
            "maxLength" : 255,
            "minLength" : 0,
            "type" : "string",
            "description" : "Display name. Must be unique per project (case-insensitive)."
          },
          "needsAttention" : {
            "type" : "boolean",
            "description" : "True if this template references resources that no longer exist (for example, a deleted source account or strategy).",
            "readOnly" : true
          },
          "payload" : {
            "$ref" : "#/components/schemas/JsonNode"
          },
          "projectId" : {
            "type" : "string",
            "description" : "Project this template belongs to. Set from the URL path; any value in the body is ignored.",
            "format" : "uuid",
            "readOnly" : true
          },
          "referenceAccountId" : {
            "type" : "string",
            "description" : "Account that was used as the source when this template was created. Helps clients resolve symbol references in the payload.",
            "format" : "uuid"
          },
          "revision" : {
            "type" : "integer",
            "description" : "Current revision number. Bumped only when the payload actually changes.",
            "format" : "int64",
            "readOnly" : true
          },
          "updated" : {
            "type" : "string",
            "format" : "date-time",
            "readOnly" : true
          },
          "updatedBy" : {
            "type" : "string",
            "readOnly" : true
          }
        }
      },
      "AccountTemplateRevisionDTO" : {
        "type" : "object",
        "properties" : {
          "compatibility" : {
            "type" : "string"
          },
          "payload" : {
            "$ref" : "#/components/schemas/JsonNode"
          },
          "revision" : {
            "type" : "integer",
            "format" : "int64"
          },
          "updated" : {
            "type" : "string",
            "format" : "date-time"
          },
          "updatedBy" : {
            "type" : "string"
          }
        },
        "description" : "Full payload snapshot of one stored template revision."
      },
      "AccountTemplateRevisionSummaryDTO" : {
        "type" : "object",
        "properties" : {
          "revision" : {
            "type" : "integer",
            "format" : "int64"
          },
          "updated" : {
            "type" : "string",
            "format" : "date-time"
          },
          "updatedBy" : {
            "type" : "string"
          }
        },
        "description" : "Compact summary of one stored template revision. Newest first."
      },
      "AccountTemplateSummaryDTO" : {
        "type" : "object",
        "properties" : {
          "attentionReason" : {
            "type" : "string"
          },
          "blocks" : {
            "type" : "array",
            "items" : {
              "type" : "string",
              "description" : "Account-Template content block name. One of: riskLimits, copiers, accountFeatures, copierFeatures.",
              "enum" : [ "riskLimits", "copiers", "accountFeatures", "copierFeatures" ]
            }
          },
          "compatibility" : {
            "type" : "string"
          },
          "description" : {
            "type" : "string"
          },
          "id" : {
            "type" : "string",
            "format" : "uuid",
            "readOnly" : true
          },
          "linkedCount" : {
            "type" : "integer",
            "format" : "int32"
          },
          "name" : {
            "type" : "string"
          },
          "needsAttention" : {
            "type" : "boolean"
          },
          "revision" : {
            "type" : "integer",
            "format" : "int64"
          },
          "updated" : {
            "type" : "string",
            "format" : "date-time"
          },
          "updatedBy" : {
            "type" : "string"
          }
        },
        "description" : "Compact summary of an account template for list views. The full payload is available via the single-template endpoint."
      },
      "AccountTypeDTO" : {
        "required" : [ "id" ],
        "type" : "object",
        "properties" : {
          "id" : {
            "type" : "integer",
            "format" : "int32"
          },
          "name" : {
            "type" : "string",
            "readOnly" : true
          }
        },
        "description" : "Select allowed account types for the white-label solution. If not specified, all account types are allowed."
      },
      "ApiKeyAccessPolicyDTO" : {
        "type" : "object",
        "properties" : {
          "allowedCorsOrigins" : {
            "type" : "array",
            "description" : "List of allowed CORS (Cross-Origin Resource Sharing) domains. If specified, only requests from these origins will be allowed. Supports wildcards. Examples: 'https://example.com', 'https://*.example.com', 'http://localhost:3000'. If null or empty, all origins are allowed.",
            "items" : {
              "type" : "string",
              "description" : "List of allowed CORS (Cross-Origin Resource Sharing) domains. If specified, only requests from these origins will be allowed. Supports wildcards. Examples: 'https://example.com', 'https://*.example.com', 'http://localhost:3000'. If null or empty, all origins are allowed."
            }
          },
          "allowedIpAddresses" : {
            "type" : "array",
            "description" : "List of allowed IP addresses or CIDR subnets. If specified, only requests from these IPs will be allowed. Supports both IPv4 and IPv6. Examples: '192.168.1.100', '10.0.0.0/24', '2001:db8::/32'. If null or empty, all IPs are allowed.",
            "items" : {
              "type" : "string",
              "description" : "List of allowed IP addresses or CIDR subnets. If specified, only requests from these IPs will be allowed. Supports both IPv4 and IPv6. Examples: '192.168.1.100', '10.0.0.0/24', '2001:db8::/32'. If null or empty, all IPs are allowed."
            }
          },
          "enabled" : {
            "type" : "boolean",
            "description" : "Whether the access policy is enabled. If false, all restrictions are disabled and the API key has full access. Default is true.",
            "example" : true
          },
          "endpointPolicyMode" : {
            "type" : "string",
            "description" : "Endpoint access policy mode: ALLOW_LIST (only listed endpoints are accessible) or DENY_LIST (listed endpoints are blocked). Default is ALLOW_LIST if not specified.",
            "example" : "ALLOW_LIST",
            "enum" : [ "ALLOW_LIST", "DENY_LIST" ]
          },
          "endpoints" : {
            "type" : "array",
            "description" : "List of REST endpoints with their HTTP methods. Supports wildcards: '*' for single segment, '**' for multiple segments, '{variable}' for path variables. Examples: '/rest/api/v1/projects/*' matches any direct child, '/rest/api/v1/projects/**' matches all descendants. Behavior depends on endpointPolicyMode: ALLOW_LIST = only these endpoints accessible, DENY_LIST = these endpoints blocked.",
            "items" : {
              "$ref" : "#/components/schemas/ApiKeyEndpointDTO"
            }
          },
          "fieldPolicyMode" : {
            "type" : "string",
            "description" : "Field access policy mode: ALLOW_LIST (only listed fields are visible) or DENY_LIST (listed fields are hidden). Default is DENY_LIST if not specified.",
            "example" : "DENY_LIST",
            "enum" : [ "ALLOW_LIST", "DENY_LIST" ]
          },
          "fields" : {
            "type" : "array",
            "description" : "List of DTO fields with their class name and field name. Allows filtering fields from multiple DTOs. Behavior depends on fieldPolicyMode: ALLOW_LIST = only these fields visible, DENY_LIST = these fields hidden. If null or empty and mode is ALLOW_LIST, no fields are visible. If null or empty and mode is DENY_LIST, all fields are visible.",
            "items" : {
              "$ref" : "#/components/schemas/FieldMetadataDTO"
            }
          },
          "hiddenFrontendFeatures" : {
            "type" : "array",
            "description" : "List of frontend features to hide from the user interface. Frontend application should check this list and hide corresponding UI components. Examples: FINANCIAL_OVERVIEW to hide balance, equity, profit displays.",
            "items" : {
              "type" : "string",
              "description" : "List of frontend features to hide from the user interface. Frontend application should check this list and hide corresponding UI components. Examples: FINANCIAL_OVERVIEW to hide balance, equity, profit displays.",
              "enum" : [ "FINANCIAL_OVERVIEW" ]
            }
          }
        },
        "description" : "Access policy configuration for this API key. Controls which AccountInformationDTO fields are visible and which endpoints are accessible."
      },
      "ApiKeyDTO" : {
        "type" : "object",
        "properties" : {
          "accessPolicy" : {
            "$ref" : "#/components/schemas/ApiKeyAccessPolicyDTO"
          },
          "accountId" : {
            "type" : "string",
            "description" : "You have to set it during resource creation, after that, it is only read-only",
            "format" : "uuid"
          },
          "alias" : {
            "maxLength" : 255,
            "minLength" : 0,
            "type" : "string"
          },
          "expiresAt" : {
            "type" : "string",
            "description" : "Point in time after which this key is rejected. Null means the key never expires.",
            "format" : "date-time"
          },
          "id" : {
            "type" : "integer",
            "format" : "int32",
            "readOnly" : true
          },
          "key" : {
            "type" : "string",
            "readOnly" : true
          },
          "keyType" : {
            "type" : "string",
            "description" : "Key type: INTEGRATION or AI. At most one AI key per project; setting it on a second key clears the flag on the first. AI keys fail closed without an access policy and cannot be turned back into INTEGRATION keys.",
            "enum" : [ "INTEGRATION", "AI" ]
          },
          "lastUsedAt" : {
            "type" : "string",
            "description" : "Last time this key was accepted on a request. Updated at most once per minute.",
            "format" : "date-time",
            "readOnly" : true
          },
          "permissionType" : {
            "type" : "string",
            "description" : "Permission type: READ_WRITE or READ_ONLY",
            "enum" : [ "READ_WRITE", "READ_ONLY" ]
          },
          "projectId" : {
            "type" : "string",
            "description" : "You have to set it during resource creation, after that, it is only read-only",
            "format" : "uuid"
          },
          "revokedAt" : {
            "type" : "string",
            "description" : "Point in time at which this key was revoked. Null means the key is active.",
            "format" : "date-time",
            "readOnly" : true
          }
        }
      },
      "ApiKeyEndpointDTO" : {
        "required" : [ "method", "path" ],
        "type" : "object",
        "properties" : {
          "method" : {
            "pattern" : "GET|POST|PUT|DELETE",
            "type" : "string",
            "description" : "HTTP method",
            "example" : "GET",
            "enum" : [ "GET", "POST", "PUT", "DELETE" ]
          },
          "path" : {
            "type" : "string",
            "description" : "REST endpoint path pattern. Supports wildcards: '*' matches one path segment, '**' matches multiple segments, '{variable}' matches path variables. Examples: '/rest/api/v1/projects/*', '/rest/api/v1/projects/**', '/rest/api/v1/projects/{projectId}/strategies'",
            "example" : "/rest/api/v1/projects/{projectId}/strategies"
          }
        },
        "description" : "List of REST endpoints with their HTTP methods. Supports wildcards: '*' for single segment, '**' for multiple segments, '{variable}' for path variables. Examples: '/rest/api/v1/projects/*' matches any direct child, '/rest/api/v1/projects/**' matches all descendants. Behavior depends on endpointPolicyMode: ALLOW_LIST = only these endpoints accessible, DENY_LIST = these endpoints blocked."
      },
      "AppliedTemplateDTO" : {
        "type" : "object",
        "properties" : {
          "meta" : {
            "$ref" : "#/components/schemas/JsonNode"
          },
          "templateId" : {
            "type" : "string",
            "description" : "Template to link this account to. Send null to clear the existing link.",
            "format" : "uuid",
            "nullable" : true
          },
          "templateRevision" : {
            "type" : "integer",
            "description" : "Revision of the template that was applied. Required when templateId is set.",
            "format" : "int64",
            "nullable" : true
          }
        },
        "description" : "Sets or clears the link between an account and a template. Send templateId=null to unlink."
      },
      "ApprovalDTO" : {
        "required" : [ "accountFromId", "ticket" ],
        "type" : "object",
        "properties" : {
          "accountFromId" : {
            "type" : "string",
            "description" : "The account UUID",
            "format" : "uuid"
          },
          "ticket" : {
            "type" : "integer",
            "description" : "The ticket number of the position",
            "format" : "int64"
          },
          "volume" : {
            "type" : "number",
            "description" : "You can override the volume (lots). If not specified, it will use the lot size specified by the copier"
          }
        },
        "readOnly" : true
      },
      "AsyncAccountCreationResponseDTO" : {
        "type" : "object",
        "properties" : {
          "account" : {
            "$ref" : "#/components/schemas/AccountDTO"
          },
          "callbackUrl" : {
            "type" : "string",
            "description" : "The callback URL where the result will be sent",
            "example" : "https://example.com/webhook/account-created"
          },
          "error" : {
            "type" : "string",
            "description" : "Error message (only present when status is FAILED)"
          },
          "message" : {
            "type" : "string",
            "description" : "Status message",
            "example" : "Account creation request accepted. The result will be POSTed to the provided callback URL."
          },
          "requestId" : {
            "type" : "string",
            "description" : "Unique request ID for tracking this async operation",
            "example" : "acc_a1b2c3d4e5f67890"
          },
          "status" : {
            "type" : "string",
            "description" : "Processing status of the async request",
            "example" : "QUEUED",
            "enum" : [ "QUEUED", "PROCESSING", "COMPLETED", "FAILED" ]
          }
        },
        "description" : "Response returned when account creation is processed asynchronously via callback URL"
      },
      "AuditLogDTO" : {
        "type" : "object",
        "properties" : {
          "accountAlias" : {
            "type" : "string",
            "description" : "Account alias/name for easier identification",
            "readOnly" : true,
            "example" : "Main Trading Account"
          },
          "accountId" : {
            "type" : "string",
            "description" : "Account ID if the operation is specific to an account",
            "format" : "uuid",
            "readOnly" : true,
            "example" : "123e4567-e89b-12d3-a456-426614174001"
          },
          "apiKeyAlias" : {
            "type" : "string",
            "description" : "API Key alias/name for easier identification",
            "readOnly" : true,
            "example" : "Production API Key"
          },
          "apiKeyId" : {
            "type" : "integer",
            "description" : "API Key ID that made the request",
            "format" : "int64",
            "readOnly" : true,
            "example" : 12345
          },
          "durationMs" : {
            "type" : "integer",
            "description" : "Duration of the operation in milliseconds",
            "format" : "int64",
            "readOnly" : true,
            "example" : 125
          },
          "endpoint" : {
            "type" : "string",
            "description" : "API endpoint that was called",
            "readOnly" : true,
            "example" : "/rest/api/v1/projects/123e4567-e89b-12d3-a456-426614174000/accounts"
          },
          "errorMessage" : {
            "type" : "string",
            "description" : "Error message if the operation failed",
            "readOnly" : true,
            "example" : "Resource not found"
          },
          "id" : {
            "type" : "string",
            "description" : "Unique identifier for the audit log entry",
            "readOnly" : true,
            "example" : "507f1f77bcf86cd799439011"
          },
          "ipAddress" : {
            "type" : "string",
            "description" : "Client IP address",
            "readOnly" : true,
            "example" : "192.168.1.100"
          },
          "method" : {
            "type" : "string",
            "description" : "HTTP method used",
            "readOnly" : true,
            "example" : "POST"
          },
          "projectId" : {
            "type" : "string",
            "description" : "Project ID associated with this operation",
            "format" : "uuid",
            "readOnly" : true,
            "example" : "123e4567-e89b-12d3-a456-426614174000"
          },
          "projectName" : {
            "type" : "string",
            "description" : "Project name for easier identification",
            "readOnly" : true,
            "example" : "My Trading Project"
          },
          "queryString" : {
            "type" : "string",
            "description" : "Query parameters if any",
            "readOnly" : true,
            "example" : "limit=10&offset=0"
          },
          "requestBody" : {
            "type" : "string",
            "description" : "Request body (sanitized, passwords removed)",
            "readOnly" : true,
            "example" : "{\"name\":\"My Account\"}"
          },
          "requestBodySize" : {
            "type" : "integer",
            "description" : "Size of request body in bytes",
            "format" : "int64",
            "readOnly" : true,
            "example" : 256
          },
          "requestHeaders" : {
            "type" : "string",
            "description" : "Request headers as JSON string (sensitive headers removed)",
            "readOnly" : true,
            "example" : "{\"Content-Type\":\"application/json\"}"
          },
          "responseBody" : {
            "type" : "string",
            "description" : "Response body (only for error responses)",
            "readOnly" : true,
            "example" : "{\"error\":\"Not Found\"}"
          },
          "responseBodySize" : {
            "type" : "integer",
            "description" : "Size of response body in bytes",
            "format" : "int64",
            "readOnly" : true,
            "example" : 512
          },
          "serverHost" : {
            "type" : "string",
            "description" : "Server hostname that processed the request",
            "readOnly" : true,
            "example" : "metacopier-node-1"
          },
          "statusCode" : {
            "type" : "integer",
            "description" : "HTTP status code of the response",
            "format" : "int32",
            "readOnly" : true,
            "example" : 200
          },
          "success" : {
            "type" : "boolean",
            "description" : "Whether the operation was successful (2xx status)",
            "readOnly" : true,
            "example" : true
          },
          "timestamp" : {
            "type" : "string",
            "description" : "Timestamp when the operation was performed",
            "format" : "date-time",
            "readOnly" : true,
            "example" : "2025-11-09T10:30:00Z"
          },
          "userAgent" : {
            "type" : "string",
            "description" : "User agent string from the client",
            "readOnly" : true,
            "example" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
          }
        },
        "description" : "Audit log entry representing an API operation"
      },
      "BankHolidayDTO" : {
        "type" : "object",
        "properties" : {
          "countryCode" : {
            "type" : "string",
            "description" : "ISO-3166 alpha-2 country code",
            "example" : "US"
          },
          "currencyCode" : {
            "type" : "string",
            "description" : "Currency the country trades in",
            "example" : "USD"
          },
          "date" : {
            "type" : "string",
            "description" : "Date of the holiday (ISO-8601, no time)",
            "example" : "2026-12-25"
          },
          "global" : {
            "type" : "boolean",
            "description" : "True when the holiday applies to the whole country"
          },
          "id" : {
            "type" : "string",
            "description" : "Composite id of country and date"
          },
          "localName" : {
            "type" : "string",
            "description" : "Name in the local language"
          },
          "name" : {
            "type" : "string",
            "description" : "English name"
          },
          "types" : {
            "type" : "array",
            "description" : "Nager types, for example Public or Bank",
            "items" : {
              "type" : "string",
              "description" : "Nager types, for example Public or Bank"
            }
          }
        },
        "description" : "A public or bank holiday of one country"
      },
      "BlockCustomerRequestDTO" : {
        "required" : [ "email" ],
        "type" : "object",
        "properties" : {
          "email" : {
            "maxLength" : 254,
            "minLength" : 0,
            "type" : "string",
            "description" : "Email address of the customer to block.",
            "example" : "customer@example.com"
          },
          "reason" : {
            "maxLength" : 255,
            "minLength" : 0,
            "type" : "string",
            "description" : "Optional free-text reason logged with the block action.",
            "example" : "Non-payment of invoices for the last 2 months"
          }
        },
        "description" : "Request body for blocking a white-label customer across all their projects linked to this white-label"
      },
      "BlockCustomerResponseDTO" : {
        "type" : "object",
        "properties" : {
          "accepted" : {
            "type" : "boolean",
            "description" : "True if the request was accepted and the background job was scheduled."
          },
          "email" : {
            "type" : "string",
            "description" : "Email address that was processed."
          },
          "notificationEmail" : {
            "type" : "string",
            "description" : "Comma-separated list of email addresses that will receive the summary once the background job finishes (kept for backwards compatibility; prefer notificationEmails)."
          },
          "notificationEmails" : {
            "type" : "array",
            "description" : "Email addresses that will receive the summary once the background job finishes. Always includes the white-label project owner, plus the dashboard user who triggered the block when different.",
            "items" : {
              "type" : "string",
              "description" : "Email addresses that will receive the summary once the background job finishes. Always includes the white-label project owner, plus the dashboard user who triggered the block when different."
            }
          },
          "queuedProjectCount" : {
            "type" : "integer",
            "description" : "Number of projects that were queued for blocking.",
            "format" : "int32"
          },
          "queuedProjectIds" : {
            "type" : "array",
            "description" : "IDs of the projects that were queued for blocking.",
            "items" : {
              "type" : "string",
              "description" : "IDs of the projects that were queued for blocking.",
              "format" : "uuid"
            }
          }
        },
        "description" : "Result of a white-label customer block action. The block runs asynchronously; a summary email is sent to the white-label project owner and, if different, to the user who triggered the block, when finished."
      },
      "CalendarAlertDTO" : {
        "type" : "object",
        "properties" : {
          "accountId" : {
            "type" : "string",
            "description" : "Account the warning is about, null for a plain calendar reminder",
            "format" : "uuid"
          },
          "createdAt" : {
            "type" : "string",
            "description" : "Creation time",
            "format" : "date-time",
            "readOnly" : true
          },
          "createdByEmail" : {
            "type" : "string",
            "description" : "Who armed the row, provenance only and never a scope",
            "readOnly" : true
          },
          "eventId" : {
            "type" : "string",
            "description" : "Id of the calendar event this alert points at"
          },
          "eventTimeUtc" : {
            "type" : "string",
            "description" : "Event time the fire time was computed from",
            "format" : "date-time",
            "readOnly" : true
          },
          "eventTitle" : {
            "type" : "string",
            "description" : "Event title at arming time, for the alert list",
            "readOnly" : true
          },
          "featureId" : {
            "type" : "string",
            "description" : "Originating news feature instance, null for a bell",
            "format" : "uuid"
          },
          "fireAtUtc" : {
            "type" : "string",
            "description" : "When the alert becomes due",
            "format" : "date-time",
            "readOnly" : true
          },
          "id" : {
            "type" : "string",
            "description" : "MongoDB document id",
            "readOnly" : true
          },
          "kind" : {
            "type" : "string",
            "description" : "Which producer created the row",
            "enum" : [ "BELL", "RULE", "FILTER_WARNING", "AGENDA" ]
          },
          "leadMinutes" : {
            "type" : "integer",
            "description" : "Minutes before the event the alert fires",
            "format" : "int32",
            "example" : 15
          },
          "notificationTargets" : {
            "type" : "array",
            "description" : "Where the alert is delivered",
            "items" : {
              "$ref" : "#/components/schemas/NotificationTargetDTO"
            }
          },
          "projectId" : {
            "type" : "string",
            "description" : "Owning project",
            "format" : "uuid"
          },
          "ruleId" : {
            "type" : "string",
            "description" : "Originating standing rule, null unless kind is RULE",
            "readOnly" : true
          },
          "sent" : {
            "type" : "boolean",
            "description" : "True once the alert has been claimed and dispatched",
            "readOnly" : true
          }
        },
        "description" : "Armed reminder for an economic calendar event"
      },
      "CalendarAlertRuleDTO" : {
        "type" : "object",
        "properties" : {
          "createdAt" : {
            "type" : "string",
            "description" : "Creation time",
            "format" : "date-time",
            "readOnly" : true
          },
          "createdByEmail" : {
            "type" : "string",
            "description" : "Who created the rule, provenance only and never a scope",
            "readOnly" : true
          },
          "currencyCodes" : {
            "uniqueItems" : true,
            "type" : "array",
            "description" : "Currencies the rule reacts to. Empty matches every currency.",
            "items" : {
              "type" : "string",
              "description" : "Currencies the rule reacts to. Empty matches every currency."
            }
          },
          "enabled" : {
            "type" : "boolean",
            "description" : "A disabled rule stops materialising new alerts"
          },
          "id" : {
            "type" : "string",
            "description" : "MongoDB document id",
            "readOnly" : true
          },
          "includeMarketNews" : {
            "type" : "boolean",
            "description" : "Also send HIGH impact market news headlines matching the currencies of this rule. Those have no lead time, they are announced when they are summarised."
          },
          "leadMinutes" : {
            "type" : "array",
            "description" : "Minutes before the event the alerts fire",
            "example" : [ 30 ],
            "items" : {
              "type" : "integer",
              "description" : "Minutes before the event the alerts fire",
              "format" : "int32"
            }
          },
          "minImpact" : {
            "type" : "string",
            "description" : "Lowest impact the rule reacts to",
            "enum" : [ "HOLIDAY", "LOW", "MEDIUM", "HIGH" ]
          },
          "name" : {
            "type" : "string",
            "description" : "Label shown in the alerts panel",
            "example" : "High impact USD"
          },
          "notificationTargets" : {
            "type" : "array",
            "description" : "Where the alerts are delivered",
            "items" : {
              "$ref" : "#/components/schemas/NotificationTargetDTO"
            }
          },
          "projectId" : {
            "type" : "string",
            "description" : "Owning project",
            "format" : "uuid",
            "readOnly" : true
          }
        },
        "description" : "Standing calendar alert rule of a project"
      },
      "CalendarEventDTO" : {
        "type" : "object",
        "properties" : {
          "actual" : {
            "type" : "string",
            "description" : "Released value as a display string",
            "readOnly" : true,
            "example" : "0.3%"
          },
          "actualRaw" : {
            "type" : "number",
            "description" : "Released value, numeric",
            "format" : "double",
            "readOnly" : true,
            "example" : 0.3
          },
          "actualReleasedAt" : {
            "type" : "string",
            "description" : "When the actual value first became available",
            "format" : "date-time",
            "readOnly" : true
          },
          "allDay" : {
            "type" : "boolean",
            "description" : "True when the source gives a day but no exact time",
            "readOnly" : true
          },
          "category" : {
            "type" : "string",
            "description" : "Source category",
            "readOnly" : true,
            "example" : "prce"
          },
          "commentEn" : {
            "type" : "string",
            "description" : "Explanation rewritten by us in English, at most 150 characters",
            "readOnly" : true
          },
          "countryCode" : {
            "type" : "string",
            "description" : "ISO-3166 alpha-2, EU for the eurozone, null for global events",
            "readOnly" : true,
            "example" : "US"
          },
          "currencyCode" : {
            "type" : "string",
            "description" : "ISO-4217 currency, ALL for global events",
            "readOnly" : true,
            "example" : "USD"
          },
          "dedupKey" : {
            "type" : "string",
            "description" : "Stable hash identifying the same event across sources",
            "readOnly" : true
          },
          "disputed" : {
            "type" : "boolean",
            "description" : "True when sources disagree on the time by more than 30 minutes",
            "readOnly" : true
          },
          "eventTimeUtc" : {
            "type" : "string",
            "description" : "Release time in UTC",
            "format" : "date-time",
            "readOnly" : true
          },
          "firstSeenAt" : {
            "type" : "string",
            "description" : "When this event was first ingested",
            "format" : "date-time",
            "readOnly" : true
          },
          "forecast" : {
            "type" : "string",
            "description" : "Consensus forecast as a display string",
            "readOnly" : true,
            "example" : "0.2%"
          },
          "forecastRaw" : {
            "type" : "number",
            "description" : "Consensus forecast, numeric",
            "format" : "double",
            "readOnly" : true,
            "example" : 0.2
          },
          "id" : {
            "type" : "string",
            "description" : "MongoDB document id",
            "readOnly" : true
          },
          "impact" : {
            "type" : "string",
            "description" : "Impact classification",
            "readOnly" : true,
            "enum" : [ "HOLIDAY", "LOW", "MEDIUM", "HIGH" ]
          },
          "indicator" : {
            "type" : "string",
            "description" : "Normalised indicator name",
            "readOnly" : true,
            "example" : "core cpi mm"
          },
          "indicatorKey" : {
            "type" : "string",
            "description" : "Stable key for statistics: countryCode|normalisedIndicator",
            "readOnly" : true,
            "example" : "US|core cpi mm"
          },
          "lastUpdatedAt" : {
            "type" : "string",
            "description" : "When this event was last written",
            "format" : "date-time",
            "readOnly" : true
          },
          "period" : {
            "type" : "string",
            "description" : "Reference period",
            "readOnly" : true,
            "example" : "Jul"
          },
          "previous" : {
            "type" : "string",
            "description" : "Previous value as a display string",
            "readOnly" : true,
            "example" : "0.1%"
          },
          "previousRaw" : {
            "type" : "number",
            "description" : "Previous value, numeric",
            "format" : "double",
            "readOnly" : true,
            "example" : 0.1
          },
          "revision" : {
            "type" : "integer",
            "description" : "Incremented whenever the time or the forecast changes",
            "format" : "int32",
            "readOnly" : true,
            "example" : 1
          },
          "revisions" : {
            "type" : "array",
            "description" : "What changed and when, for the revised badge",
            "readOnly" : true,
            "items" : {
              "$ref" : "#/components/schemas/CalendarEventRevisionDTO"
            }
          },
          "scale" : {
            "type" : "string",
            "description" : "Scale of the values",
            "readOnly" : true,
            "example" : "K"
          },
          "surpriseSigma" : {
            "type" : "number",
            "description" : "(actual - forecast) divided by the historic surprise standard deviation",
            "format" : "double",
            "readOnly" : true,
            "example" : 2.4
          },
          "title" : {
            "type" : "string",
            "description" : "Event title as published",
            "readOnly" : true,
            "example" : "Core CPI m/m"
          },
          "titleEn" : {
            "type" : "string",
            "description" : "Title rewritten by us in English, at most 150 characters",
            "readOnly" : true
          },
          "unit" : {
            "type" : "string",
            "description" : "Unit of the values",
            "readOnly" : true,
            "example" : "%"
          }
        },
        "description" : "Economic calendar event, normalised across all sources",
        "readOnly" : true
      },
      "CalendarEventPageDTO" : {
        "type" : "object",
        "properties" : {
          "items" : {
            "type" : "array",
            "description" : "Events of this page, ascending by release time",
            "readOnly" : true,
            "items" : {
              "$ref" : "#/components/schemas/CalendarEventDTO"
            }
          },
          "lastSyncUtc" : {
            "type" : "string",
            "description" : "When the ingestion last wrote anything, null means it never ran",
            "format" : "date-time",
            "readOnly" : true
          },
          "nextEventTitle" : {
            "type" : "string",
            "description" : "Title of the event behind nextEventUtc",
            "readOnly" : true,
            "example" : "Non-Farm Payrolls"
          },
          "nextEventUtc" : {
            "type" : "string",
            "description" : "First matching event after the requested range, so an empty page is never a dead end",
            "format" : "date-time",
            "readOnly" : true
          },
          "page" : {
            "type" : "integer",
            "description" : "Zero based page index",
            "format" : "int32",
            "readOnly" : true,
            "example" : 0
          },
          "size" : {
            "type" : "integer",
            "description" : "Page size",
            "format" : "int32",
            "readOnly" : true,
            "example" : 25
          },
          "total" : {
            "type" : "integer",
            "description" : "Total number of matching events",
            "format" : "int64",
            "readOnly" : true,
            "example" : 134
          }
        },
        "description" : "One page of economic calendar events"
      },
      "CalendarEventRevisionDTO" : {
        "type" : "object",
        "properties" : {
          "changedAt" : {
            "type" : "string",
            "description" : "When the change was observed",
            "format" : "date-time",
            "readOnly" : true
          },
          "field" : {
            "type" : "string",
            "description" : "Field that changed",
            "readOnly" : true,
            "example" : "eventTimeUtc"
          },
          "newValue" : {
            "type" : "string",
            "description" : "Value after the change",
            "readOnly" : true,
            "example" : "2026-08-12T14:30:00Z"
          },
          "oldValue" : {
            "type" : "string",
            "description" : "Value before the change",
            "readOnly" : true,
            "example" : "2026-08-12T12:30:00Z"
          }
        },
        "description" : "One recorded change to a calendar event after it was first seen",
        "readOnly" : true
      },
      "CalendarExposureDTO" : {
        "type" : "object",
        "properties" : {
          "asOfUtc" : {
            "type" : "string",
            "description" : "When the positions were read from the broker",
            "format" : "date-time"
          },
          "events" : {
            "type" : "array",
            "description" : "Soonest event first",
            "items" : {
              "$ref" : "#/components/schemas/CalendarExposureEventDTO"
            }
          },
          "fromUtc" : {
            "type" : "string",
            "format" : "date-time"
          },
          "openPositions" : {
            "type" : "integer",
            "format" : "int32"
          },
          "toUtc" : {
            "type" : "string",
            "format" : "date-time"
          },
          "unresolvedSymbols" : {
            "type" : "array",
            "description" : "Symbols that could not be mapped to a currency, so they show no exposure even if they are risky",
            "items" : {
              "type" : "string",
              "description" : "Symbols that could not be mapped to a currency, so they show no exposure even if they are risky"
            }
          }
        }
      },
      "CalendarExposureEventDTO" : {
        "type" : "object",
        "properties" : {
          "currencyCode" : {
            "type" : "string"
          },
          "eventId" : {
            "type" : "string"
          },
          "eventTimeUtc" : {
            "type" : "string",
            "format" : "date-time"
          },
          "floatingProfit" : {
            "type" : "number",
            "description" : "Current floating profit of those positions"
          },
          "impact" : {
            "type" : "string",
            "enum" : [ "HOLIDAY", "LOW", "MEDIUM", "HIGH" ]
          },
          "margin" : {
            "type" : "number",
            "description" : "Initial margin of those positions in account currency, null when the broker did not report it"
          },
          "positions" : {
            "type" : "integer",
            "format" : "int32"
          },
          "symbols" : {
            "type" : "array",
            "description" : "Which symbols are exposed, so a wrong mapping is visible at a glance",
            "items" : {
              "type" : "string",
              "description" : "Which symbols are exposed, so a wrong mapping is visible at a glance"
            }
          },
          "title" : {
            "type" : "string"
          },
          "volume" : {
            "type" : "number",
            "description" : "Combined volume in lots"
          }
        },
        "description" : "Soonest event first"
      },
      "CalendarSubscriptionDTO" : {
        "type" : "object",
        "properties" : {
          "alias" : {
            "type" : "string"
          },
          "createdAt" : {
            "type" : "string",
            "format" : "date-time"
          },
          "currencies" : {
            "type" : "array",
            "items" : {
              "type" : "string"
            }
          },
          "customerEmail" : {
            "type" : "string",
            "description" : "Who created the subscription. A subscription belongs to the project, this is only the audit trail"
          },
          "id" : {
            "type" : "string"
          },
          "includeHolidays" : {
            "type" : "boolean"
          },
          "lastUsedAt" : {
            "type" : "string",
            "format" : "date-time"
          },
          "minImpact" : {
            "type" : "string",
            "enum" : [ "HOLIDAY", "LOW", "MEDIUM", "HIGH" ]
          },
          "projectId" : {
            "type" : "string",
            "format" : "uuid"
          },
          "requestCount" : {
            "type" : "integer",
            "format" : "int64"
          },
          "url" : {
            "type" : "string",
            "description" : "The feed URL including the token. Returned once, at creation, and never again"
          }
        }
      },
      "CloseReopenScheduleDTO" : {
        "required" : [ "closeTime" ],
        "type" : "object",
        "properties" : {
          "activeDays" : {
            "type" : "array",
            "description" : "Specific days when this schedule is active, represented as integers (e.g., 1 for Monday, 7 for Sunday).",
            "example" : [ 1, 2, 3, 4, 5 ],
            "items" : {
              "type" : "integer",
              "description" : "Specific days when this schedule is active, represented as integers (e.g., 1 for Monday, 7 for Sunday).",
              "format" : "int32"
            }
          },
          "closeTime" : {
            "type" : "string",
            "description" : "Time (UTC) at which all matching open positions are closed. Note: The date component is ignored.",
            "format" : "date-time",
            "example" : "2025-01-01T23:45:00Z"
          },
          "enabled" : {
            "type" : "boolean",
            "description" : "If false, this schedule is ignored without having to delete it.",
            "example" : true,
            "default" : true
          },
          "label" : {
            "maxLength" : 50,
            "minLength" : 0,
            "type" : "string",
            "description" : "Optional name of the schedule, shown in the user interface and used as close/reopen reason.",
            "example" : "Overnight swap"
          },
          "reopenDayOffset" : {
            "maximum" : 7,
            "type" : "integer",
            "description" : "Number of days between the close day and the reopen day. 0 means the next occurrence of the reopen time. Use 3 to close on Friday and reopen on Monday.",
            "format" : "int32",
            "example" : 0,
            "default" : 0
          },
          "reopenTime" : {
            "type" : "string",
            "description" : "Time (UTC) at which the positions closed by this schedule are reopened. If null, the positions stay closed. Note: The date component is ignored.",
            "format" : "date-time",
            "example" : "2025-01-02T00:15:00Z"
          },
          "skipNewTradesUntilReopen" : {
            "type" : "boolean",
            "description" : "Indicates whether new trades are skipped between the close time and the reopen time. This option is only applicable to copiers.",
            "example" : true,
            "default" : false
          }
        },
        "description" : "DTO for defining a single scheduled close (and optional reopen) entry (copier/account)"
      },
      "ClosedPositionInfo" : {
        "type" : "object",
        "properties" : {
          "error" : {
            "type" : "string",
            "description" : "Error message if close failed"
          },
          "positionId" : {
            "type" : "string",
            "description" : "Broker position ID",
            "example" : "12345678"
          },
          "success" : {
            "type" : "boolean",
            "description" : "Whether the close was successful",
            "example" : true
          },
          "symbol" : {
            "type" : "string",
            "description" : "Symbol",
            "example" : "EURUSD"
          }
        },
        "description" : "Information about a closed position"
      },
      "ContactDTO" : {
        "type" : "object",
        "properties" : {
          "discord" : {
            "maxLength" : 100,
            "minLength" : 0,
            "type" : "string",
            "description" : "Discord username or server invite. This provides a community-oriented communication channel.",
            "example" : "username#1234"
          },
          "email" : {
            "maxLength" : 255,
            "minLength" : 0,
            "type" : "string",
            "description" : "Email contact for inquiries and support.",
            "example" : "signal@example.com"
          },
          "telegram" : {
            "maxLength" : 100,
            "minLength" : 0,
            "type" : "string",
            "description" : "Telegram username or contact information. This provides an alternative communication channel for support and updates.",
            "example" : "@username"
          },
          "website" : {
            "maxLength" : 500,
            "minLength" : 0,
            "type" : "string",
            "description" : "Additional website or social media link for contact purposes.",
            "example" : "https://example.com"
          },
          "whatsapp" : {
            "maxLength" : 50,
            "minLength" : 0,
            "type" : "string",
            "description" : "WhatsApp contact information. Include country code (e.g., +1234567890). This provides an additional channel for communication with subscribers.",
            "example" : "+1234567890"
          }
        },
        "description" : "Contact information for signal providers"
      },
      "CopierDTO" : {
        "type" : "object",
        "properties" : {
          "active" : {
            "type" : "boolean",
            "description" : "Controls whether the copier is active or disabled. When false (inactive), the copier is fully disabled/detached and will not copy any new trades and existing open positions are no longer managed. When true, the copier operates normally.",
            "default" : true
          },
          "copyMagicNumber" : {
            "type" : "boolean",
            "description" : "When enabled, the magic number from the master account's order will be copied to the corresponding trade on the slave account. If the master's magic number is 0 (or absent), no magic number is stamped on the copy — the field is omitted in the outgoing order rather than sent as 0. If `customMagicNumber` is also set to a non-zero value, `customMagicNumber` takes precedence and overrides this behavior.",
            "example" : false,
            "default" : false
          },
          "copyOpenPositions" : {
            "type" : "boolean",
            "description" : "When enabled, the copier will also replicate any open positions on the master account to the slave account at the time of activation.",
            "example" : false,
            "default" : false
          },
          "copyOriginalComment" : {
            "type" : "boolean",
            "description" : "Enabling this option is not recommended. Comments on the slave account are used for internal tracking purposes, and if missing, open positions may under certain circumstances be incorrectly detected as unmanaged. When enabled, the original order comment from the master account will be copied to the corresponding order on the slave account. If disabled, the default tracking comment will be used instead.",
            "example" : false,
            "default" : false
          },
          "copyStopLoss" : {
            "type" : "boolean",
            "description" : "If the copier belongs to a strategy, this setting will be ignored.",
            "default" : true
          },
          "copyTakeProfit" : {
            "type" : "boolean",
            "description" : "If the copier belongs to a strategy, this setting will be ignored.",
            "default" : true
          },
          "created" : {
            "type" : "string",
            "description" : "ISO 8601. Timestamp when this copier was created.",
            "format" : "date-time",
            "readOnly" : true
          },
          "customComment" : {
            "maxLength" : 20,
            "minLength" : 0,
            "type" : "string",
            "description" : "Custom comment to be used for trades. If specified, this comment will be used instead of the default tracking comment.",
            "example" : "My Custom Comment"
          },
          "customMagicNumber" : {
            "type" : "integer",
            "description" : "Custom magic number to be stamped on every copied trade on the slave account, overriding the master's magic number regardless of the `copyMagicNumber` setting. Only applies to copied trades — trades opened directly on the slave (manual or by other systems) are not affected. The value 0 is treated as 'not set' (no override is applied, and no magic number is sent on the copy); use null/omit the field for the same effect. To apply a magic number, send any positive integer.",
            "format" : "int32",
            "example" : 123456
          },
          "fixMasterBalanceAndEquity" : {
            "type" : "integer",
            "description" : "Set the master balance and equity to the specified value. A value of 0 means deactivated. If set to 1000, the lot size calculation for the slave account will use 1000 as the master balance/equity.  If the copier belongs to a strategy, this setting will be ignored.",
            "format" : "int32",
            "example" : 0,
            "default" : 0
          },
          "fixSlaveBalanceAndEquity" : {
            "type" : "integer",
            "description" : "Set the slave balance and equity to the specified value. A value of 0 means deactivated. If set to 1000, the lot size calculation for the slave account will use 1000 as the slave balance/equity.  If the copier belongs to a strategy, this setting will be ignored.",
            "format" : "int32",
            "example" : 0,
            "default" : 0
          },
          "fixedLotSize" : {
            "type" : "number",
            "description" : "Set the lot size to a specific value, only applicable when the scaleType is set to '3' (Fixed lot size).  If the copier belongs to a strategy, this setting will be ignored.",
            "example" : 0.01,
            "default" : 0.01
          },
          "forceMinTrade" : {
            "type" : "boolean",
            "description" : "If set to true, when the calculated lot size is for example 0.005, it will be adjusted to the minimum size of the symbol. If set to false, the trade will not be executed. If the copier belongs to a strategy, this setting will be ignored.",
            "example" : true,
            "default" : true
          },
          "forcePositionLotSize" : {
            "type" : "boolean",
            "description" : "Place more trades if max lot size for a specific symbol is reached. Not available for Binance, Bybit, Bitget, BloFin, OKX, TradeStation, Tradovate and Alpaca.",
            "example" : false,
            "default" : false
          },
          "fromAccountAlias" : {
            "type" : "string",
            "readOnly" : true
          },
          "fromAccountId" : {
            "type" : "string",
            "description" : "You have to set it during resource creation, after that, it is only read-only",
            "format" : "uuid"
          },
          "fromStrategyId" : {
            "type" : "string",
            "description" : "You have to set it during resource creation, after that, it is only read-only",
            "format" : "uuid"
          },
          "fromStrategyName" : {
            "type" : "string",
            "readOnly" : true
          },
          "hideComment" : {
            "type" : "boolean",
            "description" : "When enabled, the comment will be hidden, leaving the comment field empty. Furthermore, any positions opened manually or by other systems with an empty comment field will be closed to prevent them from remaining open in case of an error. It is recommended to enable this option only if absolutely necessary.",
            "example" : false,
            "default" : false
          },
          "id" : {
            "type" : "string",
            "format" : "uuid",
            "readOnly" : true
          },
          "ignoreContractSize" : {
            "type" : "boolean",
            "description" : "For the lot size calculation, the contract size (lot size) of the symbol will be ignored.",
            "example" : true,
            "default" : true
          },
          "ignoreCurrency" : {
            "type" : "boolean",
            "description" : "When enabled, the lot size calculation will ignore currency differences between the master and slave accounts—no conversion will be applied. If false, and the currencies of the master and slave accounts differ, the lot size calculation will include a conversion to account for the currency difference.",
            "example" : false,
            "default" : false
          },
          "martingaleStrategy" : {
            "type" : "boolean",
            "description" : "Adjust the lot size based on the Martingale multiplier. If there is a significant difference in balance/equity between the master and slave accounts, the lot size on the slave account may be rounded down. For example, if trades of 0.02 and 0.04 lots are placed on the master account (balance 4000 USD), a standard copier would open 0.01 and 0.01 lots on the slave account (balance 1000 USD - which is incorrect). However, if this option is activated, it will open 0.01 and 0.02 lots. Default is false.  If the copier belongs to a strategy, this setting will be ignored.",
            "example" : false,
            "default" : false
          },
          "maxLotSize" : {
            "type" : "number",
            "description" : "Sets the maximum lot size for each position. If a position exceeds this size, it will be adjusted to this maximum limit. A value of 0 means deactivated.",
            "example" : 0.0,
            "default" : 0.0
          },
          "maxOpenPositions" : {
            "type" : "integer",
            "description" : "Limits the maximum number of open positions the copier can maintain at any given time. If the limit is reached, new positions will be skipped until existing positions are closed. A value of 0 means the feature is deactivated.",
            "format" : "int32",
            "example" : 0,
            "default" : 0
          },
          "maxSlippage" : {
            "type" : "integer",
            "description" : "Set the slippage (deviation) in points. A value of 0 means deactivated. For scalping strategies with a close take profit, it's recommended to set the value low, for example, 1-3 points (10 points = 1 pip). A common value is 20. A value of 0 means deactivated (Trade is always executed at actual price - recommended if you use martingale/hedging/grid). If the copier belongs to a strategy, this setting will be ignored.",
            "format" : "int32",
            "example" : 0,
            "default" : 0
          },
          "maximumLot" : {
            "type" : "number",
            "description" : "When enabled, the total lot size of all open positions (related to this copier) will not exceed this value, new positions will be skipped until existing positions are closed. A value of 0 means deactivated.",
            "example" : 0.0,
            "default" : 0.0
          },
          "minVolumeSafetySkipThresholdMultiplier" : {
            "maximum" : 999.99,
            "exclusiveMaximum" : false,
            "minimum" : 0,
            "exclusiveMinimum" : false,
            "type" : "number",
            "description" : "Defines the maximum allowed amplification when forceMinTrade would increase the calculated slave lot to the broker minimum. This check only applies when the slave broker's minimum lot size for the symbol is greater than the master broker's minimum lot size. If the amplification (slave min lot / calculated lot) is equal to or greater than this value, the trade is skipped. A value of 0 means deactivated. Example: master min lot 0.01, slave min lot 1.00, calculated lot 0.10 → amplification = 1.00 / 0.10 = 10.0x → skipped if threshold <= 10.0. If both brokers have the same min lot size, this check is not applied.",
            "example" : 3.0,
            "default" : 0
          },
          "monitorOnly" : {
            "type" : "boolean",
            "description" : "Indicates whether this copier is in monitor-only mode. When true, the copier monitors the source account and manages existing open positions (can close, modify them) but will not copy any new trades. When false, the copier operates in normal copying mode.",
            "default" : false
          },
          "multiplier" : {
            "maximum" : 999.999,
            "exclusiveMaximum" : false,
            "minimum" : 0.001,
            "exclusiveMinimum" : false,
            "type" : "number",
            "description" : "Set the multiplier. Default is 1.000",
            "example" : 1.0,
            "default" : 1.0
          },
          "openRetry" : {
            "type" : "boolean",
            "description" : "If enabled, the retry mechanism activates when a broker rejects the request or fails to respond. If set to false, the request is sent only once. For Martingale strategies, it is recommended to activate this option, especially when copying between different brokers with varying market opening/closing times. For strategies with small pip profits and larger lot sizes, it is better to deactivate the retry mechanism. For HFT (High-Frequency Trading), it is also better to deactivate it.",
            "example" : false,
            "default" : false
          },
          "openRetryTimeoutInMinutes" : {
            "type" : "integer",
            "description" : "Specifies the total duration (in minutes) during which the retry mechanism will attempt to resend a rejected or failed request. If set to 0, the system will retry indefinitely. Once this duration elapses, no further retry attempts will be made. This setting is applicable only if 'openRetry' is set to true.",
            "format" : "int32",
            "example" : 10,
            "default" : 10
          },
          "reverse" : {
            "type" : "boolean",
            "description" : "If enabled, the order direction is reversed. Useful for trading strategies that require inverse operations.",
            "example" : false,
            "default" : false
          },
          "scaleType" : {
            "$ref" : "#/components/schemas/ScaleTypeDTO"
          },
          "skipPendingOrders" : {
            "type" : "boolean",
            "description" : "This setting allows traders to choose whether or not to replicate pending orders (orders that have not yet been executed). Skipping pending orders is highly recommended. By default, this option is blocked. If you are an expert trader, please contact us to unlock this option. If the copier belongs to a strategy, this setting will be ignored. For DXtrade is not supported. For TradeLocker, MatchTrader, Binance, Bybit, Bitget, BloFin, OKX, TradeStation, Tradovate and Alpaca, quotes are not in real-time, so small slippage settings are not recommended.",
            "example" : true,
            "default" : true
          },
          "toAccountId" : {
            "type" : "string",
            "description" : "You have to set it during resource creation, after that, it is only read-only",
            "format" : "uuid"
          },
          "toStrategyId" : {
            "type" : "string",
            "description" : "You have to set it during resource creation, after that, it is only read-only",
            "format" : "uuid"
          }
        },
        "description" : "If you add a copier to a strategy, only the properties 'active', 'multiplier', and the feature 'FeatureCopierFilterDTO' are available. Copying is only allowed from an account; copying from one strategy to another strategy is not allowed."
      },
      "CopierSettingFieldDTO" : {
        "type" : "object",
        "properties" : {
          "description" : {
            "type" : "string",
            "description" : "Human-readable description of what this setting controls",
            "example" : "Multiplier for lot size calculation"
          },
          "name" : {
            "type" : "string",
            "description" : "The field name from CopierDTO",
            "example" : "multiplier"
          }
        },
        "description" : "DTO representing a copier setting field that can be controlled for override in signal provider features"
      },
      "CopierStateDTO" : {
        "type" : "object",
        "properties" : {
          "active" : {
            "type" : "boolean"
          },
          "monitorOnly" : {
            "type" : "boolean"
          }
        },
        "description" : "Map of copier IDs to their original states before maintenance. Used to restore copiers to their exact previous state."
      },
      "CryptoWalletConfigDTO" : {
        "type" : "object",
        "properties" : {
          "btcXpub" : {
            "pattern" : "^(zpub|vpub)[1-9A-HJ-NP-Za-km-z]{100,120}$",
            "type" : "string",
            "description" : "Bitcoin zpub (native segwit) used to derive BTC receive addresses"
          },
          "custodyMode" : {
            "type" : "string",
            "description" : "XPUB_ONLY (default) lets us only derive addresses. ENCRYPTED_SEED lets the platform sweeper move funds; not enabled in v1.",
            "example" : "XPUB_ONLY",
            "default" : "XPUB_ONLY"
          },
          "enabledCoins" : {
            "type" : "array",
            "description" : "Coins offered to end-users. Default: all coins for which an xpub is set.",
            "example" : [ "USDT_TRON", "USDC_TRON" ],
            "items" : {
              "type" : "string",
              "description" : "Coins offered to end-users. Default: all coins for which an xpub is set.",
              "example" : "[\"USDT_TRON\",\"USDC_TRON\"]"
            }
          },
          "encryptedSeed" : {
            "type" : "string",
            "description" : "AES-GCM ciphertext of the BIP39 mnemonic (advanced mode only)."
          },
          "ethXpub" : {
            "pattern" : "^(xpub|tpub)[1-9A-HJ-NP-Za-km-z]{100,120}$",
            "type" : "string",
            "description" : "Ethereum xpub used to derive ETH / USDT-ERC20 / USDC-ERC20 receive addresses"
          },
          "sweepDestinationByNetwork" : {
            "type" : "object",
            "additionalProperties" : {
              "type" : "string",
              "description" : "Destination cold address per chain used by the platform sweeper (advanced mode only)."
            },
            "description" : "Destination cold address per chain used by the platform sweeper (advanced mode only)."
          },
          "tronXpub" : {
            "pattern" : "^(xpub|tpub)[1-9A-HJ-NP-Za-km-z]{100,120}$",
            "type" : "string",
            "description" : "TRON xpub used to derive USDT/USDC TRC20 receive addresses"
          }
        },
        "description" : "Per-chain wallet configuration for MetaCopier-native crypto"
      },
      "CurrencyTypeDTO" : {
        "required" : [ "id" ],
        "type" : "object",
        "properties" : {
          "id" : {
            "type" : "integer",
            "format" : "int32"
          },
          "name" : {
            "type" : "string",
            "readOnly" : true
          }
        },
        "description" : "You have only to set the id e.g 1 for USD, 2 for EUR, 3 for CHF. Example: {id:1}"
      },
      "CustomerDTO" : {
        "type" : "object",
        "properties" : {
          "blocked" : {
            "type" : "boolean",
            "readOnly" : true
          },
          "created" : {
            "type" : "string",
            "description" : "ISO 8601",
            "format" : "date-time",
            "readOnly" : true
          },
          "email" : {
            "type" : "string",
            "readOnly" : true
          },
          "id" : {
            "type" : "integer",
            "format" : "int32",
            "readOnly" : true
          },
          "kyc" : {
            "type" : "boolean",
            "readOnly" : true
          },
          "payoutMethod" : {
            "$ref" : "#/components/schemas/PayoutDTO"
          },
          "permissionType" : {
            "type" : "string",
            "description" : "Permission level for this customer in the project",
            "readOnly" : true,
            "enum" : [ "READ_WRITE", "READ_ONLY" ]
          },
          "tos" : {
            "type" : "string",
            "description" : "ISO 8601",
            "format" : "date-time",
            "readOnly" : true
          }
        },
        "readOnly" : true
      },
      "CustomerSummaryDTO" : {
        "type" : "object",
        "properties" : {
          "accountCount" : {
            "type" : "integer",
            "description" : "Number of accounts owned by this customer in this project",
            "format" : "int32"
          },
          "activeProjectCount" : {
            "type" : "integer",
            "description" : "Number of projects of this customer under this white-label that are still active (not blocked). When 0, the customer has already been fully blocked at the WL level.",
            "format" : "int32"
          },
          "blocked" : {
            "type" : "boolean",
            "description" : "Whether customer is blocked"
          },
          "created" : {
            "type" : "string",
            "description" : "Customer creation date",
            "format" : "date-time"
          },
          "currentMonthOutstanding" : {
            "type" : "number",
            "description" : "Sum of OPEN invoice amounts for this customer created in the current calendar month"
          },
          "customerId" : {
            "type" : "integer",
            "description" : "Customer ID",
            "format" : "int32"
          },
          "email" : {
            "type" : "string",
            "description" : "Customer email"
          },
          "openInvoices" : {
            "type" : "array",
            "description" : "All OPEN invoices for this customer across the projects of this white-label",
            "items" : {
              "$ref" : "#/components/schemas/InvoiceSummaryDTO"
            }
          },
          "outstandingAmount" : {
            "type" : "number",
            "description" : "Sum of OPEN invoice amounts for this customer across all projects in this white-label"
          },
          "paidAmount" : {
            "type" : "number",
            "description" : "Sum of PAID invoice amounts for this customer across all projects in this white-label"
          },
          "permission" : {
            "type" : "string",
            "description" : "Customer permission in the project"
          },
          "projectIds" : {
            "type" : "array",
            "description" : "IDs of all projects of this white-label where the customer is registered",
            "items" : {
              "type" : "string",
              "description" : "IDs of all projects of this white-label where the customer is registered",
              "format" : "uuid"
            }
          }
        },
        "description" : "Customer information within a project"
      },
      "DashboardStorageDTO" : {
        "type" : "object",
        "properties" : {
          "dashboards" : {
            "type" : "array",
            "description" : "List of dashboards",
            "items" : {
              "$ref" : "#/components/schemas/UserDashboardConfigDTO"
            }
          },
          "syncedAt" : {
            "type" : "string",
            "description" : "Timestamp when data was synced",
            "format" : "date-time",
            "readOnly" : true,
            "example" : "2026-01-26T12:30:00Z"
          }
        },
        "description" : "Dashboard storage for bulk operations"
      },
      "DataCollectorRecordDTO" : {
        "type" : "object",
        "properties" : {
          "accountId" : {
            "type" : "string",
            "description" : "Account ID",
            "format" : "uuid",
            "readOnly" : true,
            "example" : "123e4567-e89b-12d3-a456-426614174000"
          },
          "balance" : {
            "type" : "number",
            "description" : "Account balance (closed positions only) at the time of recording. Represents the account value based on closed trades only.",
            "readOnly" : true,
            "example" : 10000.0
          },
          "equity" : {
            "type" : "number",
            "description" : "Account equity (including floating PnL) at the time of recording. Represents the current account value including open positions.",
            "readOnly" : true,
            "example" : 10500.25
          },
          "floatingPnL" : {
            "type" : "number",
            "description" : "Floating PnL (unrealized profit/loss from open positions) at the time of recording. Calculated as equity minus balance.",
            "readOnly" : true,
            "example" : 500.25
          },
          "id" : {
            "type" : "string",
            "description" : "Unique record identifier",
            "readOnly" : true
          },
          "timestamp" : {
            "type" : "integer",
            "description" : "Timestamp in milliseconds (Unix epoch) when this data was recorded",
            "format" : "int64",
            "readOnly" : true,
            "example" : 1672531200000
          }
        },
        "description" : "Data collector record containing equity, balance, and floating PnL time-series data for an account at a specific point in time"
      },
      "DirectionPerformanceDTO" : {
        "type" : "object",
        "properties" : {
          "buyNetProfit" : {
            "type" : "number",
            "description" : "Net profit for buy trades",
            "readOnly" : true
          },
          "buyTrades" : {
            "type" : "integer",
            "description" : "Number of buy trades",
            "format" : "int32",
            "readOnly" : true
          },
          "buyWinRate" : {
            "type" : "number",
            "description" : "Win rate for buy trades (%)",
            "readOnly" : true
          },
          "sellNetProfit" : {
            "type" : "number",
            "description" : "Net profit for sell trades",
            "readOnly" : true
          },
          "sellTrades" : {
            "type" : "integer",
            "description" : "Number of sell trades",
            "format" : "int32",
            "readOnly" : true
          },
          "sellWinRate" : {
            "type" : "number",
            "description" : "Win rate for sell trades (%)",
            "readOnly" : true
          }
        },
        "description" : "Performance split by trade direction",
        "readOnly" : true
      },
      "DnsCheckResultDTO" : {
        "type" : "object",
        "properties" : {
          "basicOk" : {
            "type" : "boolean"
          },
          "dnsConfig" : {
            "$ref" : "#/components/schemas/DnsConfigDTO"
          },
          "domain" : {
            "type" : "string"
          },
          "extraOk" : {
            "type" : "boolean"
          },
          "message" : {
            "type" : "string"
          },
          "ok" : {
            "type" : "boolean"
          },
          "records" : {
            "type" : "array",
            "items" : {
              "$ref" : "#/components/schemas/DnsRecordCheckDTO"
            }
          },
          "subdomain" : {
            "type" : "string"
          }
        }
      },
      "DnsConfigDTO" : {
        "type" : "object",
        "properties" : {
          "dmarc" : {
            "type" : "string"
          },
          "dmarcName" : {
            "type" : "string"
          },
          "pdk1" : {
            "type" : "string"
          },
          "pdk1Name" : {
            "type" : "string"
          },
          "pdk2" : {
            "type" : "string"
          },
          "pdk2Name" : {
            "type" : "string"
          },
          "spf" : {
            "type" : "string"
          },
          "spfName" : {
            "type" : "string"
          }
        }
      },
      "DnsRecordCheckDTO" : {
        "type" : "object",
        "properties" : {
          "actualValue" : {
            "type" : "string"
          },
          "expectedValue" : {
            "type" : "string"
          },
          "group" : {
            "type" : "string"
          },
          "message" : {
            "type" : "string"
          },
          "name" : {
            "type" : "string"
          },
          "ok" : {
            "type" : "boolean"
          },
          "recordType" : {
            "type" : "string"
          },
          "status" : {
            "type" : "string"
          }
        }
      },
      "DuplicateDashboardRequestDTO" : {
        "type" : "object",
        "properties" : {
          "name" : {
            "maxLength" : 100,
            "minLength" : 0,
            "type" : "string",
            "description" : "Optional name for the duplicated dashboard. Defaults to '{original name} (Copy)'",
            "example" : "Dashboard Copy"
          }
        },
        "description" : "Request to duplicate a dashboard"
      },
      "EarningsSummaryDTO" : {
        "type" : "object",
        "properties" : {
          "activeFollowers" : {
            "type" : "integer",
            "description" : "Number of currently active (non-deleted) follower subscriptions",
            "format" : "int32"
          },
          "metaCopierFeePercent" : {
            "type" : "integer",
            "description" : "Percentage MetaCopier retains as platform fee (e.g. 30 means provider receives 70%)",
            "format" : "int32"
          },
          "totalCreditedNet" : {
            "type" : "number",
            "description" : "Net amount actually credited to the provider's project balance after MetaCopier fee deduction"
          },
          "totalEarnedGross" : {
            "type" : "number",
            "description" : "Total gross amount from all follower charges across all invoice statuses, before MetaCopier fee deduction"
          },
          "totalEarnedGrossPaid" : {
            "type" : "number",
            "description" : "Gross amount from PAID invoices only"
          },
          "totalEarnedGrossUnpaid" : {
            "type" : "number",
            "description" : "Gross amount from OPEN (unpaid) invoices only"
          },
          "totalEarnedGrossVoid" : {
            "type" : "number",
            "description" : "Gross amount from VOID (cancelled) invoices only"
          },
          "totalFollowers" : {
            "type" : "integer",
            "description" : "Total number of unique follower accounts ever seen, including deleted ones",
            "format" : "int32"
          }
        },
        "description" : "Aggregated earnings summary across all billing periods"
      },
      "FeatureApprovalDTO" : {
        "type" : "object",
        "properties" : {
          "activateApproval" : {
            "type" : "boolean",
            "description" : "Activate the approval. This property is always set to true.",
            "example" : true,
            "default" : true
          }
        },
        "description" : "DTO for approval feature (copier) (PRO)"
      },
      "FeatureBlockHedgingDTO" : {
        "type" : "object",
        "properties" : {
          "blockHedging" : {
            "type" : "boolean",
            "description" : "If true, the copier will skip opening a position when the slave account already has an open position with the same symbol but in the opposite direction (BUY vs SELL). This is useful for prop firms that prohibit hedging.",
            "example" : true,
            "default" : true
          }
        },
        "description" : "DTO for block hedging feature (copier)"
      },
      "FeatureBreakEvenDTO" : {
        "type" : "object",
        "properties" : {
          "reverse" : {
            "type" : "boolean",
            "description" : "If true and no reverseTriggerInPoints/reverseStopLossInPoints are set, the break-even logic operates in reverse using triggerInPoints/stopLossInPoints. If reverseTriggerInPoints/reverseStopLossInPoints are set, this field is ignored and both normal and reverse break-even run simultaneously.",
            "example" : false,
            "default" : false
          },
          "reverseStopLossInPoints" : {
            "type" : "integer",
            "description" : "Defines the distance in points from the entry price at which the take profit will be placed after the reverse break-even is triggered.",
            "format" : "int32",
            "example" : 20,
            "default" : 0
          },
          "reverseTriggerInPoints" : {
            "type" : "integer",
            "description" : "Specifies the number of points the trade must move against the position (in loss) to trigger the reverse break-even logic. When set together with reverseStopLossInPoints, the reverse break-even runs simultaneously with the normal break-even. A value of 0 disables the reverse trigger.",
            "format" : "int32",
            "example" : 30,
            "default" : 0
          },
          "stopLossInPoints" : {
            "type" : "integer",
            "description" : "Defines the distance in points from the entry price at which the stop loss will be placed after the break-even logic is triggered.",
            "format" : "int32",
            "example" : 20,
            "default" : 20
          },
          "symbolsConfiguration" : {
            "type" : "object",
            "additionalProperties" : {
              "$ref" : "#/components/schemas/FeatureBreakEvenDTO"
            },
            "description" : "Defines the break-even per symbol.",
            "example" : {
              "EURUSD" : {
                "stopLossInPoints" : 20,
                "triggerInPoints" : 30
              }
            }
          },
          "triggerInPoints" : {
            "type" : "integer",
            "description" : "Specifies the number of points required for the trade to trigger the break-even logic. Once the profit reaches this value, the stop loss will be adjusted. A value of 0 disables the trigger.",
            "format" : "int32",
            "example" : 30,
            "default" : 30
          }
        },
        "description" : "DTO for the break-even feature (copier/account) (PRO)"
      },
      "FeatureCopierFilterDTO" : {
        "type" : "object",
        "properties" : {
          "comment" : {
            "type" : "array",
            "description" : "Regex (case insensitive) applied to the comment field to filter. If multiple filters are specified, they are combined using an OR condition.",
            "items" : {
              "type" : "string",
              "description" : "Regex (case insensitive) applied to the comment field to filter. If multiple filters are specified, they are combined using an OR condition."
            }
          },
          "magicNumber" : {
            "type" : "array",
            "description" : "Regex (case insensitive) applied to magic number field (MetaTrader -> magic number, DXtrade/TradeLocker/MatchTrader/Binance/Bybit/Bitget/BloFin/OKX/TradeStation/Tradovate/Alpaca -> no field and CTrader -> label) to filter. If multiple filters are specified, they are combined using an OR condition.",
            "items" : {
              "type" : "string",
              "description" : "Regex (case insensitive) applied to magic number field (MetaTrader -> magic number, DXtrade/TradeLocker/MatchTrader/Binance/Bybit/Bitget/BloFin/OKX/TradeStation/Tradovate/Alpaca -> no field and CTrader -> label) to filter. If multiple filters are specified, they are combined using an OR condition."
            }
          },
          "maxLotSize" : {
            "type" : "number",
            "description" : "Maximum lot size on the master. If the master position lot size is greater than this value, the position will be skipped. Set to null or 0 to disable.",
            "format" : "double",
            "example" : 10.0
          },
          "minLotSize" : {
            "type" : "number",
            "description" : "Minimum lot size on the master. If the master position lot size is less than this value, the position will be skipped. Set to null or 0 to disable.",
            "format" : "double",
            "example" : 0.01
          }
        },
        "description" : "DTO for copier filter feature (copier)"
      },
      "FeatureDTO" : {
        "required" : [ "setting", "type" ],
        "type" : "object",
        "properties" : {
          "accountId" : {
            "type" : "string",
            "description" : "You have to set it during resource creation, after that, it is only read-only",
            "format" : "uuid"
          },
          "copierId" : {
            "type" : "string",
            "description" : "You have to set it during resource creation, after that, it is only read-only",
            "format" : "uuid"
          },
          "created" : {
            "type" : "string",
            "description" : "ISO 8601",
            "format" : "date-time",
            "readOnly" : true
          },
          "featureId" : {
            "type" : "string",
            "description" : "You have to set it during resource creation, after that, it is only read-only. Use this to attach copier features to a Signal Follower feature.",
            "format" : "uuid"
          },
          "id" : {
            "type" : "string",
            "format" : "uuid",
            "readOnly" : true
          },
          "projectId" : {
            "type" : "string",
            "description" : "You have to set it during resource creation, after that, it is only read-only",
            "format" : "uuid"
          },
          "setting" : {
            "$ref" : "#/components/schemas/FeatureSettingDTO"
          },
          "type" : {
            "$ref" : "#/components/schemas/FeatureTypeDTO"
          }
        }
      },
      "FeatureDailyProfitTargetDTO" : {
        "type" : "object",
        "properties" : {
          "autoResetIfBalanceIsBelow" : {
            "type" : "boolean",
            "description" : "Reset this target if the balance falls below the target. For example, after a withdrawal.",
            "default" : false
          },
          "dailyAbsoluteProfitTarget" : {
            "minimum" : 0.00,
            "exclusiveMinimum" : false,
            "type" : "number",
            "description" : "Enter a daily absolute profit target in account currency. If the target is reached, all positions will be closed (unless 'pauseInsteadOfClose' is enabled) and new ones will be blocked until the next day. Set to 0 to deactivate. For example if is set to 1300, the profit target is 1300 in the account currency.",
            "default" : 0
          },
          "dailyProfitTarget" : {
            "maximum" : 100.00,
            "exclusiveMaximum" : false,
            "minimum" : 0.00,
            "exclusiveMinimum" : false,
            "type" : "number",
            "description" : "Enter a daily target in %. If the target is reached, all positions will be closed (unless 'pauseInsteadOfClose' is enabled). New positions will not be copied until the next day, and any positions placed outside our system will be closed immediately (if 'pauseInsteadOfClose' is false). Set to 0 to deactivate.",
            "default" : 2.0
          },
          "dailyRelativeProfitTarget" : {
            "minimum" : 0.00,
            "exclusiveMinimum" : false,
            "type" : "number",
            "description" : "Enter a daily relative profit target in account currency. If the target is reached, all positions will be closed (unless 'pauseInsteadOfClose' is enabled) and new ones will be blocked until the next day. Set to 0 to deactivate. For example if is set to 300 and account balance is 1000, the profit target is 1300 in the account currency.",
            "default" : 0
          },
          "pauseInsteadOfClose" : {
            "type" : "boolean",
            "description" : "If set to 'true', when the profit target is reached, the copier will pause and stop opening new positions instead of closing all existing positions. The open positions will remain active. If set to 'false', all positions will be closed when the target is reached.",
            "default" : false
          },
          "resetOnBalanceChange" : {
            "type" : "boolean",
            "description" : "If set to 'false', balance changes (deposits and withdrawals) will NOT trigger a reset of this profit target. If set to 'true', any deposit or withdrawal will reset the profit target reference balance. This option allows you to maintain the profit target calculation even when adding or removing funds from the account.",
            "default" : true
          },
          "resetTime" : {
            "type" : "string",
            "description" : "ISO 8601. Set the reset time for the profit target. Only the time is considered, and the date is ignored.",
            "format" : "date-time",
            "default" : "2023-12-30T00:00:00Z"
          },
          "trackByOpenDate" : {
            "type" : "boolean",
            "description" : "If set to 'true', the daily profit target will be calculated based on the profit of trades that were OPENED on the current day (instead of the default equity-vs-balance comparison). This is useful for prop firm consistency rules (e.g. Aqua Funded) where a single day's profits (by open date) may not exceed a certain percentage.",
            "default" : false
          }
        },
        "description" : "DTO for daily profit target feature (account)"
      },
      "FeatureDataCollectorDTO" : {
        "required" : [ "activateDataCollector", "collectionIntervalSeconds", "normalizeValues", "recordBalance", "recordEquity", "recordFloatingPnL" ],
        "type" : "object",
        "properties" : {
          "activateDataCollector" : {
            "type" : "boolean",
            "description" : "Activate the data collector feature to record equity, profit, and balance time series data.",
            "example" : true,
            "default" : true
          },
          "collectionIntervalSeconds" : {
            "minimum" : 30,
            "type" : "integer",
            "description" : "Collection interval in seconds. Defines how frequently the system checks and records equity, profit, and balance data. Note: Data is only saved when values have changed from the previous record to optimize storage and reduce redundancy.",
            "format" : "int32",
            "example" : 60,
            "default" : 60
          },
          "normalizeValues" : {
            "type" : "boolean",
            "description" : "If true, normalizes all values when fetching data via REST endpoint to hide real account size. Uses the first record's balance (or equity if balance not recorded, or floating PnL if neither recorded) as reference point and scales it to 100,000. The same scaling factor is then applied to ALL records, preserving relative performance and growth patterns while obscuring actual account values. Example: if first balance is 50,000, all values are doubled (factor 2.0), making first balance = 100,000, but subsequent balances scale proportionally. Data is always stored as-is without normalization. Use this feature when sharing performance data without exposing real capital.",
            "example" : false,
            "default" : false
          },
          "recordBalance" : {
            "type" : "boolean",
            "description" : "If true, records account balance (closed positions only). Balance represents the account value based on closed trades only.",
            "example" : true,
            "default" : true
          },
          "recordEquity" : {
            "type" : "boolean",
            "description" : "If true, records account equity (including floating PnL). Equity represents the current account value including open positions.",
            "example" : true,
            "default" : true
          },
          "recordFloatingPnL" : {
            "type" : "boolean",
            "description" : "If true, records floating PnL separately. This is the unrealized profit/loss from currently open positions.",
            "example" : true,
            "default" : true
          },
          "retentionDays" : {
            "type" : "integer",
            "description" : "Data retention period in days. This is a fixed system value and cannot be modified by users.",
            "format" : "int32",
            "readOnly" : true,
            "example" : 90
          }
        },
        "description" : "DTO for the Data Collector feature (account) (PRO)"
      },
      "FeatureDedicatedIpDTO" : {
        "required" : [ "dedicatedProxyServerId" ],
        "type" : "object",
        "properties" : {
          "dedicatedProxyServerId" : {
            "type" : "integer",
            "description" : "Enter an dedicated proxy server id (see \"FeatureDedicatedIpPoolDTO\")",
            "format" : "int32"
          }
        },
        "description" : "DTO for assigning a dedicated IP feature (account) (PRO)"
      },
      "FeatureDedicatedIpPoolDTO" : {
        "required" : [ "poolSize" ],
        "type" : "object",
        "properties" : {
          "dedicatedProxyServerIds" : {
            "type" : "object",
            "additionalProperties" : {
              "type" : "array",
              "description" : "Read-only. The system will reserve the proxy servers per region and list them in this field.",
              "readOnly" : true,
              "items" : {
                "$ref" : "#/components/schemas/ProxyDTO"
              }
            },
            "description" : "Read-only. The system will reserve the proxy servers per region and list them in this field.",
            "readOnly" : true
          },
          "poolSize" : {
            "type" : "object",
            "additionalProperties" : {
              "type" : "integer",
              "description" : "Specify the number of dedicated proxy server (IPs) per region you want. Use \"FeatureDedicatedIpDTO\" to assign an proxy server (IP) to an account.",
              "format" : "int32"
            },
            "description" : "Specify the number of dedicated proxy server (IPs) per region you want. Use \"FeatureDedicatedIpDTO\" to assign an proxy server (IP) to an account."
          }
        },
        "description" : "DTO for defining a pool of dedicated IPs feature (project) (PRO)"
      },
      "FeatureDelayedExecutionDTO" : {
        "type" : "object",
        "properties" : {
          "maxDelayClose" : {
            "maximum" : 3600,
            "minimum" : 0,
            "type" : "number",
            "description" : "Maximum delay in seconds (with millisecond resolution) before closing a trade. Maximum allowed value is 3600 seconds (60 minutes).",
            "example" : 40.125,
            "default" : 0
          },
          "maxDelayOpen" : {
            "maximum" : 3600,
            "minimum" : 0,
            "type" : "number",
            "description" : "Maximum delay in seconds (with millisecond resolution) before opening a trade. Maximum allowed value is 3600 seconds (60 minutes).",
            "example" : 40.125,
            "default" : 0
          },
          "minDelayClose" : {
            "maximum" : 3600,
            "minimum" : 0,
            "type" : "number",
            "description" : "Minimum delay in seconds (with millisecond resolution) before closing a trade. A value of 0 means no delay.",
            "example" : 10.02,
            "default" : 0
          },
          "minDelayOpen" : {
            "maximum" : 3600,
            "minimum" : 0,
            "type" : "number",
            "description" : "Minimum delay in seconds (with millisecond resolution) before opening a trade. A value of 0 means no delay.",
            "example" : 10.02,
            "default" : 0
          },
          "symbolsConfiguration" : {
            "type" : "object",
            "additionalProperties" : {
              "$ref" : "#/components/schemas/FeatureDelayedExecutionDTO"
            },
            "description" : "Defines the delay execution per symbol.",
            "example" : {
              "EURUSD" : {
                "maxDelayClose" : 40,
                "maxDelayOpen" : 40,
                "minDelayClose" : 10,
                "minDelayOpen" : 10
              }
            }
          }
        },
        "description" : "DTO for the Delayed Execution feature (copier) (PRO)"
      },
      "FeatureExitSignalOverrideDTO" : {
        "required" : [ "onlyIfTpSlAreSet" ],
        "type" : "object",
        "properties" : {
          "ignoreForSeconds" : {
            "minimum" : 0,
            "type" : "integer",
            "description" : "Specifies the number of seconds to wait before closing the trade. This is useful if you want the slave account to hold the position until the Take Profit (TP) level is reached. A value of 0 indicates that the exit signal will be ignored indefinitely.",
            "format" : "int32",
            "example" : 5,
            "default" : 5
          },
          "onlyIfTpSlAreSet" : {
            "type" : "boolean",
            "description" : "Indicates whether the exit signal should only be ignored if both Take Profit (TP) and Stop Loss (SL) levels are set on the trade.",
            "example" : true,
            "default" : true
          }
        },
        "description" : "DTO for configuring the exit signal override feature (copier)"
      },
      "FeatureFallbackSettingDTO" : {
        "type" : "object",
        "properties" : {
          "allowedRegions" : {
            "type" : "array",
            "description" : "A list of allowed regions to which the account can be moved if an error or issue occurs. When an account is moved, another IP address will be assigned to it. If the list is empty, all regions are allowed.",
            "items" : {
              "$ref" : "#/components/schemas/RegionDTO"
            }
          },
          "noFallback" : {
            "type" : "boolean",
            "description" : "Indicates whether fallback behavior is disabled. If set to true, the account will not be moved to another region in case of errors or issues. If fallback is enabled, another IP address will be assigned to the account when it is moved.",
            "example" : false,
            "default" : false
          }
        },
        "description" : "DTO for fallback setting feature (account and project). If applied to a project, the fallback behavior will be applied to all accounts within that project."
      },
      "FeatureHftModeDTO" : {
        "type" : "object",
        "properties" : {
          "activateHftMode" : {
            "type" : "boolean",
            "description" : "Activate the hft mode. This property is always set to true.",
            "example" : true,
            "default" : true
          }
        },
        "description" : "DTO to activate the hft mode feature (account) (PRO)"
      },
      "FeatureInvestorDTO" : {
        "type" : "object",
        "properties" : {
          "profitSharePercentage" : {
            "type" : "number",
            "description" : "Profit share percentage that goes to the traders after MetaCopier fee deduction (0-100). Example: 30.00 means 30% profit share to traders."
          },
          "status" : {
            "type" : "string",
            "description" : "Status of an investor within the investor program",
            "readOnly" : true,
            "enum" : [ "PENDING", "ACTIVE", "SUSPENDED" ]
          },
          "traderFeatures" : {
            "type" : "array",
            "description" : "List of trader features this investor is following. The investor can choose multiple traders.",
            "items" : {
              "$ref" : "#/components/schemas/FeatureDTO"
            }
          }
        },
        "description" : "DTO for investor program investor feature (account)"
      },
      "FeatureKeepAliveTradeDTO" : {
        "required" : [ "cronExpressions", "symbol" ],
        "type" : "object",
        "properties" : {
          "closeAfterInSeconds" : {
            "maximum" : 3600,
            "minimum" : 0,
            "type" : "integer",
            "description" : "Defines the duration in seconds after which the opened trade will be closed automatically.",
            "format" : "int32",
            "default" : 0
          },
          "cronExpressions" : {
            "type" : "array",
            "description" : "Cron expressions to trigger the trade (UTC time)",
            "items" : {
              "type" : "string",
              "description" : "Cron expressions to trigger the trade (UTC time)"
            }
          },
          "symbol" : {
            "type" : "string",
            "description" : "Define the symbol for which the trades will be opened. The opened lot size is the minimum size of the symbol."
          }
        },
        "description" : "DTO for keep alive trade feature (account) (PRO)"
      },
      "FeatureLiveDelayDTO" : {
        "type" : "object",
        "properties" : {
          "resetIntervalMinutes" : {
            "maximum" : 1440,
            "type" : "integer",
            "description" : "Time interval in minutes after which the skip counter resets. The timer starts from the last time an order was opened. For example, if set to 120, the skip counter will reset every 120 minutes from the last order. A value of 0 disables time-based reset (the counter will only reset via resetOnPositionClose if enabled). Maximum value is 1440 minutes (24 hours).",
            "format" : "int32",
            "example" : 120,
            "default" : 120
          },
          "resetOnPositionClose" : {
            "type" : "boolean",
            "description" : "If true, the skip counter resets automatically when a copied position closes. For example, if skipOrdersCount is 1, order 1 is skipped, order 2 is copied, and when order 2 closes, the counter resets so the next order will be skipped again. This can be used with resetIntervalMinutes=0 to disable time-based reset and only reset on position close.",
            "example" : false,
            "default" : false
          },
          "skipOrdersCount" : {
            "type" : "integer",
            "description" : "Number of orders to skip from the master account. For example, if set to 3, the first 3 orders will be skipped and only subsequent orders will be copied. A value of 0 means the feature is deactivated (no live delay).",
            "format" : "int32",
            "example" : 3,
            "default" : 3
          },
          "symbolsConfiguration" : {
            "type" : "object",
            "additionalProperties" : {
              "$ref" : "#/components/schemas/FeatureLiveDelayDTO"
            },
            "description" : "Defines the live delay configuration per symbol. Each symbol can have its own skip count and reset interval.",
            "example" : {
              "EURUSD" : {
                "resetIntervalMinutes" : 120,
                "skipOrdersCount" : 3
              }
            }
          },
          "trackByDirection" : {
            "type" : "boolean",
            "description" : "If true, BUY and SELL orders are tracked separately. For example, if skipOrdersCount is 3, the first 3 BUY orders AND the first 3 SELL orders will be skipped (6 total). If false (default), direction is ignored and the first 3 orders are skipped regardless of direction.",
            "example" : false,
            "default" : false
          }
        },
        "description" : "DTO for live delay feature (copier)"
      },
      "FeatureMaintenanceWindowDTO" : {
        "required" : [ "endTime", "startTime" ],
        "type" : "object",
        "properties" : {
          "accountType" : {
            "$ref" : "#/components/schemas/AccountTypeDTO"
          },
          "affectedAccountIds" : {
            "type" : "array",
            "description" : "List of account IDs that were affected by this maintenance window. Used to restart/resume only these accounts when the window ends.",
            "items" : {
              "type" : "string",
              "description" : "List of account IDs that were affected by this maintenance window. Used to restart/resume only these accounts when the window ends.",
              "format" : "uuid"
            }
          },
          "affectedCopierStates" : {
            "type" : "object",
            "additionalProperties" : {
              "$ref" : "#/components/schemas/CopierStateDTO"
            },
            "description" : "Map of copier IDs to their original states before maintenance. Used to restore copiers to their exact previous state."
          },
          "broker" : {
            "maxLength" : 255,
            "minLength" : 0,
            "type" : "string",
            "description" : "Is only applied to a specific broker, for example, 'ICMarkets.*' (case non sensitive). For all brokers, you can enter '.*' or null (this is a regex)"
          },
          "closePositionStrategy" : {
            "type" : "string",
            "description" : "Strategy for closing positions during maintenance window. Default is DO_NOT_CLOSE.",
            "enum" : [ "DO_NOT_CLOSE", "CLOSE_ALL", "CLOSE_ALL_IF_PROFIT" ]
          },
          "enabled" : {
            "type" : "boolean",
            "description" : "Whether the maintenance window is enabled. Default is true."
          },
          "endTime" : {
            "type" : "string",
            "description" : "End time of the maintenance window.",
            "format" : "date-time",
            "example" : "2025-01-01T06:00:00Z"
          },
          "entryActionsExecuted" : {
            "type" : "boolean",
            "description" : "Tracks whether entry actions (close positions, stop accounts/pause copiers) have been executed for this maintenance window instance."
          },
          "maintenanceAction" : {
            "type" : "string",
            "description" : "Action to perform during maintenance window. Default is PAUSE_COPIERS.",
            "enum" : [ "STOP_ACCOUNTS", "PAUSE_COPIERS" ]
          },
          "positionsClosedForAccounts" : {
            "uniqueItems" : true,
            "type" : "array",
            "description" : "Set of account IDs for which positions have already been closed during this maintenance window.",
            "items" : {
              "type" : "string",
              "description" : "Set of account IDs for which positions have already been closed during this maintenance window.",
              "format" : "uuid"
            }
          },
          "startTime" : {
            "type" : "string",
            "description" : "Start time of the maintenance window.",
            "format" : "date-time",
            "example" : "2025-01-01T02:00:00Z"
          }
        },
        "description" : "DTO for defining a maintenance window (project)"
      },
      "FeatureMarginCapDTO" : {
        "type" : "object",
        "properties" : {
          "behavior" : {
            "type" : "string",
            "description" : "Defines the behavior when a new trade would exceed the margin cap. REDUCE_LOT_SIZE: automatically calculates the maximum lot size that fits within the remaining margin. SKIP_TRADE: rejects/skips the trade entirely if it would exceed the cap.",
            "example" : "REDUCE_LOT_SIZE",
            "default" : "REDUCE_LOT_SIZE",
            "enum" : [ "REDUCE_LOT_SIZE", "SKIP_TRADE" ]
          },
          "leverageOverride" : {
            "type" : "integer",
            "description" : "Optional leverage override used in the margin calculation. When null or 0, the leverage is auto-detected (broker per-symbol leverage if reported, otherwise the account leverage). When > 0, the given value is used as-is (e.g. set to 30 to force a 1:30 calculation even if the broker reports 1:100). Useful when the broker does not expose per-symbol leverage overrides (e.g. metals/CFDs).",
            "format" : "int32",
            "example" : 30,
            "default" : 0
          },
          "marginCapPercentage" : {
            "type" : "number",
            "description" : "Maximum allowed margin usage as a percentage of the account balance. For example, 20 means the total used margin must not exceed 20% of the account balance. If set to 0, the feature is disabled.",
            "example" : 20,
            "default" : 0
          },
          "scope" : {
            "type" : "string",
            "description" : "Defines whether the margin cap applies cumulatively across all open positions or per individual trade. CUMULATIVE: the sum of all open positions must not exceed the margin cap. PER_TRADE: each individual trade must not exceed the margin cap independently.",
            "example" : "CUMULATIVE",
            "default" : "CUMULATIVE",
            "enum" : [ "CUMULATIVE", "PER_TRADE" ]
          },
          "symbolsConfiguration" : {
            "type" : "object",
            "additionalProperties" : {
              "$ref" : "#/components/schemas/FeatureMarginCapDTO"
            },
            "description" : "Defines margin cap configuration per symbol or asset class. Symbol-specific configuration takes priority over the global setting.",
            "example" : {
              "XAUUSD" : {
                "marginCapPercentage" : 10
              }
            }
          }
        },
        "description" : "DTO for margin cap feature (copier) (PRO)"
      },
      "FeatureMartingaleStrategyDTO" : {
        "type" : "object",
        "properties" : {
          "enableMartingaleStrategy" : {
            "type" : "boolean",
            "description" : "Adjust the lot size based on the Martingale multiplier. If there is a significant difference in balance/equity between the master and slave accounts, the lot size on the slave account may be rounded down. For example, if trades of 0.02 and 0.04 lots are placed on the master account (balance 4000 USD), a standard copier would open 0.01 and 0.01 lots on the slave account (balance 1000 USD - which is incorrect). However, if this option is activated, it will open 0.01 and 0.02 lots. Default is false. This can be overridden per symbol using symbolsConfiguration.",
            "example" : true,
            "default" : false
          },
          "symbolsConfiguration" : {
            "type" : "object",
            "additionalProperties" : {
              "$ref" : "#/components/schemas/FeatureMartingaleStrategyDTO"
            },
            "description" : "Defines the martingale strategy setting per symbol. Each symbol can have its own enabled/disabled setting that overrides the global setting.",
            "example" : {
              "XAUUSD" : {
                "enableMartingaleStrategy" : true
              }
            }
          }
        },
        "description" : "DTO for martingale strategy feature (copier)"
      },
      "FeatureMasanielloDTO" : {
        "required" : [ "bankrollBase", "lotRoundingMode", "outcomePolicy", "partialWinPolicy", "payoutModel", "winThresholdBase" ],
        "type" : "object",
        "properties" : {
          "assumedPointRisk" : {
            "maximum" : 10000,
            "exclusiveMaximum" : false,
            "minimum" : 1,
            "exclusiveMinimum" : false,
            "type" : "number",
            "description" : "Expected point movement used to convert money stakes to lot sizes. Represents the typical price movement in points (MetaTrader minimal price change) for position sizing calculations. Larger values = more conservative lot sizes (smaller positions for the same stake).",
            "example" : 100,
            "default" : 100
          },
          "autoResetOnSeriesComplete" : {
            "type" : "boolean",
            "description" : "Reset after completing all events.",
            "example" : true,
            "default" : true
          },
          "autoTuneBoundsValid" : {
            "type" : "boolean"
          },
          "bankrollBase" : {
            "type" : "string",
            "description" : "Defines the base used for bankroll percentage: BALANCE, EQUITY, FREE_MARGIN.",
            "example" : "EQUITY",
            "default" : "EQUITY",
            "enum" : [ "BALANCE", "EQUITY", "FREE_MARGIN" ]
          },
          "bankrollPercentage" : {
            "maximum" : 100.0,
            "exclusiveMaximum" : false,
            "minimum" : 0.1,
            "exclusiveMinimum" : false,
            "type" : "number",
            "description" : "Percentage of account base (balance/equity/free margin) used as bankroll for one series.",
            "example" : 5.0,
            "default" : 5.0
          },
          "cooldownAfterResetMinutes" : {
            "maximum" : 1440,
            "minimum" : 0,
            "type" : "integer",
            "description" : "Cooldown period in minutes before starting a new series after reset. 0 = no cooldown.",
            "format" : "int32",
            "example" : 0,
            "default" : 0
          },
          "excludeBreakEvenTrades" : {
            "type" : "boolean",
            "description" : "If true, break-even trades do not consume an event in the series.",
            "example" : true,
            "default" : true
          },
          "expectedLossRMultiple" : {
            "maximum" : 0.0,
            "exclusiveMaximum" : false,
            "minimum" : -1.0,
            "exclusiveMinimum" : false,
            "type" : "number",
            "description" : "Expected loss per losing trade as R multiple. Default -1.0 means full risk is lost. For binary options use -1.0. For Forex with SL, typically -1.0. Use values like -0.5 if you expect partial losses on average.",
            "example" : -1.0,
            "default" : -1.0
          },
          "expectedPayoutFactor" : {
            "maximum" : 5.0,
            "exclusiveMaximum" : false,
            "minimum" : 0.01,
            "exclusiveMinimum" : false,
            "type" : "number",
            "description" : "Expected payout factor for fixed payout systems (binary, etc). Example: 0.75 means +75% of risk on win. Used when payoutModel=PAYOUT_FACTOR.",
            "example" : 0.75,
            "default" : 0.75
          },
          "expectedRMultiple" : {
            "maximum" : 10.0,
            "exclusiveMaximum" : false,
            "minimum" : 0.05,
            "exclusiveMinimum" : false,
            "type" : "number",
            "description" : "Expected average profit per win, expressed as R multiple. Example: 1.0 means +1R average win. Used when payoutModel=R_MULTIPLE.",
            "example" : 1.0,
            "default" : 1.0
          },
          "expectedWins" : {
            "maximum" : 100,
            "minimum" : 1,
            "type" : "integer",
            "description" : "Expected number of wins in one series. Must be <= totalEvents.",
            "format" : "int32",
            "example" : 6,
            "default" : 6
          },
          "expectedWinsValid" : {
            "type" : "boolean"
          },
          "lotRoundingMode" : {
            "type" : "string",
            "description" : "How to round the computed lot size to the lot step.",
            "example" : "DOWN",
            "default" : "DOWN",
            "enum" : [ "DOWN", "UP", "NEAREST" ]
          },
          "lotStep" : {
            "maximum" : 100.0,
            "exclusiveMaximum" : false,
            "minimum" : 0.0001,
            "exclusiveMinimum" : false,
            "type" : "number",
            "description" : "Lot step to round lots to, e.g. 0.01 for Forex.",
            "example" : 0.01,
            "default" : 0.01
          },
          "maxConsecutiveLosses" : {
            "maximum" : 50,
            "minimum" : 0,
            "type" : "integer",
            "description" : "Maximum consecutive losses allowed before forcing series reset as safety breaker. 0 = disabled.",
            "format" : "int32",
            "example" : 0,
            "default" : 0
          },
          "maxExpectedWins" : {
            "maximum" : 100,
            "minimum" : 1,
            "type" : "integer",
            "description" : "Maximum expectedWins when auto-tuning is enabled. Null means no cap besides totalEvents.",
            "format" : "int32",
            "example" : 10
          },
          "maximumLotSize" : {
            "maximum" : 1000.0,
            "exclusiveMaximum" : false,
            "minimum" : 0.01,
            "exclusiveMinimum" : false,
            "type" : "number",
            "description" : "Maximum lot size allowed.",
            "example" : 10.0,
            "default" : 10.0
          },
          "minExpectedWins" : {
            "maximum" : 100,
            "minimum" : 1,
            "type" : "integer",
            "description" : "Minimum expectedWins when auto-tuning is enabled.",
            "format" : "int32",
            "example" : 1,
            "default" : 1
          },
          "minimumLotSize" : {
            "maximum" : 100.0,
            "exclusiveMaximum" : false,
            "minimum" : 0.0,
            "exclusiveMinimum" : false,
            "type" : "number",
            "description" : "Minimum lot size allowed.",
            "example" : 0.01,
            "default" : 0.01
          },
          "minimumTradesForHistoricalWinRate" : {
            "maximum" : 500,
            "minimum" : 1,
            "type" : "integer",
            "description" : "Minimum number of historical trades required before using historical win rate. If fewer trades exist, falls back to manual expectedWins.",
            "format" : "int32",
            "example" : 20,
            "default" : 20
          },
          "outcomePolicy" : {
            "type" : "string",
            "description" : "Defines how trades are classified (win/loss/breakeven).",
            "example" : "THRESHOLD",
            "default" : "THRESHOLD",
            "enum" : [ "THRESHOLD", "SIGN", "R_BASED" ]
          },
          "partialWinPolicy" : {
            "type" : "string",
            "description" : "Defines how partial closes (multiple TPs, manual partial close) are handled for outcome classification.",
            "example" : "IGNORE",
            "default" : "IGNORE",
            "enum" : [ "IGNORE", "COUNT_AS_WIN", "COUNT_AS_LOSS", "PROPORTIONAL" ]
          },
          "payoutModel" : {
            "type" : "string",
            "description" : "Defines how expected profit per win is modeled.",
            "example" : "R_MULTIPLE",
            "default" : "R_MULTIPLE",
            "enum" : [ "R_MULTIPLE", "PAYOUT_FACTOR", "REALIZED_R" ]
          },
          "resetOnBankrollDepleted" : {
            "type" : "boolean",
            "description" : "Reset series if bankroll is depleted.",
            "example" : true,
            "default" : true
          },
          "resetOnTargetReached" : {
            "type" : "boolean",
            "description" : "Reset series automatically when target profit is reached early.",
            "example" : true,
            "default" : true
          },
          "statisticsLookBackDays" : {
            "maximum" : 365,
            "minimum" : 0,
            "type" : "integer",
            "description" : "Look-back days for stats (0 = only current series).",
            "format" : "int32",
            "example" : 30,
            "default" : 30
          },
          "symbolsConfiguration" : {
            "type" : "object",
            "additionalProperties" : {
              "$ref" : "#/components/schemas/FeatureMasanielloDTO"
            },
            "description" : "Symbol-specific overrides for Masaniello settings. Only changed fields need to be provided.",
            "example" : {
              "EURUSD" : {
                "expectedWins" : 7
              }
            }
          },
          "targetProfitPercentage" : {
            "maximum" : 1000.0,
            "exclusiveMaximum" : false,
            "minimum" : 1.0,
            "exclusiveMinimum" : false,
            "type" : "number",
            "description" : "Target profit percentage relative to bankroll. Example: 50 means +50% of the bankroll.",
            "example" : 50.0,
            "default" : 50.0
          },
          "totalEvents" : {
            "maximum" : 100,
            "minimum" : 2,
            "type" : "integer",
            "description" : "Total number of trades (events) in one Masaniello series.",
            "format" : "int32",
            "example" : 10,
            "default" : 10
          },
          "useHistoricalWinRate" : {
            "type" : "boolean",
            "description" : "If true, system adjusts expectedWins based on historical win rate.",
            "example" : false,
            "default" : false
          },
          "winRateSmoothingFactor" : {
            "maximum" : 1.0,
            "exclusiveMaximum" : false,
            "minimum" : 0.0,
            "exclusiveMinimum" : false,
            "type" : "number",
            "description" : "Smoothing factor for historical win-rate adjustment (0..1). Higher means faster adaptation.",
            "example" : 0.3,
            "default" : 0.3
          },
          "winThresholdBase" : {
            "type" : "string",
            "description" : "Defines what winThresholdPercentage is applied to.",
            "example" : "RISK",
            "default" : "RISK",
            "enum" : [ "RISK", "NOTIONAL", "ABSOLUTE" ]
          },
          "winThresholdPercentage" : {
            "maximum" : 100.0,
            "exclusiveMaximum" : false,
            "minimum" : 0.0,
            "exclusiveMinimum" : false,
            "type" : "number",
            "description" : "Trade counts as WIN if profit >= winThresholdPercentage% of base (risk or notional), depending on winThresholdBase.",
            "example" : 0.0,
            "default" : 0.0
          }
        },
        "description" : "DTO for the Masaniello money management feature (copier) (PRO)"
      },
      "FeatureMaxLotSizeDTO" : {
        "type" : "object",
        "properties" : {
          "checkMasterLotSize" : {
            "type" : "boolean",
            "description" : "If true, the max lot size check will compare against the master account's original position lot size instead of the calculated lot size. Only active when skipIfExceedsMax is true.",
            "example" : false,
            "default" : false
          },
          "maxLotSize" : {
            "type" : "number",
            "description" : "Sets the global max lot size for each position for all symbols. If a position exceeds this size, it will be adjusted to this max limit. This setting will override the copier's max lot size. A value of 0 means deactivated.",
            "example" : 0.0,
            "default" : 0.0
          },
          "skipIfExceedsMax" : {
            "type" : "boolean",
            "description" : "If true, positions that exceed the max lot size will be skipped instead of being limited to the max lot size.",
            "example" : false,
            "default" : false
          },
          "symbolsConfiguration" : {
            "type" : "object",
            "additionalProperties" : {
              "$ref" : "#/components/schemas/FeatureMaxLotSizeDTO"
            },
            "description" : "Defines the max lot size per symbol.",
            "example" : {
              "EURUSD" : {
                "maxLotSize" : 1.0
              }
            }
          }
        },
        "description" : "DTO for max lot size feature (copier)"
      },
      "FeatureMaxOpenPositionsDTO" : {
        "type" : "object",
        "properties" : {
          "maxOpenPositions" : {
            "type" : "integer",
            "description" : "Specifies the global maximum number of open positions allowed across all symbols. If this limit is reached, no new positions will be opened until existing positions are closed. This setting will override the copier's multiplier. A value of 0 disables this feature, allowing unlimited open positions.",
            "format" : "int32",
            "example" : 10,
            "default" : 0
          },
          "maxPositionsInTimeWindow" : {
            "type" : "integer",
            "description" : "Maximum number of positions allowed to be opened within the specified time window. For example, if set to 1 with a 120-second time window, only 1 position can be opened every 2 minutes. If multiple orders arrive simultaneously, only the first N orders (based on this value) will be taken, and the rest will be skipped until the time window expires. A value of 0 disables this time-based throttling. Works at both copier and account levels.",
            "format" : "int32",
            "example" : 1,
            "default" : 0
          },
          "symbolsConfiguration" : {
            "type" : "object",
            "additionalProperties" : {
              "$ref" : "#/components/schemas/FeatureMaxOpenPositionsDTO"
            },
            "description" : "Defines the maximum number of open positions per symbol. The total number of open positions across all symbols is subject to the general maxOpenPositions limit.",
            "example" : {
              "EURUSD" : {
                "maxOpenPositions" : 10
              }
            }
          },
          "timeWindowSeconds" : {
            "type" : "integer",
            "description" : "Time window in seconds for the position throttling. Works together with maxPositionsInTimeWindow to limit how many positions can be opened in a given time period. For example, with maxPositionsInTimeWindow=1 and timeWindowSeconds=120, only 1 position can be opened every 2 minutes. Works at both copier and account levels.",
            "format" : "int32",
            "example" : 120,
            "default" : 0
          }
        },
        "description" : "DTO for max open positions feature (copier/account)"
      },
      "FeatureMaximumLotDTO" : {
        "type" : "object",
        "properties" : {
          "maximumLot" : {
            "type" : "number",
            "description" : "When enabled, the total lot size of all open positions (related to this copier) will not exceed this value, new positions will be skipped until existing positions are closed. This setting will override the copier's maximum lot. A value of 0 means deactivated.",
            "example" : 0.0,
            "default" : 0.0
          },
          "symbolsConfiguration" : {
            "type" : "object",
            "additionalProperties" : {
              "$ref" : "#/components/schemas/FeatureMaximumLotDTO"
            },
            "description" : "Defines the maximum lot size per symbol.",
            "example" : {
              "EURUSD" : {
                "maximumLot" : 1.0
              }
            }
          }
        },
        "description" : "DTO for maximum lot feature (copier)"
      },
      "FeatureMinimumHoldingTimeDTO" : {
        "type" : "object",
        "properties" : {
          "minimumHoldSeconds" : {
            "minimum" : 0,
            "type" : "integer",
            "description" : "Minimum number of seconds a copied trade must stay open before the exit signal from the master account can be executed on the slave account. Example: if this value is set to 30 and the master opens and closes a position after 2 seconds, the slave will keep the position open for the full 30 seconds. 0 means deactivated",
            "format" : "int32",
            "example" : 30,
            "default" : 5
          },
          "symbolsConfiguration" : {
            "type" : "object",
            "additionalProperties" : {
              "$ref" : "#/components/schemas/FeatureMinimumHoldingTimeDTO"
            },
            "description" : "Defines the minimum holding time for each symbol.",
            "example" : {
              "EURUSD" : {
                "minimumHoldSeconds" : 5
              }
            }
          }
        },
        "description" : "DTO for configuring the minimum holding time feature (copier)"
      },
      "FeatureMonthlyProfitTargetDTO" : {
        "type" : "object",
        "properties" : {
          "autoResetIfBalanceIsBelow" : {
            "type" : "boolean",
            "description" : "Reset this target if the balance falls below the target. For example, after a withdrawal.",
            "default" : false
          },
          "monthlyAbsoluteProfitTarget" : {
            "minimum" : 0.00,
            "exclusiveMinimum" : false,
            "type" : "number",
            "description" : "Enter a monthly absolute profit target in account currency. If the target is reached, all positions will be closed (unless 'pauseInsteadOfClose' is enabled) and new ones will be blocked until the next month. Set to 0 to deactivate.",
            "default" : 0
          },
          "monthlyProfitTarget" : {
            "maximum" : 100.00,
            "exclusiveMaximum" : false,
            "minimum" : 0.00,
            "exclusiveMinimum" : false,
            "type" : "number",
            "description" : "Enter a monthly target in %. If the target is reached, all positions will be closed (unless 'pauseInsteadOfClose' is enabled). New positions will not be copied until the next month, and any positions placed outside system will be closed immediately (if 'pauseInsteadOfClose' is false). Set to 0 to deactivate.",
            "default" : 10.0
          },
          "monthlyRelativeProfitTarget" : {
            "minimum" : 0.00,
            "exclusiveMinimum" : false,
            "type" : "number",
            "description" : "Enter a monthly relative profit target in account currency. If the target is reached, all positions will be closed (unless 'pauseInsteadOfClose' is enabled) and new ones will be blocked until the next month. Set to 0 to deactivate.",
            "default" : 0
          },
          "pauseInsteadOfClose" : {
            "type" : "boolean",
            "description" : "If set to 'true', when the profit target is reached, the copier will pause and stop opening new positions instead of closing all existing positions. The open positions will remain active. If set to 'false', all positions will be closed when the target is reached.",
            "default" : false
          },
          "resetOnBalanceChange" : {
            "type" : "boolean",
            "description" : "If set to 'false', balance changes (deposits and withdrawals) will NOT trigger a reset of this profit target. If set to 'true', any deposit or withdrawal will reset the profit target reference balance. This option allows you to maintain the profit target calculation even when adding or removing funds from the account.",
            "default" : true
          }
        },
        "description" : "DTO for monthly profit target feature (account)"
      },
      "FeatureMultiplierDTO" : {
        "type" : "object",
        "properties" : {
          "fixMasterBalanceAndEquity" : {
            "type" : "integer",
            "description" : "Set the master balance and equity to the specified value for lot size calculation. A value of 0 means deactivated. If set to 1000, the lot size calculation will use 1000 as the master balance/equity. This allows for flexible lot size calculations per symbol within the multiplier feature.",
            "format" : "int32",
            "example" : 0,
            "default" : 0
          },
          "fixSlaveBalanceAndEquity" : {
            "type" : "integer",
            "description" : "Set the slave balance and equity to the specified value for lot size calculation. A value of 0 means deactivated. If set to 1000, the lot size calculation will use 1000 as the slave balance/equity. This allows for flexible lot size calculations per symbol within the multiplier feature.",
            "format" : "int32",
            "example" : 0,
            "default" : 0
          },
          "fixedLotSize" : {
            "type" : "number",
            "description" : "Set the lot size to a specific value, only applicable when the scaleType is set to '3' (Fixed lot size).",
            "example" : 0.01,
            "default" : 0.01
          },
          "multiplier" : {
            "maximum" : 999.999,
            "exclusiveMaximum" : false,
            "minimum" : 0.001,
            "exclusiveMinimum" : false,
            "type" : "number",
            "description" : "Specifies the global multiplier applied to all symbols. This setting will override the copier's multiplier.",
            "example" : 1.0,
            "default" : 0
          },
          "scaleType" : {
            "$ref" : "#/components/schemas/ScaleTypeDTO"
          },
          "symbolsConfiguration" : {
            "type" : "object",
            "additionalProperties" : {
              "$ref" : "#/components/schemas/FeatureMultiplierDTO"
            },
            "description" : "Defines the multiplier for each symbol.",
            "example" : {
              "EURUSD" : {
                "multiplier" : 1.0
              }
            }
          }
        },
        "description" : "DTO for multiplier feature (copier)"
      },
      "FeatureMyHomeIpDTO" : {
        "required" : [ "host", "password", "username" ],
        "type" : "object",
        "properties" : {
          "host" : {
            "type" : "string",
            "description" : "Your IP address or DNS hostname."
          },
          "httpPort" : {
            "type" : "integer",
            "description" : "The port number for HTTP proxy.",
            "format" : "int32"
          },
          "password" : {
            "type" : "string",
            "description" : "The password for SOCKS/HTTP authentication."
          },
          "socksPort" : {
            "type" : "integer",
            "description" : "The port number for SOCKS proxy.",
            "format" : "int32"
          },
          "username" : {
            "type" : "string",
            "description" : "The username for SOCKS/HTTP authentication."
          }
        },
        "description" : "DTO for defining a my home ip feature (project) (PRO)"
      },
      "FeatureNewsFilterDTO" : {
        "type" : "object",
        "properties" : {
          "blackoutAfterMinutes" : {
            "maximum" : 240,
            "type" : "integer",
            "description" : "Minutes after the event during which new opens are skipped. Maximum 240.",
            "format" : "int32",
            "example" : 15,
            "default" : 15
          },
          "blackoutBeforeMinutes" : {
            "maximum" : 240,
            "type" : "integer",
            "description" : "Minutes before the event during which new opens are skipped. Maximum 240.",
            "format" : "int32",
            "example" : 15,
            "default" : 15
          },
          "blockModifications" : {
            "type" : "boolean",
            "description" : "Whether stop loss and take profit changes are blocked during the blackout window",
            "example" : false,
            "default" : false
          },
          "dailyAgendaAtUtc" : {
            "type" : "string",
            "description" : "Time of day in UTC at which the daily agenda is sent, format HH:mm",
            "example" : "07:00"
          },
          "enableHolidayMode" : {
            "type" : "boolean",
            "description" : "Whether bank holidays of the traded currencies' countries are acted on",
            "example" : false,
            "default" : false
          },
          "enableNewsFilter" : {
            "type" : "boolean",
            "description" : "Master switch. If false the feature stays attached but does nothing.",
            "example" : true,
            "default" : true
          },
          "events" : {
            "$ref" : "#/components/schemas/NewsEventSelectionDTO"
          },
          "holidayAction" : {
            "type" : "string",
            "description" : "What happens on a holiday: NONE, REDUCE_SIZE or SKIP_NEW_OPENS",
            "example" : "REDUCE_SIZE",
            "default" : "REDUCE_SIZE",
            "enum" : [ "NONE", "REDUCE_SIZE", "SKIP_NEW_OPENS" ]
          },
          "holidayCountries" : {
            "type" : "array",
            "description" : "ISO-2 country codes whose holidays count. Empty means the countries are derived from the traded currencies.",
            "example" : [ "US", "GB" ],
            "items" : {
              "type" : "string",
              "description" : "ISO-2 country codes whose holidays count. Empty means the countries are derived from the traded currencies.",
              "example" : "[\"US\",\"GB\"]"
            }
          },
          "holidaySizeFactorPercent" : {
            "maximum" : 100,
            "type" : "integer",
            "description" : "Percentage of the normal lot size used when holidayAction is REDUCE_SIZE",
            "format" : "int32",
            "example" : 50,
            "default" : 50
          },
          "logSkippedTrades" : {
            "type" : "boolean",
            "description" : "Whether every skipped trade is written to the account log",
            "example" : true,
            "default" : true
          },
          "notificationTargets" : {
            "type" : "array",
            "description" : "Notification destinations that should receive the alerts. Empty means the events are only written to the account log.",
            "items" : {
              "$ref" : "#/components/schemas/NotificationTargetDTO"
            }
          },
          "notifyOnEvents" : {
            "type" : "array",
            "description" : "Which events are notified. Empty means all events of this feature.",
            "example" : [ "NEWS_FILTER_SKIPPED_COPY" ],
            "items" : {
              "type" : "string",
              "description" : "Which events are notified. Empty means all events of this feature.",
              "example" : "[\"NEWS_FILTER_SKIPPED_COPY\"]",
              "enum" : [ "POSITION_OPENED", "POSITION_CLOSED", "HISTORY_UPDATED", "NEWS_EVENT_UPCOMING", "NEWS_EVENT_RELEASED", "NEWS_FILTER_ACTION_SCHEDULED", "NEWS_FILTER_ACTION_IMMINENT", "NEWS_FILTER_DAILY_AGENDA", "NEWS_FILTER_SKIPPED_COPY", "NEWS_FILTER_CLOSED_POSITION", "NEWS_FILTER_REOPENED", "NEWS_FILTER_REOPEN_SKIPPED", "NEWS_FILTER_HOLIDAY_MODE", "MARKET_NEWS_HIGH_IMPACT" ]
            }
          },
          "sendDailyAgenda" : {
            "type" : "boolean",
            "description" : "Send one daily digest instead of many single warnings",
            "example" : false,
            "default" : false
          },
          "skipMarketOrders" : {
            "type" : "boolean",
            "description" : "Whether market orders are skipped during the blackout window",
            "example" : true,
            "default" : true
          },
          "skipPendingOrders" : {
            "type" : "boolean",
            "description" : "Whether pending orders are skipped during the blackout window",
            "example" : false,
            "default" : false
          },
          "symbolsConfiguration" : {
            "type" : "object",
            "additionalProperties" : {
              "$ref" : "#/components/schemas/FeatureNewsFilterDTO"
            },
            "description" : "Per-symbol overrides. An entry replaces the whole configuration for that symbol, it does not merge field by field.",
            "example" : {
              "XAUUSD" : {
                "blackoutBeforeMinutes" : 30
              }
            }
          },
          "warnBeforeMinutes" : {
            "type" : "array",
            "description" : "Minutes before an event at which a warning is sent. Empty disables the warnings.",
            "example" : [ 360, 60 ],
            "items" : {
              "type" : "integer",
              "description" : "Minutes before an event at which a warning is sent. Empty disables the warnings.",
              "format" : "int32"
            }
          },
          "warnOnlyIfExposed" : {
            "type" : "boolean",
            "description" : "Stay silent when nothing is open on the affected symbols",
            "example" : true,
            "default" : true
          }
        },
        "description" : "DTO for the news filter feature (copier). Skips copying new opens on a symbol while a calendar event that affects the symbol's currencies is inside its blackout window, and optionally reduces or skips trades on bank holidays. It never blocks a close."
      },
      "FeatureNewsProtectionDTO" : {
        "type" : "object",
        "properties" : {
          "cancelPendingOrders" : {
            "type" : "boolean",
            "description" : "Whether pending orders on affected symbols are cancelled as well",
            "example" : false,
            "default" : false
          },
          "closeBeforeMinutes" : {
            "maximum" : 120,
            "minimum" : 1,
            "type" : "integer",
            "description" : "Minutes before the event at which affected positions are closed. Maximum 120.",
            "format" : "int32",
            "example" : 5,
            "default" : 5
          },
          "closeOnlyLosingPositions" : {
            "type" : "boolean",
            "description" : "Only close positions that are currently losing",
            "example" : false,
            "default" : false
          },
          "dailyAgendaAtUtc" : {
            "type" : "string",
            "description" : "Time of day in UTC at which the daily agenda is sent, format HH:mm",
            "example" : "07:00"
          },
          "enableNewsProtection" : {
            "type" : "boolean",
            "description" : "Master switch. If false the feature stays attached but does nothing.",
            "example" : true,
            "default" : true
          },
          "events" : {
            "$ref" : "#/components/schemas/NewsEventSelectionDTO"
          },
          "minProfitToClose" : {
            "type" : "number",
            "description" : "Only close positions whose floating profit is at least this amount in account currency",
            "example" : 10.0
          },
          "notificationTargets" : {
            "type" : "array",
            "description" : "Notification destinations that should receive the alerts. Empty means the events are only written to the account log.",
            "items" : {
              "$ref" : "#/components/schemas/NotificationTargetDTO"
            }
          },
          "notifyOnEvents" : {
            "type" : "array",
            "description" : "Which events are notified. Empty means all events of this feature.",
            "example" : [ "NEWS_FILTER_CLOSED_POSITION" ],
            "items" : {
              "type" : "string",
              "description" : "Which events are notified. Empty means all events of this feature.",
              "example" : "[\"NEWS_FILTER_CLOSED_POSITION\"]",
              "enum" : [ "POSITION_OPENED", "POSITION_CLOSED", "HISTORY_UPDATED", "NEWS_EVENT_UPCOMING", "NEWS_EVENT_RELEASED", "NEWS_FILTER_ACTION_SCHEDULED", "NEWS_FILTER_ACTION_IMMINENT", "NEWS_FILTER_DAILY_AGENDA", "NEWS_FILTER_SKIPPED_COPY", "NEWS_FILTER_CLOSED_POSITION", "NEWS_FILTER_REOPENED", "NEWS_FILTER_REOPEN_SKIPPED", "NEWS_FILTER_HOLIDAY_MODE", "MARKET_NEWS_HIGH_IMPACT" ]
            }
          },
          "reopenAfterMinutes" : {
            "maximum" : 240,
            "minimum" : 1,
            "type" : "integer",
            "description" : "Minutes after the event at which the position is re-opened. Maximum 240.",
            "format" : "int32",
            "example" : 10,
            "default" : 10
          },
          "reopenExpiryMinutes" : {
            "maximum" : 1440,
            "minimum" : 1,
            "type" : "integer",
            "description" : "Drop a pending re-open intent after this many minutes. Maximum 1440.",
            "format" : "int32",
            "example" : 10,
            "default" : 10
          },
          "reopenMaxAdverseMovePips" : {
            "type" : "integer",
            "description" : "Do not re-open when the price moved against the original direction by more than this, in pips. Empty means no limit, which defeats the purpose of protecting.",
            "format" : "int32",
            "example" : 30
          },
          "reopenMaxSpreadPoints" : {
            "type" : "integer",
            "description" : "Do not re-open while the spread is wider than this, in points. Empty means no limit.",
            "format" : "int32",
            "example" : 50
          },
          "reopenMode" : {
            "type" : "string",
            "description" : "How a closed position is restored: NONE, SAME_VOLUME or RESYNC_WITH_MASTER",
            "example" : "RESYNC_WITH_MASTER",
            "default" : "RESYNC_WITH_MASTER",
            "enum" : [ "NONE", "SAME_VOLUME", "RESYNC_WITH_MASTER" ]
          },
          "reopenOnlyIfMasterStillOpen" : {
            "type" : "boolean",
            "description" : "Only re-open while the master still holds the position",
            "example" : true,
            "default" : true
          },
          "sendDailyAgenda" : {
            "type" : "boolean",
            "description" : "Send one daily digest instead of many single warnings",
            "example" : false,
            "default" : false
          },
          "symbolsConfiguration" : {
            "type" : "object",
            "additionalProperties" : {
              "$ref" : "#/components/schemas/FeatureNewsProtectionDTO"
            },
            "description" : "Per-symbol overrides. An entry replaces the whole configuration for that symbol, it does not merge field by field.",
            "example" : {
              "XAUUSD" : {
                "closeBeforeMinutes" : 15
              }
            }
          },
          "warnBeforeMinutes" : {
            "type" : "array",
            "description" : "Minutes before an event at which a warning is sent. Empty disables the warnings.",
            "example" : [ 360, 60 ],
            "items" : {
              "type" : "integer",
              "description" : "Minutes before an event at which a warning is sent. Empty disables the warnings.",
              "format" : "int32"
            }
          },
          "warnImminent" : {
            "type" : "boolean",
            "description" : "Send one last notice right before the close runs",
            "example" : true,
            "default" : true
          },
          "warnOnlyIfExposed" : {
            "type" : "boolean",
            "description" : "Stay silent when nothing is open on the affected symbols",
            "example" : true,
            "default" : true
          }
        },
        "description" : "DTO for the news protection feature (account). Closes open positions before a calendar event that affects their currencies and optionally re-opens them afterwards. Attaching the feature is the switch, there is no separate enable flag on the account."
      },
      "FeatureOrderTypeFilterDTO" : {
        "type" : "object",
        "properties" : {
          "allowedOrderTypes" : {
            "type" : "array",
            "description" : "List of order types to copy. Only orders matching these types will be copied. If the list is empty or null, all order types will be copied. Available types: Buy, Sell, BuyLimit, SellLimit, BuyStop, SellStop.",
            "example" : [ "Buy", "Sell" ],
            "items" : {
              "type" : "string",
              "description" : "List of order types to copy. Only orders matching these types will be copied. If the list is empty or null, all order types will be copied. Available types: Buy, Sell, BuyLimit, SellLimit, BuyStop, SellStop.",
              "example" : "[\"Buy\",\"Sell\"]",
              "enum" : [ "Buy", "Sell", "BuyLimit", "SellLimit", "BuyStop", "SellStop" ]
            }
          }
        },
        "description" : "DTO for order type filter feature (copier)"
      },
      "FeatureOverallTargetDTO" : {
        "type" : "object",
        "properties" : {
          "adjustReferenceOnBalanceChange" : {
            "type" : "boolean",
            "description" : "If true, deposits and withdrawals shift the reference balance by the same amount, so the configured target and limit stay intact after funding changes. If false, the reference balance is never touched and a deposit counts as profit.",
            "example" : true,
            "default" : true
          },
          "overallLossLimit" : {
            "maximum" : 100.00,
            "exclusiveMaximum" : false,
            "minimum" : 0.00,
            "exclusiveMinimum" : false,
            "type" : "number",
            "description" : "Overall loss limit in percent of the reference balance. Uses the same reference balance as the profit target and is never reset, which corresponds to a static (non-trailing) drawdown. When the limit is reached, all positions are closed (unless 'pauseInsteadOfClose' is enabled) and no new positions are copied. Set to 0 to deactivate.",
            "example" : 10.0,
            "default" : 0.0
          },
          "overallLossLimitAmount" : {
            "minimum" : 0.00,
            "exclusiveMinimum" : false,
            "type" : "number",
            "description" : "Overall loss limit as an amount in account currency, measured as the loss below the reference balance. Set to 0 to deactivate. If both the percentage and the amount are active, whichever is reached first triggers the limit.",
            "example" : 10000.0,
            "default" : 0.0
          },
          "overallProfitTarget" : {
            "maximum" : 1000.00,
            "exclusiveMaximum" : false,
            "minimum" : 0.00,
            "exclusiveMinimum" : false,
            "type" : "number",
            "description" : "Overall profit target in percent of the reference balance. Unlike the daily, weekly and monthly profit targets, this target is never reset: it is always measured against the reference balance below. When the target is reached, all positions are closed (unless 'pauseInsteadOfClose' is enabled) and no new positions are copied. Set to 0 to deactivate.",
            "example" : 8.0,
            "default" : 0.0
          },
          "overallProfitTargetAmount" : {
            "minimum" : 0.00,
            "exclusiveMinimum" : false,
            "type" : "number",
            "description" : "Overall profit target as an amount in account currency, measured as the gain above the reference balance. Set to 0 to deactivate. If both the percentage and the amount are active, whichever is reached first triggers the target.",
            "example" : 8500.0,
            "default" : 0.0
          },
          "pauseInsteadOfClose" : {
            "type" : "boolean",
            "description" : "If true, reaching the target or the limit only pauses the copier so that no new positions are opened, while open positions keep running. If false, all open positions are closed.",
            "example" : false,
            "default" : false
          },
          "referenceBalance" : {
            "minimum" : 0.00,
            "exclusiveMinimum" : false,
            "type" : "number",
            "description" : "The fixed starting balance the target and the limit are measured against. Set to 0 to capture the current account balance automatically when the feature is activated.",
            "example" : 106200.0,
            "default" : 0.0
          },
          "referenceMode" : {
            "type" : "string",
            "description" : "Defines which account value is compared against the reference balance. EQUITY includes open positions, swap and accrued costs and therefore reacts while trades are still running. BALANCE only counts closed trades, so all fees are already realized before the target can trigger.",
            "example" : "EQUITY",
            "default" : "EQUITY",
            "enum" : [ "EQUITY", "BALANCE", "EQUITY", "BALANCE" ]
          },
          "symbolsConfiguration" : {
            "type" : "object",
            "additionalProperties" : {
              "$ref" : "#/components/schemas/FeatureOverallTargetDTO"
            },
            "description" : "Defines the overall target per symbol. A symbol entry is evaluated against the profit and loss of that symbol only, in addition to the account wide values above, and triggers only for that symbol. Honoured fields per entry are 'overallProfitTarget', 'overallProfitTargetAmount', 'overallLossLimit', 'overallLossLimitAmount' and 'pauseInsteadOfClose'; 'referenceMode', 'referenceBalance' and 'adjustReferenceOnBalanceChange' are always taken from the account wide configuration. Set a value to 0 in an entry to deactivate it for that symbol.",
            "example" : {
              "EURUSD" : {
                "overallProfitTarget" : 3.0
              },
              "XAUUSD" : {
                "overallLossLimit" : 4.0
              }
            }
          }
        },
        "description" : "DTO for the overall target feature (account)"
      },
      "FeaturePermittedSymbolsDTO" : {
        "type" : "object",
        "properties" : {
          "blacklist" : {
            "type" : "array",
            "description" : "Blacklist regex (case insensitive). If multiple regex are specified, they are combined using an OR condition. The regex is applied to both the master symbol and the slave/mapped symbol - if either matches, the trade is blocked.",
            "items" : {
              "type" : "string",
              "description" : "Blacklist regex (case insensitive). If multiple regex are specified, they are combined using an OR condition. The regex is applied to both the master symbol and the slave/mapped symbol - if either matches, the trade is blocked."
            }
          },
          "whitelist" : {
            "type" : "array",
            "description" : "Whitelist regex (case insensitive). If multiple regex are specified, they are combined using an OR condition. The regex is applied to both the master symbol and the slave/mapped symbol - if either matches, the trade is allowed.",
            "items" : {
              "type" : "string",
              "description" : "Whitelist regex (case insensitive). If multiple regex are specified, they are combined using an OR condition. The regex is applied to both the master symbol and the slave/mapped symbol - if either matches, the trade is allowed."
            }
          }
        },
        "description" : "DTO for the permitted symbols feature: If both a whitelist and a blacklist are defined, the whitelist has priority over the blacklist. (copier)"
      },
      "FeatureProgressiveTradeSizingDTO" : {
        "type" : "object",
        "properties" : {
          "cycles" : {
            "maximum" : 10,
            "minimum" : 1,
            "type" : "integer",
            "description" : "Number of consecutive profitable trades at the elevated level required before the trade volume resets to the base size. For example, if set to 2, you need 2 consecutive winning trades at the multiplied level before it drops back. Default is 1 (original behavior: a single win resets immediately).",
            "format" : "int32",
            "example" : 1,
            "default" : 1
          },
          "lastLossGreaterThanInPercentage" : {
            "maximum" : 100.00,
            "exclusiveMaximum" : false,
            "minimum" : 0.00,
            "exclusiveMinimum" : false,
            "type" : "number",
            "description" : "Defines the loss percentage threshold required to activate the feature. For instance, if set to 1%, the system will trigger the multiplier if a trade closes with a loss greater than 1% of the account balance. The default is 0%, meaning any negative trade will activate the feature.",
            "example" : 0,
            "default" : 0
          },
          "limitLevels" : {
            "maximum" : 100,
            "minimum" : 1,
            "type" : "integer",
            "description" : "Limits the maximum number of consecutive times the trade volume can be increased after successive losses. For example, if set to 3, the trade volume will only be increased up to 3 times before being capped.",
            "format" : "int32",
            "example" : 3,
            "default" : 3
          },
          "lookBackInDays" : {
            "maximum" : 7,
            "minimum" : 1,
            "type" : "integer",
            "description" : "Defines the number of days to consider when evaluating past trades. For example, if set to 5, the system will look back at trades opened by the copier over the last 5 days to determine if the most recent trade closed with a loss.",
            "format" : "int32",
            "example" : 5,
            "default" : 5
          },
          "multiplier" : {
            "maximum" : 999.999,
            "exclusiveMaximum" : false,
            "minimum" : 0.001,
            "exclusiveMinimum" : false,
            "type" : "number",
            "description" : "Specifies the multiplier to apply when increasing trade volume after a loss. The default multiplier is 2.000, meaning the volume of the next trade will be doubled after a loss.",
            "example" : 2.0,
            "default" : 2.0
          }
        },
        "description" : "DTO for progressive trade sizing feature (copier) (PRO)"
      },
      "FeatureRiskPerTradeDTO" : {
        "type" : "object",
        "properties" : {
          "absoluteRisk" : {
            "type" : "number",
            "description" : "Defines the risk per trade as a fixed absolute value (e.g., 50 USD). If set to 0, this mode is disabled.",
            "example" : 50,
            "default" : 0
          },
          "aggregateRiskPerSymbol" : {
            "type" : "boolean",
            "description" : "If enabled, aggregates risk calculation across all open positions for the same symbol. When true and multiple positions exist for a symbol (e.g., XAUUSD), the total risk will be calculated by summing all open positions for that symbol before checking against the risk limits. When false, each position is evaluated independently.",
            "example" : true,
            "default" : false
          },
          "autoCloseOnRiskThresholdReached" : {
            "type" : "boolean",
            "description" : "Only applies when 'correctLotSizeBasedOnTheStopLoss' is enabled. If set to true (default), the system will automatically close the position when the defined risk threshold is reached, acting as a hard risk limit supervisor. If set to false, the system will NOT auto-close the position when the risk threshold is reached, allowing the stop loss to execute naturally. Use this option when you want precise lot sizing based on SL but prefer the trade to hit the SL rather than being closed by the risk supervisor. Note: If the position has no stop loss set, the system will still auto-close regardless of this setting.",
            "example" : false,
            "default" : true
          },
          "correctLotSizeBasedOnTheStopLoss" : {
            "type" : "boolean",
            "description" : "If enabled, adjusts the lot size automatically based on the distance to the stop loss (SL). Ensures that the actual monetary risk per trade aligns with the configured percentage or absolute risk. This calculation only applies when a stop loss is defined on the master trade. Only valid for copier.",
            "example" : true,
            "default" : false
          },
          "relativeRisk" : {
            "type" : "number",
            "description" : "Defines the risk per trade as a percentage of the account balance. If set to 0, this mode is disabled.",
            "example" : 2.5,
            "default" : 0
          },
          "symbolsConfiguration" : {
            "type" : "object",
            "additionalProperties" : {
              "$ref" : "#/components/schemas/FeatureRiskPerTradeDTO"
            },
            "description" : "Defines risk per trader per symbol. Symbol configuration has priority over the general configuration.",
            "example" : {
              "EURUSD" : {
                "absoluteRisk" : 0,
                "relativeRisk" : 2.5
              }
            }
          },
          "tickValue" : {
            "type" : "number",
            "description" : "Monetary value of one point (smallest price increment) per 1.0 lot, already expressed in the account currency.",
            "example" : 0.01,
            "default" : 0
          },
          "tickValueAutomaticAdjustement" : {
            "type" : "boolean",
            "description" : "Enable automatic detection of the point-value in account currency from live trades. When true, the system overrides `tickValue` with the detected value at runtime.",
            "example" : true,
            "default" : true
          }
        },
        "description" : "DTO for risk per trade feature (copier/account) (PRO)"
      },
      "FeatureScheduledCloseReopenDTO" : {
        "required" : [ "schedules" ],
        "type" : "object",
        "properties" : {
          "enabled" : {
            "type" : "boolean",
            "description" : "Master switch. If false, the feature is disabled and no schedule is evaluated, not even the ones in symbolsConfiguration.",
            "example" : true,
            "default" : true
          },
          "includePendingOrders" : {
            "type" : "boolean",
            "description" : "Indicates whether pending orders are deleted at the close time and restored at the reopen time.",
            "example" : false,
            "default" : false
          },
          "maxLossToClosePoints" : {
            "type" : "integer",
            "description" : "Maximum loss in points a position may have to still be closed. A value of 0 or null closes the position regardless of its loss.",
            "format" : "int32",
            "example" : 200,
            "default" : 0
          },
          "maxReopenSlippagePoints" : {
            "type" : "integer",
            "description" : "Maximum allowed price movement in points between the close price and the reopen price. A value of 0 or null disables the check.",
            "format" : "int32",
            "example" : 500,
            "default" : 0
          },
          "onlyCloseInProfit" : {
            "type" : "boolean",
            "description" : "Indicates whether only positions currently in profit are closed. Takes precedence over maxLossToClosePoints.",
            "example" : false,
            "default" : false
          },
          "onlyCloseNegativeSwapPositions" : {
            "type" : "boolean",
            "description" : "Indicates whether only positions with a negative swap are closed.",
            "example" : false,
            "default" : false
          },
          "restoreStopLossTakeProfit" : {
            "type" : "boolean",
            "description" : "Indicates whether the stop loss and take profit are restored when a position is reopened.",
            "example" : true,
            "default" : true
          },
          "schedules" : {
            "type" : "array",
            "description" : "List of close (and optional reopen) schedules defined by the user. Leave empty to run only the symbols listed in symbolsConfiguration.",
            "items" : {
              "$ref" : "#/components/schemas/CloseReopenScheduleDTO"
            }
          },
          "skipReopenIfMasterClosed" : {
            "type" : "boolean",
            "description" : "Indicates whether a copied position whose master position was closed in the meantime is skipped at the reopen time.",
            "example" : true,
            "default" : true
          },
          "symbolsConfiguration" : {
            "type" : "object",
            "additionalProperties" : {
              "$ref" : "#/components/schemas/FeatureScheduledCloseReopenDTO"
            },
            "description" : "Defines the scheduled close and reopen configuration per symbol. An entry replaces the whole configuration for that symbol."
          }
        },
        "description" : "DTO for the scheduled close and reopen feature (copier/account)"
      },
      "FeatureSettingDTO" : {
        "type" : "object",
        "description" : "Configure setting for the specific feature",
        "oneOf" : [ {
          "$ref" : "#/components/schemas/FeatureTelegramNotificationDTO"
        }, {
          "$ref" : "#/components/schemas/FeatureCopierFilterDTO"
        }, {
          "$ref" : "#/components/schemas/FeatureKeepAliveTradeDTO"
        }, {
          "$ref" : "#/components/schemas/FeaturePermittedSymbolsDTO"
        }, {
          "$ref" : "#/components/schemas/FeatureDedicatedIpDTO"
        }, {
          "$ref" : "#/components/schemas/FeatureDedicatedIpPoolDTO"
        }, {
          "$ref" : "#/components/schemas/FeatureProgressiveTradeSizingDTO"
        }, {
          "$ref" : "#/components/schemas/FeatureTpSlManagementDTO"
        }, {
          "$ref" : "#/components/schemas/FeatureExitSignalOverrideDTO"
        }, {
          "$ref" : "#/components/schemas/FeatureDailyProfitTargetDTO"
        }, {
          "$ref" : "#/components/schemas/FeatureWeeklyProfitTargetDTO"
        }, {
          "$ref" : "#/components/schemas/FeatureMonthlyProfitTargetDTO"
        }, {
          "$ref" : "#/components/schemas/FeatureSignalProviderDTO"
        }, {
          "$ref" : "#/components/schemas/FeatureSignalFollowerDTO"
        }, {
          "$ref" : "#/components/schemas/FeatureFallbackSettingDTO"
        }, {
          "$ref" : "#/components/schemas/FeatureMyHomeIpDTO"
        }, {
          "$ref" : "#/components/schemas/FeatureMaxOpenPositionsDTO"
        }, {
          "$ref" : "#/components/schemas/FeatureMaxLotSizeDTO"
        }, {
          "$ref" : "#/components/schemas/FeatureMultiplierDTO"
        }, {
          "$ref" : "#/components/schemas/FeatureMaximumLotDTO"
        }, {
          "$ref" : "#/components/schemas/FeatureBreakEvenDTO"
        }, {
          "$ref" : "#/components/schemas/FeatureTrailingStopDTO"
        }, {
          "$ref" : "#/components/schemas/FeatureTradingWindowsDTO"
        }, {
          "$ref" : "#/components/schemas/FeatureHftModeDTO"
        }, {
          "$ref" : "#/components/schemas/FeatureSocketDTO"
        }, {
          "$ref" : "#/components/schemas/FeatureApprovalDTO"
        }, {
          "$ref" : "#/components/schemas/FeatureDelayedExecutionDTO"
        }, {
          "$ref" : "#/components/schemas/FeatureMaintenanceWindowDTO"
        }, {
          "$ref" : "#/components/schemas/FeatureWhiteLabelDTO"
        }, {
          "$ref" : "#/components/schemas/FeatureMinimumHoldingTimeDTO"
        }, {
          "$ref" : "#/components/schemas/FeatureSkipPositionDTO"
        }, {
          "$ref" : "#/components/schemas/FeatureRiskPerTradeDTO"
        }, {
          "$ref" : "#/components/schemas/FeatureLiveDelayDTO"
        }, {
          "$ref" : "#/components/schemas/FeatureOrderTypeFilterDTO"
        }, {
          "$ref" : "#/components/schemas/FeatureDataCollectorDTO"
        }, {
          "$ref" : "#/components/schemas/FeatureMasanielloDTO"
        }, {
          "$ref" : "#/components/schemas/FeatureTradeGuardrailsDTO"
        }, {
          "$ref" : "#/components/schemas/FeatureMartingaleStrategyDTO"
        }, {
          "$ref" : "#/components/schemas/FeatureTraderDTO"
        }, {
          "$ref" : "#/components/schemas/FeatureInvestorDTO"
        }, {
          "$ref" : "#/components/schemas/FeatureTradingViewWebhookDTO"
        }, {
          "$ref" : "#/components/schemas/FeatureWebhookDTO"
        }, {
          "$ref" : "#/components/schemas/FeatureTelegramAccountDTO"
        }, {
          "$ref" : "#/components/schemas/FeatureTelegramConnectorDTO"
        }, {
          "$ref" : "#/components/schemas/FeatureBlockHedgingDTO"
        }, {
          "$ref" : "#/components/schemas/FeatureTradeCooldownDTO"
        }, {
          "$ref" : "#/components/schemas/FeatureNewsFilterDTO"
        }, {
          "$ref" : "#/components/schemas/FeatureNewsProtectionDTO"
        }, {
          "$ref" : "#/components/schemas/FeatureMarginCapDTO"
        }, {
          "$ref" : "#/components/schemas/FeatureSpreadFilterDTO"
        }, {
          "$ref" : "#/components/schemas/FeatureOverallTargetDTO"
        }, {
          "$ref" : "#/components/schemas/FeatureScheduledCloseReopenDTO"
        } ]
      },
      "FeatureSignalFollowerDTO" : {
        "required" : [ "signalProviderId" ],
        "type" : "object",
        "properties" : {
          "active" : {
            "type" : "boolean",
            "description" : "Specifies if the copier is active.",
            "default" : true
          },
          "copier" : {
            "$ref" : "#/components/schemas/CopierDTO"
          },
          "disableMinVolumeSafetySkip" : {
            "type" : "boolean",
            "description" : "Deactivates the minimum volume safety skip for this follower, even when the signal provider does not allow overriding the copier settings. When true, the copier's 'minVolumeSafetySkipThresholdMultiplier' is forced to 0 and trades are never skipped because of lot size amplification.",
            "default" : false
          },
          "monitorOnly" : {
            "type" : "boolean",
            "description" : "Indicates whether this copier is in monitor-only mode. When true, the copier monitors the source account and manages existing open positions (can close, modify them) but will not copy any new trades. When false, the copier operates in normal copying mode.",
            "default" : false
          },
          "signalProviderAvailable" : {
            "type" : "boolean",
            "description" : "Indicates that the signal provider is available to the follower.",
            "readOnly" : true
          },
          "signalProviderId" : {
            "type" : "string",
            "description" : "Unique identifier (id of FeatureSignalProviderDTO) for the associated signal provider that the follower is linked to.",
            "format" : "uuid"
          },
          "signalProviderName" : {
            "type" : "string",
            "description" : "Name of the signal provider.",
            "readOnly" : true
          },
          "suspended" : {
            "type" : "boolean",
            "description" : "Specifies whether the follower is suspended (the copier is deactivated). This setting can only be changed by the signal provider and cannot be overridden by the follower.",
            "default" : false
          }
        },
        "description" : "DTO for signal follower feature (account)"
      },
      "FeatureSignalProviderDTO" : {
        "required" : [ "copier", "name" ],
        "type" : "object",
        "properties" : {
          "accessAllowed" : {
            "type" : "boolean",
            "description" : "Indicates whether the current user has access to subscribe to this signal. This is determined based on the signal's visibility settings (isPublic, makeVisibleInMarketplace) and the user's email in the allowCustomers list.",
            "readOnly" : true,
            "example" : true,
            "default" : false
          },
          "allowCustomers" : {
            "type" : "array",
            "description" : "If the signal is private, specify the email addresses of customers you wish to grant access. Only users with these listed email addresses will be able to view and subscribe to your private signals.",
            "example" : [ "user@example.com" ],
            "items" : {
              "type" : "string",
              "description" : "If the signal is private, specify the email addresses of customers you wish to grant access. Only users with these listed email addresses will be able to view and subscribe to your private signals.",
              "example" : "[\"user@example.com\"]"
            }
          },
          "allowOverrideCopierSetting" : {
            "type" : "boolean",
            "description" : "Enable this option if you want followers to customize certain copier settings, such as risk parameters or trade sizes. Allowing overrides gives followers flexibility while using your signals. NOTE: This field can ONLY be set during resource creation and CANNOT be changed later.",
            "example" : true,
            "default" : true
          },
          "allowReselling" : {
            "type" : "boolean",
            "description" : "Enable this option to allow subscribers to resell your signal to their own customers. When enabled, your subscribers can act as intermediaries, offering your signals to others while potentially adding their own markup or fees. This creates a reseller network for your signal. NOTE: This field can ONLY be set during resource creation and CANNOT be changed later.",
            "example" : false,
            "default" : false
          },
          "allowedBrokers" : {
            "type" : "array",
            "description" : "List of allowed broker patterns (regex supported) that followers must use to subscribe to this signal. Use regex patterns to match broker names, for example 'ICMarketsSC-Live.*' will match all ICMarkets SC Live servers. Leave empty to allow all brokers.",
            "example" : [ "ICMarketsSC-Live.*", "Pepperstone-Live" ],
            "items" : {
              "type" : "string",
              "description" : "List of allowed broker patterns (regex supported) that followers must use to subscribe to this signal. Use regex patterns to match broker names, for example 'ICMarketsSC-Live.*' will match all ICMarkets SC Live servers. Leave empty to allow all brokers.",
              "example" : "[\"ICMarketsSC-Live.*\",\"Pepperstone-Live\"]"
            }
          },
          "allowedOverrideFields" : {
            "type" : "array",
            "description" : "Fine-grained control over which specific copier settings followers are allowed to override. Specify the field names from CopierDTO (e.g., 'multiplier', 'maxSlippage', 'copyStopLoss'). If this list is null or empty, ALL copier settings can be overridden (when allowOverrideCopierSetting is true). If this list contains specific field names, ONLY those fields can be overridden by followers, and all other settings will use the signal provider's defaults. This provides precise control over follower customization.",
            "example" : [ "multiplier", "maxSlippage", "copyStopLoss" ],
            "items" : {
              "type" : "string",
              "description" : "Fine-grained control over which specific copier settings followers are allowed to override. Specify the field names from CopierDTO (e.g., 'multiplier', 'maxSlippage', 'copyStopLoss'). If this list is null or empty, ALL copier settings can be overridden (when allowOverrideCopierSetting is true). If this list contains specific field names, ONLY those fields can be overridden by followers, and all other settings will use the signal provider's defaults. This provides precise control over follower customization.",
              "example" : "[\"multiplier\",\"maxSlippage\",\"copyStopLoss\"]"
            }
          },
          "billingModel" : {
            "type" : "string",
            "description" : "Billing model for profit sharing fees. MONTHLY_PROFIT: Charge on all profits each month (default). HIGH_WATERMARK: Charge only on new profits above the previous peak cumulative profit. High watermark ensures followers only pay when their total performance reaches a new high, regardless of deposits/withdrawals. NOTE: This field can ONLY be set during resource creation and CANNOT be changed later.",
            "example" : "MONTHLY_PROFIT",
            "default" : "MONTHLY_PROFIT",
            "enum" : [ "MONTHLY_PROFIT", "HIGH_WATERMARK" ]
          },
          "contact" : {
            "$ref" : "#/components/schemas/ContactDTO"
          },
          "copier" : {
            "$ref" : "#/components/schemas/CopierDTO"
          },
          "coverFollowerCosts" : {
            "type" : "boolean",
            "description" : "When enabled, the follower accounts' MetaCopier subscription fees will be charged to this signal provider's project instead, allowing followers to use MetaCopier for free. This applies to all accounts that follow your signal (subject to 'maxCoveredAccountsPerProject'). Note: This only covers the base MetaCopier subscription cost, not signal provider performance fees or other charges. NOTE: This flag is read-only via this endpoint; activation/deactivation is performed by MetaCopier (contact support to enable).",
            "readOnly" : true,
            "example" : false,
            "default" : false
          },
          "customerId" : {
            "type" : "integer",
            "description" : "The customer ID of the signal provider owner.",
            "format" : "int32",
            "readOnly" : true
          },
          "description" : {
            "maxLength" : 400,
            "minLength" : 0,
            "type" : "string",
            "description" : "A short summary of your trading strategy or approach. Use this field to give potential followers an idea of what to expect from your signals, including any specific methods, goals, or markets you specialize in."
          },
          "detailedDescription" : {
            "maxLength" : 10000,
            "minLength" : 0,
            "type" : "string",
            "description" : "A comprehensive description of how your trading strategy works, including entry/exit criteria, risk management approach, trading timeframes, market conditions, and any other important details that help followers understand your methodology. Use this field to provide in-depth information about your strategy."
          },
          "isPublic" : {
            "type" : "boolean",
            "description" : "Mark this setting if you want your signal provider profile to be visible and searchable by other users. If set to private, only users with direct access will be able to view and follow your signals. NOTE: This field can ONLY be set during resource creation and CANNOT be changed later.",
            "example" : false,
            "default" : false
          },
          "logo" : {
            "type" : "string",
            "description" : "A square logo image for the signal provider profile, encoded as a Base64 string. The image must be square and the Base64 string cannot exceed 256 KB in size.",
            "example" : "iVBORw0KGgoAAAANSUhEUgAAAAE..."
          },
          "makeHistoryPublic" : {
            "type" : "boolean",
            "description" : "Enable this option to make your trading history publicly visible to potential followers. When enabled, users can view your historical trades before subscribing. This transparency can help build trust and attract more followers.",
            "example" : false,
            "default" : false
          },
          "makeVisibleInMarketplace" : {
            "type" : "boolean",
            "description" : "If the signal is not public, enable this option to make your signal visible in the marketplace for discovery. This allows users to find your signal through the marketplace while maintaining controlled access.",
            "example" : false,
            "default" : false
          },
          "maxCoveredAccountsPerProject" : {
            "maximum" : 100,
            "minimum" : 0,
            "type" : "integer",
            "description" : "Maximum number of follower accounts per follower project whose MetaCopier costs the signal provider will cover. Only applies when 'coverFollowerCosts' is enabled (otherwise this value is silently ignored). If a follower project connects more accounts than this limit to the same signal, only the first accounts (by follower-feature creation date ascending) up to the cap will be covered; the remaining accounts will be billed to the follower's project as usual. Within a billing month, a covered slot remains assigned to its earliest-created feature even if that feature is deleted mid-month - this prevents gaming the cap by deleting and recreating features. Use 0 to cover all follower accounts without a per-project cap. This field can be updated at any time; changes take effect immediately for the current billing period.",
            "format" : "int32",
            "example" : 1,
            "default" : 0
          },
          "minimumBalance" : {
            "minimum" : 0,
            "type" : "integer",
            "description" : "The minimum account balance required for followers to use this signal, specified in the currency of the signal provider's account. If a follower's account uses a different currency, this minimum will be automatically converted to their account currency using the current exchange rate. Set this to ensure followers have adequate capital to properly follow your trading strategy and manage risk. Leave null or 0 for no minimum requirement.",
            "format" : "int32",
            "example" : 1000,
            "default" : 0
          },
          "monthlySubscriptionFee" : {
            "maximum" : 300,
            "minimum" : 0,
            "type" : "number",
            "description" : "The amount charged to followers on a monthly basis for access to your signals. Set a competitive price based on the value and insights you provide, or leave it 0 if you want to offer free access. NOTE: This field can be changed after creation, but only lowered. Increasing it requires MetaCopier support. White label brands may increase it freely.",
            "example" : 20.0,
            "default" : 20.0
          },
          "name" : {
            "maxLength" : 255,
            "minLength" : 0,
            "type" : "string",
            "description" : "The display name for your signal provider profile. Choose a name that reflects your trading style or focus, so followers can easily recognize and identify your signals."
          },
          "profileLink" : {
            "maxLength" : 500,
            "minLength" : 0,
            "type" : "string",
            "description" : "Optional link to your trading performance profile on platforms like MyFXBook, FXBlue, or ShowMyTrades. This allows potential followers to verify your track record and trading history.",
            "example" : "https://www.myfxbook.com/members/username/portfolio/12345"
          },
          "profitSharingFee" : {
            "maximum" : 100,
            "minimum" : 0,
            "type" : "number",
            "description" : "An optional fee based on the profits generated by followers using your signals. This allows you to earn a percentage of your followers' profits, providing an incentive tied directly to performance. NOTE: This field can be changed after creation, but only lowered. Increasing it requires MetaCopier support. White label brands may increase it as long as the current fee is not 0.",
            "example" : 15.0,
            "default" : 0
          },
          "subscribers" : {
            "type" : "array",
            "description" : "List of customers subscribed to this signal",
            "readOnly" : true,
            "example" : [ "user@example.com" ],
            "items" : {
              "type" : "string",
              "description" : "List of customers subscribed to this signal",
              "readOnly" : true,
              "example" : "[\"user@example.com\"]"
            }
          },
          "useMetaCopierAsPaymentProvider" : {
            "type" : "boolean",
            "description" : "Select this option to have MetaCopier manage payments on your behalf. When enabled, MetaCopier collects payments from followers, either through a subscription fee or profit-sharing arrangement, and transfers the funds to you. Please note that Metacopier retains a 30% service fee from each transaction.",
            "example" : true,
            "default" : false
          },
          "verified" : {
            "type" : "boolean",
            "description" : "Indicates whether this signal provider has been verified by MetaCopier. A verified signal provider means MetaCopier has personally reviewed the provider, analyzed the signals, and confirmed that the provider follows good trading practices.",
            "readOnly" : true,
            "example" : false,
            "default" : false
          }
        },
        "description" : "DTO for signal provider feature (project)"
      },
      "FeatureSkipPositionDTO" : {
        "type" : "object",
        "properties" : {
          "ifSlNotDefined" : {
            "type" : "boolean",
            "description" : "If set to true and the master position does not define a Stop Loss (SL), the copier will skip copying the position to the slave account. This can be used to avoid trades without predefined risk management.",
            "example" : false,
            "default" : false
          },
          "ifTpNotDefined" : {
            "type" : "boolean",
            "description" : "If set to true and the master position does not define a Take Profit (TP), the copier will skip copying the position to the slave account.",
            "example" : false,
            "default" : false
          },
          "logicOperatorTpSl" : {
            "type" : "string",
            "description" : "Specifies how the copier should evaluate SL and TP conditions. If set to AND, both conditions must be met to skip the position. If set to OR, either condition is enough to skip.",
            "example" : "OR",
            "default" : "OR",
            "enum" : [ "AND", "OR", "AND", "OR" ]
          },
          "symbolsConfiguration" : {
            "type" : "object",
            "additionalProperties" : {
              "$ref" : "#/components/schemas/FeatureSkipPositionDTO"
            },
            "description" : "Defines skip position per symbol. Symbol configuration has priority over the general configuration.",
            "example" : {
              "EURUSD" : {
                "ifSlNotDefined" : true
              }
            }
          }
        },
        "description" : "DTO for skip position feature (copier)"
      },
      "FeatureSocketDTO" : {
        "type" : "object",
        "properties" : {
          "activateSocket" : {
            "type" : "boolean",
            "description" : "Activate the socket. This property is always set to true.",
            "example" : true,
            "default" : true
          }
        },
        "description" : "DTO to activate the socket feature (account) (PRO)"
      },
      "FeatureSpreadFilterDTO" : {
        "type" : "object",
        "properties" : {
          "mode" : {
            "type" : "string",
            "description" : "Defines how the spread threshold is interpreted. POINTS: absolute spread limit expressed in points (broker points for the symbol). PERCENTAGE_OF_PRICE: the spread limit is expressed as a percentage of the current symbol price, so the limit scales automatically with the instrument's price level. The threshold value is the percentage itself (e.g. 0.05 means 0.05% of the price, i.e. a multiplier of 0.0005). Example: with threshold=0.05 on XAUUSD at price 2400, the spread limit is 0.05% × 2400 = 1.20.",
            "example" : "POINTS",
            "default" : "POINTS",
            "enum" : [ "POINTS", "PERCENTAGE_OF_PRICE" ]
          },
          "onMissingPrice" : {
            "type" : "string",
            "description" : "Defines what to do when the current bid/ask of the symbol is not available on the configured source account (e.g. no recent tick, symbol not subscribed, market closed, broker quote feed temporarily missing) and the spread therefore cannot be measured. ALLOW: let the open through and copy it normally (fail-open, default) - missing data is treated as 'no evidence of an abnormal spread'. BLOCK: drop the open just like a threshold violation (fail-closed) - safer when the filter is used as a hard guard (e.g. prop firm or HFT setups) where copying without a measurable spread is unacceptable. In both cases the event is logged.",
            "example" : "ALLOW",
            "default" : "ALLOW",
            "enum" : [ "ALLOW", "BLOCK" ]
          },
          "retryOnBlock" : {
            "type" : "boolean",
            "description" : "If true, an open that is blocked by the spread filter (threshold exceeded, or missing price with onMissingPrice=BLOCK) is treated as a failed open so the copier's existing open-retry mechanism re-evaluates it on subsequent attempts. The copier-wide 'openRetry' flag and 'openRetryTimeoutInMinutes' window are always respected: a spread block is only retried when both retryOnBlock=true AND the copier has openRetry=true; otherwise the blocked open is dropped immediately. Default is false so spread blocks stay decoupled from transport-error retries.",
            "example" : false,
            "default" : false
          },
          "source" : {
            "type" : "string",
            "description" : "Defines on which account the spread is measured when a new master position is detected. MASTER: the spread is read from the master account's symbol at the time the open is detected (default). SLAVE: the spread is read from the slave account's mapped symbol just before sending the copied open, which protects the slave from poor local execution conditions but adds an extra tick lookup per copied open.",
            "example" : "MASTER",
            "default" : "MASTER",
            "enum" : [ "MASTER", "SLAVE" ]
          },
          "symbolsConfiguration" : {
            "type" : "object",
            "additionalProperties" : {
              "$ref" : "#/components/schemas/FeatureSpreadFilterDTO"
            },
            "description" : "Defines spread filter configuration per symbol. Each symbol can specify its own mode and threshold. Symbol-specific configuration takes priority over the global setting.",
            "example" : {
              "EURUSD" : {
                "mode" : "POINTS",
                "threshold" : 20
              },
              "XAUUSD" : {
                "mode" : "PERCENTAGE_OF_PRICE",
                "threshold" : 0.05
              }
            }
          },
          "threshold" : {
            "type" : "number",
            "description" : "Global spread threshold applied to all symbols that do not have a symbol-specific override. The unit depends on the selected mode (points for POINTS, percentage of price for PERCENTAGE_OF_PRICE). If the measured spread (on the configured source account) exceeds this value, the open is blocked - it is then either dropped immediately or retried, depending on retryOnBlock and the copier-wide openRetry settings. A value of 0 means the global filter is disabled.",
            "example" : 30,
            "default" : 0
          }
        },
        "description" : "DTO for spread filter feature (copier)"
      },
      "FeatureTelegramAccountDTO" : {
        "required" : [ "apiId", "phoneNumber", "regionId" ],
        "type" : "object",
        "properties" : {
          "apiHash" : {
            "type" : "string",
            "description" : "Telegram API Hash (from https://my.telegram.org) - write only, not returned in responses. Required on create, optional on update (null/empty means keep existing value).",
            "writeOnly" : true
          },
          "apiId" : {
            "type" : "integer",
            "description" : "Telegram API ID (from https://my.telegram.org)",
            "format" : "int32"
          },
          "authErrorMessage" : {
            "type" : "string",
            "description" : "Error message if auth failed",
            "readOnly" : true
          },
          "authStatus" : {
            "type" : "string",
            "description" : "Current authorization status",
            "readOnly" : true,
            "enum" : [ "PENDING", "CODE_REQUIRED", "PASSWORD_REQUIRED", "AUTHORIZED", "FAILED", "SESSION_EXPIRED", "DISCONNECTED" ]
          },
          "availableChats" : {
            "type" : "array",
            "description" : "Available chats from this account (read-only, synced from backend-telegram)",
            "readOnly" : true,
            "items" : {
              "$ref" : "#/components/schemas/TelegramChatDTO"
            }
          },
          "connected" : {
            "type" : "boolean",
            "description" : "Is the Telegram client currently connected",
            "readOnly" : true
          },
          "includePrivateChats" : {
            "type" : "boolean",
            "description" : "Include private chats in the available chats list (default: false, only groups/channels are listed)",
            "default" : false
          },
          "lastSyncAt" : {
            "type" : "string",
            "description" : "Last sync timestamp",
            "format" : "date-time",
            "readOnly" : true
          },
          "phoneNumber" : {
            "pattern" : "^\\+[1-9]\\d{1,14}$",
            "type" : "string",
            "description" : "Phone number with country code (e.g., +41790000000)"
          },
          "regionId" : {
            "type" : "integer",
            "description" : "Region ID where this Telegram client should run",
            "format" : "int32"
          },
          "restartAuth" : {
            "type" : "boolean",
            "description" : "Set to true to restart authentication flow (use when session expired or auth failed)",
            "writeOnly" : true
          },
          "twoFactorPassword" : {
            "type" : "string",
            "description" : "Two-factor authentication password (if enabled)",
            "writeOnly" : true
          },
          "verificationCode" : {
            "type" : "string",
            "description" : "SMS verification code (write-only, for completing auth)",
            "writeOnly" : true
          }
        },
        "description" : "DTO for Telegram Account configuration (project)"
      },
      "FeatureTelegramConnectorDTO" : {
        "required" : [ "chatId", "enabled", "telegramAccountFeatureId" ],
        "type" : "object",
        "properties" : {
          "aiInstructions" : {
            "maxLength" : 2000,
            "minLength" : 0,
            "type" : "string",
            "description" : "AI instructions for signal interpretation. Use this to customize how the AI interprets signals. The default prompt (JSON format, symbol mappings, SL/TP rules, open positions context) is always included. Examples: 'The signal provider uses GOLD instead of XAUUSD', 'Ignore messages from admin', 'SL/TP values are always in points', 'Use only 50% of the volume specified in the signal', 'If signal says 1 lot, use 0.1 lot instead'"
          },
          "aiTier" : {
            "type" : "string",
            "description" : "AI model tier for signal interpretation. BASIC = default model, no extra charge. STANDARD = enhanced model, $5/month (billed daily). PRO = premium model, $10/month (billed daily). NOTE: Can only be set on creation. To change the tier, delete and recreate the connector.",
            "example" : "BASIC",
            "default" : "BASIC",
            "enum" : [ "BASIC", "STANDARD", "PRO" ]
          },
          "allowedActions" : {
            "type" : "array",
            "description" : "Allowed actions for signals from this chat. Valid values: open, close, modify.",
            "example" : [ "open", "close", "modify" ],
            "items" : {
              "type" : "string",
              "description" : "Allowed actions for signals from this chat. Valid values: open, close, modify.",
              "example" : "[\"open\",\"close\",\"modify\"]"
            }
          },
          "chatId" : {
            "type" : "integer",
            "description" : "Telegram chat ID to subscribe to",
            "format" : "int64"
          },
          "chatTitle" : {
            "type" : "string",
            "description" : "Chat title (denormalized for display)",
            "readOnly" : true
          },
          "confidenceThreshold" : {
            "maximum" : 100,
            "minimum" : 0,
            "type" : "integer",
            "description" : "AI confidence threshold (0-100). The AI analyzes each message and assigns a confidence score. Only signals with confidence >= this threshold are executed. Example: If threshold is 70 and AI returns confidence 65, the signal is skipped and logged but NOT executed. Lower values = more signals executed (but more false positives). Higher values = fewer signals (but more reliable). If null, uses global default (70).",
            "format" : "int32",
            "example" : 70
          },
          "connectorIndex" : {
            "type" : "integer",
            "description" : "Unique connector index (1-9) within the account. Auto-assigned on creation. Appended to position comments to identify which connector opened each position. This allows multiple connectors on the same account to manage their own positions independently.",
            "format" : "int32",
            "readOnly" : true,
            "example" : 1
          },
          "contextMessageCount" : {
            "maximum" : 10,
            "minimum" : 1,
            "type" : "integer",
            "description" : "Number of recent messages to include as context for AI interpretation. Higher values give the AI more context (useful for multi-message signals) but consume more tokens. If null, uses global default (5).",
            "format" : "int32",
            "example" : 5,
            "default" : 5
          },
          "defaultStopLossPoints" : {
            "minimum" : 0,
            "type" : "integer",
            "description" : "Default stop loss in points if the signal doesn't provide a SL. Will be applied as relative distance from the fill price.",
            "format" : "int32"
          },
          "defaultTakeProfitPoints" : {
            "minimum" : 0,
            "type" : "integer",
            "description" : "Default take profit in points if the signal doesn't provide a TP. Will be applied as relative distance from the fill price.",
            "format" : "int32"
          },
          "defaultVolume" : {
            "minimum" : 0.001,
            "exclusiveMinimum" : false,
            "type" : "number",
            "description" : "Default volume if not specified in signal (used when volumeMode='fixed')",
            "format" : "double",
            "example" : 0.1
          },
          "enabled" : {
            "type" : "boolean",
            "description" : "Enable signal processing from this chat",
            "example" : true,
            "default" : true
          },
          "errorMessage" : {
            "type" : "string",
            "description" : "Error message if status is ERROR",
            "readOnly" : true
          },
          "excludePatterns" : {
            "maxItems" : 60,
            "minItems" : 0,
            "type" : "array",
            "description" : "Optional list of regular expressions (case-insensitive) used as an exclusion filter. If any pattern matches the message text, the message is skipped BEFORE the AI is called (does not count against the daily AI call limit). Exclude is evaluated before include and always wins.",
            "example" : [ "announcement", "^promo:" ],
            "items" : {
              "type" : "string",
              "description" : "Optional list of regular expressions (case-insensitive) used as an exclusion filter. If any pattern matches the message text, the message is skipped BEFORE the AI is called (does not count against the daily AI call limit). Exclude is evaluated before include and always wins.",
              "example" : "[\"announcement\",\"^promo:\"]"
            }
          },
          "forceVolumeMode" : {
            "type" : "boolean",
            "description" : "Force volume mode (ignore signal volume). If false (default): use volume from signal if provided, otherwise use volumeMode calculation. If true: always use volumeMode calculation, ignore any volume specified in the signal. Note: forceVolumeMode=true with volumeMode=AI will fall back to defaultVolume.",
            "example" : false,
            "default" : false
          },
          "forumTopicId" : {
            "type" : "integer",
            "description" : "Forum topic ID to subscribe to, for groups that are split into topics. Null (default) subscribes to the whole chat, i.e. every topic. Available topics are listed flat in the Telegram account's availableChats as \"Group -> Topic\".",
            "format" : "int32",
            "example" : 12
          },
          "includePatterns" : {
            "maxItems" : 60,
            "minItems" : 0,
            "type" : "array",
            "description" : "Optional list of regular expressions (case-insensitive) used as an inclusion filter. If non-empty, only messages whose text matches AT LEAST ONE pattern are sent to the AI. If null/empty, all messages are eligible (subject to the exclude list). When BOTH include and exclude are set, exclude is evaluated first and wins; the message is then sent only if it also matches at least one include pattern.",
            "example" : [ "\bbuy\b", "\bsell\b" ],
            "items" : {
              "type" : "string",
              "description" : "Optional list of regular expressions (case-insensitive) used as an inclusion filter. If non-empty, only messages whose text matches AT LEAST ONE pattern are sent to the AI. If null/empty, all messages are eligible (subject to the exclude list). When BOTH include and exclude are set, exclude is evaluated first and wins; the message is then sent only if it also matches at least one include pattern.",
              "example" : "[\"\\bbuy\\b\",\"\\bsell\\b\"]"
            }
          },
          "lastMessageAt" : {
            "type" : "string",
            "description" : "Last message processed timestamp",
            "format" : "date-time",
            "readOnly" : true
          },
          "lotsPerThousandBalance" : {
            "minimum" : 0.001,
            "exclusiveMinimum" : false,
            "type" : "number",
            "description" : "Lots per 1000 balance (used when volumeMode='balance_scaled'). Example: If balance is 10000 and lotsPerThousandBalance is 0.01, calculated volume will be 0.1",
            "format" : "double",
            "example" : 0.01,
            "default" : 0.01
          },
          "magicNumber" : {
            "type" : "integer",
            "description" : "Magic number for positions from this connector",
            "format" : "int32"
          },
          "marginPercent" : {
            "minimum" : 0.01,
            "exclusiveMinimum" : false,
            "type" : "number",
            "description" : "Percentage of the account's free (available) margin the position should consume. Used when volumeMode='MARGIN_PERCENT'. The lot size is calculated as (freeMargin * marginPercent/100) / marginPerLot. Unlike RISK_PERCENT/RISK_AMOUNT this does NOT require a stop loss.",
            "format" : "double",
            "example" : 5.0
          },
          "maxAllowedVolume" : {
            "minimum" : 0.001,
            "exclusiveMinimum" : false,
            "type" : "number",
            "description" : "Maximum allowed volume (safety limit). Applies to ALL volume modes. If calculated volume exceeds this, it will be capped to this value. Default is 1.0 lot.",
            "format" : "double",
            "example" : 1.0,
            "default" : 1.0
          },
          "messageExpiryMinutes" : {
            "maximum" : 10080,
            "minimum" : 1,
            "type" : "integer",
            "description" : "Maximum message age in minutes. Messages older than this are skipped (e.g., due to network delays, Telegram outages, or server restarts). If null, uses global default (10).",
            "format" : "int32",
            "example" : 10
          },
          "riskAmount" : {
            "minimum" : 0.01,
            "exclusiveMinimum" : false,
            "type" : "number",
            "description" : "Risk per trade as fixed currency amount (in account currency). Used when volumeMode='RISK_AMOUNT'. The lot size is calculated based on this amount, the stop loss distance, and the tick value. Requires the account-level FeatureRiskPerTrade to be enabled (for tick value configuration). A stop loss must be present on the signal or configured via defaultStopLossPoints.",
            "format" : "double",
            "example" : 100.0
          },
          "riskPercent" : {
            "minimum" : 0.01,
            "exclusiveMinimum" : false,
            "type" : "number",
            "description" : "Risk per trade as percentage of account balance (used when volumeMode='RISK_PERCENT'). The lot size is calculated based on this percentage, the stop loss distance, and the tick value. Requires the account-level FeatureRiskPerTrade to be enabled (for tick value configuration). A stop loss must be present on the signal or configured via defaultStopLossPoints.",
            "format" : "double",
            "example" : 1.0
          },
          "status" : {
            "type" : "string",
            "description" : "Connector status",
            "readOnly" : true,
            "enum" : [ "PENDING", "ACTIVE", "PAUSED", "ERROR", "DISCONNECTED" ]
          },
          "telegramAccountFeatureId" : {
            "type" : "string",
            "description" : "Reference to the FeatureTelegramAccount feature ID",
            "format" : "uuid"
          },
          "volumeMode" : {
            "type" : "string",
            "description" : "Volume calculation mode: FIXED = use defaultVolume, BALANCE_SCALED = calculate from account balance, AI = let AI determine volume based on signal (customizable via aiInstructions field), RISK_PERCENT = calculate lot size from risk percentage of account balance (requires riskPercent and stop loss), RISK_AMOUNT = calculate lot size from fixed currency amount risk (requires riskAmount and stop loss), MARGIN_PERCENT = calculate lot size so the position consumes a percentage of the free (available) margin (requires marginPercent, no stop loss needed)",
            "example" : "FIXED",
            "default" : "FIXED",
            "enum" : [ "FIXED", "BALANCE_SCALED", "RISK_PERCENT", "RISK_AMOUNT", "MARGIN_PERCENT", "AI" ]
          }
        },
        "description" : "DTO for Telegram Connector configuration (account) (PRO)"
      },
      "FeatureTelegramNotificationDTO" : {
        "required" : [ "notifications" ],
        "type" : "object",
        "properties" : {
          "notifications" : {
            "type" : "array",
            "description" : "List of telegram notifications",
            "items" : {
              "$ref" : "#/components/schemas/TelegramNotificationDTO"
            }
          }
        },
        "description" : "DTO for telegram feature (project)"
      },
      "FeatureTpSlManagementDTO" : {
        "type" : "object",
        "properties" : {
          "additionalSlPoints" : {
            "type" : "integer",
            "description" : "Additional points to add to the existing SL value. Useful for prop firms.",
            "format" : "int32",
            "example" : 5
          },
          "additionalTpPoints" : {
            "type" : "integer",
            "description" : "Additional points to add to the existing TP value. Useful for prop firms.",
            "format" : "int32",
            "example" : 5
          },
          "adjustWithMasterDistance" : {
            "type" : "boolean",
            "description" : "Indicates whether the TP/SL should be adjusted based on the distance from the master trade's values, maintaining the same distance on both the master and the slave trades.",
            "example" : false,
            "default" : false
          },
          "blockTradeWithoutTpSl" : {
            "type" : "boolean",
            "description" : "If true, trades will not be opened on slave accounts if no TP/SL is available (neither from master nor from configured values). Important for prop firm accounts.",
            "example" : false,
            "default" : false
          },
          "fixedSlInPoints" : {
            "type" : "integer",
            "description" : "Fixed Stop Loss value in points. Set to 0 if not used.",
            "format" : "int32",
            "example" : 15
          },
          "fixedTpInPoints" : {
            "type" : "integer",
            "description" : "Fixed Take Profit value in points. Set to 0 if not used.",
            "format" : "int32",
            "example" : 20
          },
          "lockTpSl" : {
            "type" : "boolean",
            "description" : "If true, the TP/SL values are set once and are never modified afterward.",
            "example" : false,
            "default" : false
          },
          "masterTpSlPriority" : {
            "type" : "boolean",
            "description" : "If true, the master account's TP/SL values have priority. The configured fixed TP/SL values are only applied as a fallback when the master has no TP/SL set. If the master later adds TP/SL, the slave accounts will be updated accordingly.",
            "example" : false,
            "default" : false
          },
          "removeSl" : {
            "type" : "boolean",
            "description" : "If true, removes the Stop Loss (SL) from the copied positions.",
            "example" : false,
            "default" : false
          },
          "removeTp" : {
            "type" : "boolean",
            "description" : "If true, removes the Take Profit (TP) from the copied positions.",
            "example" : false,
            "default" : false
          },
          "symbolsConfiguration" : {
            "type" : "object",
            "additionalProperties" : {
              "$ref" : "#/components/schemas/FeatureTpSlManagementDTO"
            },
            "description" : "Defines TP/SL management per symbol. Symbol configuration has priority over the general configuration.",
            "example" : {
              "EURUSD" : {
                "fixedSlInPoints" : 5,
                "fixedTpInPoints" : 10
              }
            }
          }
        },
        "description" : "DTO for TP/SL management feature (copier) (PRO)"
      },
      "FeatureTradeCooldownDTO" : {
        "type" : "object",
        "properties" : {
          "cooldownAnchor" : {
            "type" : "string",
            "description" : "Whether the cooldown window is measured from the previous copied position's CLOSE (default) or OPEN.",
            "example" : "CLOSE",
            "default" : "CLOSE",
            "enum" : [ "CLOSE", "OPEN" ]
          },
          "cooldownMinutes" : {
            "maximum" : 1440,
            "type" : "integer",
            "description" : "Minutes after the anchor event during which new market opens on the symbol are skipped. A value of 0 or null disables the feature. Maximum is 1440 minutes (24 hours).",
            "format" : "int32",
            "example" : 60,
            "default" : 60
          },
          "correlationGroups" : {
            "type" : "array",
            "description" : "Used only when correlationMode is CUSTOM_GROUPS. Groups of symbols treated as one trade idea, e.g. [[\"US30\",\"US500\",\"NAS100\"],[\"USOIL\",\"UKOIL\"]]. A cooldown started by any member also applies to the other members of its group.",
            "example" : [ [ "US30", "US500", "NAS100" ] ],
            "items" : {
              "type" : "array",
              "description" : "Used only when correlationMode is CUSTOM_GROUPS. Groups of symbols treated as one trade idea, e.g. [[\"US30\",\"US500\",\"NAS100\"],[\"USOIL\",\"UKOIL\"]]. A cooldown started by any member also applies to the other members of its group.",
              "example" : [ [ "US30", "US500", "NAS100" ] ],
              "items" : {
                "type" : "string",
                "description" : "Used only when correlationMode is CUSTOM_GROUPS. Groups of symbols treated as one trade idea, e.g. [[\"US30\",\"US500\",\"NAS100\"],[\"USOIL\",\"UKOIL\"]]. A cooldown started by any member also applies to the other members of its group.",
                "example" : "[[\"US30\",\"US500\",\"NAS100\"]]"
              }
            }
          },
          "correlationMode" : {
            "type" : "string",
            "description" : "How a 'correlated symbol' is resolved. NONE = same symbol only. CUSTOM_GROUPS = symbols listed together in correlationGroups are treated as one trade idea.",
            "example" : "NONE",
            "default" : "NONE",
            "enum" : [ "NONE", "CUSTOM_GROUPS" ]
          },
          "symbolsConfiguration" : {
            "type" : "object",
            "additionalProperties" : {
              "$ref" : "#/components/schemas/FeatureTradeCooldownDTO"
            },
            "description" : "Per-symbol overrides. The cooldownMinutes, cooldownAnchor and trackByDirection of an override are applied for that symbol; correlationMode and correlationGroups are always taken from the top-level configuration.",
            "example" : {
              "XAUUSD" : {
                "cooldownMinutes" : 30
              }
            }
          },
          "trackByDirection" : {
            "type" : "boolean",
            "description" : "If true, BUY and SELL are tracked separately, so only a new open in the same direction as the anchored position is blocked. If false (default), both directions are blocked during the cooldown.",
            "example" : false,
            "default" : false
          }
        },
        "description" : "DTO for trade cooldown feature (copier). Skips copying a new market open on a symbol when a previous copied trade on the same (or a configured correlated) symbol was opened/closed less than 'cooldownMinutes' ago. Helps comply with prop-firm 'trade idea' rules (e.g. FTMO's 1-hour rule)."
      },
      "FeatureTradeGuardrailsDTO" : {
        "type" : "object",
        "properties" : {
          "aggregatePerSymbol" : {
            "type" : "boolean",
            "description" : "If true, the lot size threshold will be applied to the aggregated total lot size per symbol rather than to individual positions. For example, if you have 3 positions on EURUSD with 0.3 lots each (total 0.9 lots), setting this to true will check the 0.9 total against the threshold instead of checking each 0.3 lot position individually.",
            "example" : false,
            "default" : false
          },
          "enabled" : {
            "type" : "boolean",
            "description" : "If true, the trade guardrails feature is enabled and will monitor and close positions that exceed the threshold. If false, the feature is disabled.",
            "example" : true,
            "default" : true
          },
          "maxLotSizeThreshold" : {
            "type" : "number",
            "description" : "Sets the global maximum lot size threshold for individual open positions across all symbols. By default, each position is checked individually. If an open position exceeds this lot size, it will be automatically closed. A value of 0 means deactivated.",
            "example" : 0.5,
            "default" : 0.0
          },
          "maxOpenTimeSeconds" : {
            "type" : "integer",
            "description" : "Sets the maximum open time for positions in seconds. If a position has been open longer than this threshold, it will be automatically closed. A value of 0 means deactivated (no time limit).",
            "format" : "int32",
            "example" : 3600,
            "default" : 0
          },
          "symbolsConfiguration" : {
            "type" : "object",
            "additionalProperties" : {
              "$ref" : "#/components/schemas/FeatureTradeGuardrailsDTO"
            },
            "description" : "Defines the maximum lot size threshold per symbol. This allows for symbol-specific thresholds that override the global threshold.",
            "example" : {
              "EURUSD" : {
                "aggregatePerSymbol" : false,
                "enabled" : true,
                "maxLotSizeThreshold" : 1.0,
                "maxOpenTimeSeconds" : 7200
              }
            }
          }
        },
        "description" : "DTO for trade guardrails feature (account) (PRO)"
      },
      "FeatureTraderDTO" : {
        "required" : [ "description", "displayName", "maxDrawdownPercentage" ],
        "type" : "object",
        "properties" : {
          "analyticsUrl" : {
            "type" : "string",
            "description" : "Link to the trader's performance analytics profile on platforms like MyFXBook, FXBlue, or ShowMyTrades. This value is set by MetaCopier.",
            "readOnly" : true,
            "example" : "https://www.myfxbook.com/members/username/portfolio/12345"
          },
          "description" : {
            "maxLength" : 1000,
            "minLength" : 0,
            "type" : "string",
            "description" : "A description of the trader's strategy or approach within the investor program.",
            "example" : "Trend following strategy focused on major pairs"
          },
          "displayName" : {
            "maxLength" : 255,
            "minLength" : 0,
            "type" : "string",
            "description" : "The display name for the trader within the investor program.",
            "example" : "Alpha Trader"
          },
          "maxDrawdownPercentage" : {
            "type" : "number",
            "description" : "Maximum drawdown percentage that the trader sets for their strategy. This information is used by MetaCopier to calculate an adequate risk level for investors. This value can only be set at feature creation and cannot be updated afterwards.",
            "example" : 10.0
          },
          "status" : {
            "type" : "string",
            "description" : "Status of a trader within the investor program",
            "readOnly" : true,
            "enum" : [ "PENDING", "ACTIVE", "SUSPENDED" ]
          }
        },
        "description" : "DTO for investor program trader feature (account)"
      },
      "FeatureTradingViewWebhookDTO" : {
        "required" : [ "authMethod", "enableWebhook" ],
        "type" : "object",
        "properties" : {
          "allowCloseAll" : {
            "type" : "boolean",
            "description" : "Allow closeAll action. WARNING: Closes ALL positions!",
            "example" : false,
            "default" : false
          },
          "allowSymbolOnlyClose" : {
            "type" : "boolean",
            "description" : "Allow close by symbol only without additional filters (direction/closeMode). WARNING: Can close multiple positions.",
            "example" : false,
            "default" : false
          },
          "allowedActions" : {
            "type" : "array",
            "description" : "Allowed actions. Null or empty means all actions are allowed.",
            "example" : [ "open", "close", "modify" ],
            "items" : {
              "type" : "string",
              "description" : "Allowed actions. Null or empty means all actions are allowed.",
              "example" : "[\"open\",\"close\",\"modify\"]"
            }
          },
          "authMethod" : {
            "type" : "string",
            "description" : "Authentication method: SECRET (recommended) or HMAC (requires proxy)",
            "example" : "SECRET",
            "default" : "SECRET",
            "enum" : [ "SECRET", "HMAC" ]
          },
          "dataRetentionDays" : {
            "maximum" : 90,
            "minimum" : 1,
            "type" : "integer",
            "description" : "TTL in days for stored TradingView data.",
            "format" : "int32",
            "example" : 30,
            "default" : 30
          },
          "enableWebhook" : {
            "type" : "boolean",
            "description" : "Enable TradingView webhook access for this account",
            "example" : true,
            "default" : true
          },
          "enabled" : {
            "type" : "boolean"
          },
          "hmacSecret" : {
            "type" : "string",
            "description" : "HMAC secret (auto-generated, read-only). Used for HMAC signature verification.",
            "readOnly" : true
          },
          "ipAllowlist" : {
            "type" : "array",
            "description" : "IP allowlist for additional security. Empty means allow all IPs (recommended). WARNING: TradingView IPs may change without notice.",
            "example" : [ ],
            "items" : {
              "type" : "string",
              "description" : "IP allowlist for additional security. Empty means allow all IPs (recommended). WARNING: TradingView IPs may change without notice.",
              "example" : "[]"
            }
          },
          "maxAllowedVolume" : {
            "minimum" : 0,
            "exclusiveMinimum" : false,
            "type" : "number",
            "description" : "Maximum allowed volume in lots (safety cap). Applies to ALL sizing modes (explicit volume, riskPercent, riskAmount). If the resulting volume exceeds this value it is capped to it. 0 (or null) means the cap is deactivated (default). For multi-TP requests the cap applies to each leg.",
            "format" : "double",
            "example" : 1.0,
            "default" : 0
          },
          "maxMatchCount" : {
            "maximum" : 100,
            "minimum" : 1,
            "type" : "integer",
            "description" : "Max positions to match before requiring force:true. Safety guard against accidental bulk operations.",
            "format" : "int32",
            "example" : 3,
            "default" : 3
          },
          "maxMatchCountOrDefault" : {
            "type" : "integer",
            "format" : "int32"
          },
          "openRetry" : {
            "type" : "boolean",
            "description" : "If enabled, the retry mechanism activates when the broker rejects the request or the terminal does not respond in time. If set to false, the request is sent only once. Retries are executed every 30 seconds until 'openRetryTimeoutInMinutes' has elapsed.",
            "example" : true,
            "default" : true
          },
          "openRetryTimeoutInMinutes" : {
            "maximum" : 60,
            "minimum" : 1,
            "type" : "integer",
            "description" : "Specifies the total duration (in minutes) during which the retry mechanism will attempt to resend a rejected or unanswered request. Retries run every 30 seconds. Once this duration elapses, no further retry attempts will be made and the request is marked as failed. This setting is applicable only if 'openRetry' is set to true.",
            "format" : "int32",
            "example" : 5,
            "default" : 5
          },
          "openRetryTimeoutInMinutesOrDefault" : {
            "type" : "integer",
            "format" : "int32"
          },
          "requireTimestampForSecret" : {
            "type" : "boolean",
            "description" : "Require timestamp field for SECRET auth (optional replay protection).",
            "example" : false,
            "default" : false
          },
          "timestampToleranceSeconds" : {
            "maximum" : 300,
            "minimum" : 10,
            "type" : "integer",
            "description" : "Timestamp tolerance in seconds for replay protection. Requests with timestamps older than this are rejected.",
            "format" : "int32",
            "example" : 60,
            "default" : 60
          },
          "timestampToleranceSecondsOrDefault" : {
            "type" : "integer",
            "format" : "int32"
          },
          "webhookSecret" : {
            "maxLength" : 64,
            "minLength" : 16,
            "type" : "string",
            "description" : "Webhook secret for SECRET auth (min 16 chars, stored hashed). Use 'Generate Secret' button for a random secure secret.",
            "example" : "wh_abc123def456xyz789"
          }
        },
        "description" : "DTO to enable TradingView webhook access (account) (PRO)"
      },
      "FeatureTradingWindowsDTO" : {
        "required" : [ "tradingWindows" ],
        "type" : "object",
        "properties" : {
          "closePositionsAtWindowEnd" : {
            "type" : "boolean",
            "description" : "Indicates whether to close all open positions at the end of the trading window.",
            "example" : true,
            "default" : true
          },
          "symbolsConfiguration" : {
            "type" : "object",
            "additionalProperties" : {
              "$ref" : "#/components/schemas/FeatureTradingWindowsDTO"
            },
            "description" : "Defines the trading windows configuration per symbol."
          },
          "temporarilySkipUntilNextWindow" : {
            "type" : "boolean",
            "description" : "Indicates whether trades outside the defined windows are temporarily skipped until the next trading window starts. This option is only applicable to copiers.",
            "example" : true,
            "default" : false
          },
          "tradingWindows" : {
            "type" : "array",
            "description" : "List of trading windows defined by the user.",
            "items" : {
              "$ref" : "#/components/schemas/TradingWindowDTO"
            }
          }
        },
        "description" : "DTO for the trading windows feature (copier/account) (PRO)"
      },
      "FeatureTrailingStopDTO" : {
        "type" : "object",
        "properties" : {
          "activationThresholdPercentage" : {
            "type" : "number",
            "description" : "Defines the activation threshold as a percentage of the take profit. For example, if TP is 1000 points and this is set to 50, trailing stop activates at 500 points profit. A value of 0 means this activation method is deactivated. Requires TakeProfit to be set on the trade. If both activationThresholdPoints and activationThresholdPercentage are active (>0), the maximum (most conservative) value will be used.",
            "format" : "double",
            "example" : 50,
            "default" : 0
          },
          "activationThresholdPoints" : {
            "type" : "integer",
            "description" : "Defines the activation threshold in points. Trailing stop starts only when profit reaches this value. A value of 0 means this activation method is deactivated. If both activationThresholdPoints and activationThresholdPercentage are active (>0), the maximum (most conservative) value will be used.",
            "format" : "int32",
            "example" : 30,
            "default" : 30
          },
          "initialStopLossPoints" : {
            "type" : "integer",
            "description" : "Defines the initial stop loss distance in points from the entry price when the trade is opened. A value of 0 means no stop loss is applied initially.",
            "format" : "int32",
            "example" : 50,
            "default" : 50
          },
          "minimumDistancePoints" : {
            "type" : "integer",
            "description" : "Defines the minimum distance in points from the current price to the stop loss. Prevents the stop-loss from moving too close.",
            "format" : "int32",
            "example" : 20,
            "default" : 20
          },
          "symbolsConfiguration" : {
            "type" : "object",
            "additionalProperties" : {
              "$ref" : "#/components/schemas/FeatureTrailingStopDTO"
            },
            "description" : "Defines the trailing stop configuration per symbol.",
            "example" : {
              "EURUSD" : {
                "activationThresholdPercentage" : 0,
                "activationThresholdPoints" : 30,
                "initialStopLossPoints" : 50,
                "minimumDistancePoints" : 20,
                "trailingStepPercentage" : 0,
                "trailingStepPoints" : 10
              }
            }
          },
          "trailingStepPercentage" : {
            "type" : "number",
            "description" : "Defines the step distance as a percentage of the take profit. For example, if TP is 1000 points and this is set to 10, the trailing step equals 100 points. A value of 0 means this method is deactivated. Requires TakeProfit to be set on the trade. If both trailingStepPoints and trailingStepPercentage are active (>0), the maximum (most conservative) value will be used.",
            "format" : "double",
            "example" : 10,
            "default" : 0
          },
          "trailingStepPoints" : {
            "type" : "integer",
            "description" : "Defines the step distance in points at which the trailing stop will move as the trade progresses. A value of 0 means this method is deactivated. If both trailingStepPoints and trailingStepPercentage are active (>0), the maximum (most conservative) value will be used.",
            "format" : "int32",
            "example" : 10,
            "default" : 10
          }
        },
        "description" : "DTO for the trailing stop feature (copier/account) (PRO)"
      },
      "FeatureTypeDTO" : {
        "required" : [ "id" ],
        "type" : "object",
        "properties" : {
          "id" : {
            "type" : "integer",
            "format" : "int32"
          },
          "name" : {
            "type" : "string",
            "readOnly" : true
          },
          "planName" : {
            "type" : "string",
            "readOnly" : true
          }
        },
        "description" : "You have only to set the id e.g 1 for Telegram. Example: {id:1}"
      },
      "FeatureWebhookDTO" : {
        "required" : [ "authMethod", "enableOutboundWebhook", "endpointUrl" ],
        "type" : "object",
        "properties" : {
          "authMethod" : {
            "type" : "string",
            "description" : "Authentication method for webhook delivery. HMAC_SHA256: Signs payload with shared secret (most secure, recommended). BEARER_TOKEN: Sends a static token in Authorization header. NONE: No authentication (not recommended).",
            "example" : "NONE",
            "default" : "NONE",
            "enum" : [ "HMAC_SHA256", "BEARER_TOKEN", "NONE" ]
          },
          "bearerToken" : {
            "maxLength" : 512,
            "minLength" : 16,
            "type" : "string",
            "description" : "Bearer token for BEARER_TOKEN auth method. Sent as 'Authorization: Bearer <token>' header. Required when authMethod is BEARER_TOKEN. Min 16 characters for security.",
            "example" : "your_secure_token_here"
          },
          "customHeaders" : {
            "type" : "object",
            "additionalProperties" : {
              "type" : "string",
              "description" : "Custom HTTP headers to include in every webhook delivery. Useful for routing, identification, or receiver-side filtering. Max 10 headers. Header names must not override reserved headers (Content-Type, Authorization, X-MetaCopier-*).",
              "example" : "{\"X-Project-Id\":\"my-project\",\"X-Environment\":\"production\"}"
            },
            "description" : "Custom HTTP headers to include in every webhook delivery. Useful for routing, identification, or receiver-side filtering. Max 10 headers. Header names must not override reserved headers (Content-Type, Authorization, X-MetaCopier-*).",
            "example" : {
              "X-Environment" : "production",
              "X-Project-Id" : "my-project"
            }
          },
          "description" : {
            "maxLength" : 255,
            "minLength" : 0,
            "type" : "string",
            "description" : "Optional description/label for this webhook endpoint (for dashboard display).",
            "example" : "Production trade alerts"
          },
          "enableOutboundWebhook" : {
            "type" : "boolean",
            "description" : "Enable or disable webhook delivery. When disabled, events are not sent but configuration is preserved.",
            "example" : true,
            "default" : true
          },
          "enabled" : {
            "type" : "boolean"
          },
          "endpointUrl" : {
            "maxLength" : 2048,
            "minLength" : 10,
            "type" : "string",
            "description" : "The destination URL where webhook payloads will be delivered via HTTP POST. Must be HTTPS in production.",
            "example" : "https://your-app.com/api/webhooks/metacopier"
          },
          "hmacSecret" : {
            "maxLength" : 512,
            "minLength" : 32,
            "type" : "string",
            "description" : "HMAC signing secret for HMAC_SHA256 auth method. Used to compute: HMAC-SHA256(timestamp + '.' + body, secret). Verify on your side by recomputing and comparing signatures. Required when authMethod is HMAC_SHA256. Min 32 characters for security."
          },
          "includeAccountMetadata" : {
            "type" : "boolean",
            "description" : "Include additional account metadata (broker name, login number) in webhook payload. The accountId is always included by default. When enabled, extra identifying fields are added so receivers can distinguish accounts without a separate lookup.",
            "example" : false,
            "default" : false
          },
          "includePositionDetails" : {
            "type" : "boolean",
            "description" : "Include full position details in webhook payload (symbol, volume, prices, profit, etc.). When false, only accountId and ticket are sent (minimal payload). Full payload is useful for analytics; minimal reduces bandwidth.",
            "example" : true,
            "default" : true
          },
          "includeTimestampInSignature" : {
            "type" : "boolean",
            "description" : "Include a timestamp in the HMAC signature for replay protection. When enabled, the X-MetaCopier-Timestamp header is included and the signature is computed as HMAC-SHA256(timestamp + '.' + body, secret). Receivers can reject old timestamps to prevent replay attacks. Only relevant for HMAC_SHA256 auth method.",
            "example" : true,
            "default" : true
          },
          "initialRetryDelayMs" : {
            "maximum" : 30000,
            "minimum" : 500,
            "type" : "integer",
            "description" : "Initial retry delay in milliseconds. Each subsequent retry doubles the delay (exponential backoff). E.g., 2000ms → retries at 2s, 4s, 8s.",
            "format" : "int32",
            "example" : 2000,
            "default" : 2000
          },
          "initialRetryDelayMsOrDefault" : {
            "type" : "integer",
            "format" : "int32"
          },
          "maxRetries" : {
            "maximum" : 5,
            "minimum" : 0,
            "type" : "integer",
            "description" : "Maximum number of retry attempts on delivery failure (5xx or network error). Retries use exponential backoff. 0 = no retries.",
            "format" : "int32",
            "example" : 3,
            "default" : 3
          },
          "maxRetriesOrDefault" : {
            "type" : "integer",
            "format" : "int32"
          },
          "rateLimitPerMinute" : {
            "maximum" : 1000,
            "minimum" : 0,
            "type" : "integer",
            "description" : "Maximum webhook deliveries per minute per endpoint. Protects the receiver from being overwhelmed during high-frequency trading. Events exceeding the limit are queued and delivered when the window resets. 0 = unlimited.",
            "format" : "int32",
            "example" : 60,
            "default" : 60
          },
          "rateLimitPerMinuteOrDefault" : {
            "type" : "integer",
            "format" : "int32"
          },
          "requestTimeoutSeconds" : {
            "maximum" : 60,
            "minimum" : 5,
            "type" : "integer",
            "description" : "Request timeout in seconds. If the receiver does not respond within this time, the delivery is considered failed and may be retried.",
            "format" : "int32",
            "example" : 30,
            "default" : 30
          },
          "requestTimeoutSecondsOrDefault" : {
            "type" : "integer",
            "format" : "int32"
          },
          "subscribedEvents" : {
            "type" : "array",
            "description" : "List of events that trigger webhook delivery. Null or empty means ALL events are subscribed. Available events: POSITION_OPENED, POSITION_CLOSED, HISTORY_UPDATED.",
            "example" : [ "POSITION_OPENED", "POSITION_CLOSED" ],
            "items" : {
              "type" : "string",
              "description" : "List of events that trigger webhook delivery. Null or empty means ALL events are subscribed. Available events: POSITION_OPENED, POSITION_CLOSED, HISTORY_UPDATED.",
              "example" : "[\"POSITION_OPENED\",\"POSITION_CLOSED\"]",
              "enum" : [ "POSITION_OPENED", "POSITION_CLOSED", "HISTORY_UPDATED" ]
            }
          }
        },
        "description" : "DTO to configure outbound webhook delivery (project/account)"
      },
      "FeatureWeeklyProfitTargetDTO" : {
        "type" : "object",
        "properties" : {
          "autoResetIfBalanceIsBelow" : {
            "type" : "boolean",
            "description" : "Reset this target if the balance falls below the target. For example, after a withdrawal.",
            "default" : false
          },
          "pauseInsteadOfClose" : {
            "type" : "boolean",
            "description" : "If set to 'true', when the profit target is reached, the copier will pause and stop opening new positions instead of closing all existing positions. The open positions will remain active. If set to 'false', all positions will be closed when the target is reached.",
            "default" : false
          },
          "resetOnBalanceChange" : {
            "type" : "boolean",
            "description" : "If set to 'false', balance changes (deposits and withdrawals) will NOT trigger a reset of this profit target. If set to 'true', any deposit or withdrawal will reset the profit target reference balance. This option allows you to maintain the profit target calculation even when adding or removing funds from the account.",
            "default" : true
          },
          "weeklyAbsoluteProfitTarget" : {
            "minimum" : 0.00,
            "exclusiveMinimum" : false,
            "type" : "number",
            "description" : "Enter a weekly absolute profit target in account currency. If the target is reached, all positions will be closed (unless 'pauseInsteadOfClose' is enabled) and new ones will be blocked until the next week. Set to 0 to deactivate.",
            "default" : 0
          },
          "weeklyProfitTarget" : {
            "maximum" : 100.00,
            "exclusiveMaximum" : false,
            "minimum" : 0.00,
            "exclusiveMinimum" : false,
            "type" : "number",
            "description" : "Enter a weekly target in %. If the target is reached, all positions will be closed (unless 'pauseInsteadOfClose' is enabled). New positions will not be copied until the next week, and any positions placed outside system will be closed immediately (if 'pauseInsteadOfClose' is false). Set to 0 to deactivate.",
            "default" : 5.0
          },
          "weeklyRelativeProfitTarget" : {
            "minimum" : 0.00,
            "exclusiveMinimum" : false,
            "type" : "number",
            "description" : "Enter a weekly relative profit target in account currency. If the target is reached, all positions will be closed (unless 'pauseInsteadOfClose' is enabled) and new ones will be blocked until the next week. Set to 0 to deactivate.",
            "default" : 0
          }
        },
        "description" : "DTO for weekly profit target feature (account)"
      },
      "FeatureWhiteLabelDTO" : {
        "required" : [ "logo", "name", "stripeApiKey", "subdomain" ],
        "type" : "object",
        "properties" : {
          "accountPriceDedicated" : {
            "maximum" : 5.00,
            "exclusiveMaximum" : false,
            "minimum" : 0.00,
            "exclusiveMinimum" : false,
            "type" : "number",
            "description" : "Price per day (USD) for an account in a dedicated project",
            "example" : 0.32
          },
          "accountPriceDedicatedMin" : {
            "maximum" : 5.00,
            "exclusiveMaximum" : false,
            "minimum" : 0.00,
            "exclusiveMinimum" : false,
            "type" : "number",
            "description" : "Minimum daily price in USD for an account in a dedicated project after volume discount",
            "example" : 0.22
          },
          "accountPriceShared" : {
            "maximum" : 5.00,
            "exclusiveMaximum" : false,
            "minimum" : 0.00,
            "exclusiveMinimum" : false,
            "type" : "number",
            "description" : "Price per day (USD) for an account in a shared project",
            "example" : 0.27
          },
          "accountTypes" : {
            "type" : "array",
            "description" : "Select allowed account types for the white-label solution. If not specified, all account types are allowed.",
            "items" : {
              "$ref" : "#/components/schemas/AccountTypeDTO"
            }
          },
          "allowedEmailDomains" : {
            "type" : "array",
            "description" : "Comma-separated list of email domains (without @) allowed to register/access this white-label platform. Only enforced when restrictRegistration is true. Users with emails matching any listed domain are allowed.",
            "example" : "company.com,partner.org",
            "items" : {
              "type" : "string",
              "description" : "Comma-separated list of email domains (without @) allowed to register/access this white-label platform. Only enforced when restrictRegistration is true. Users with emails matching any listed domain are allowed.",
              "example" : "company.com,partner.org"
            }
          },
          "allowedRegions" : {
            "type" : "array",
            "description" : "Select allowed regions for the white-label solution. If empty or not specified, all regions are allowed.",
            "items" : {
              "$ref" : "#/components/schemas/RegionDTO"
            }
          },
          "allowedRegistrationEmails" : {
            "type" : "array",
            "description" : "Comma-separated list of email addresses allowed to register/access this white-label platform. Only enforced when restrictRegistration is true.",
            "example" : "john@company.com,jane@company.com",
            "items" : {
              "type" : "string",
              "description" : "Comma-separated list of email addresses allowed to register/access this white-label platform. Only enforced when restrictRegistration is true.",
              "example" : "john@company.com,jane@company.com"
            }
          },
          "authPageBackground" : {
            "maxLength" : 7,
            "minLength" : 0,
            "type" : "string",
            "description" : "Hex color code (e.g. #1C1917) for the authentication page background.",
            "example" : "#1C1917"
          },
          "cTraderClientId" : {
            "type" : "string",
            "description" : "cTrader Client ID used to enable support for cTrader accounts"
          },
          "cTraderClientSecret" : {
            "type" : "string",
            "description" : "cTrader Client Secret used to enable support for cTrader accounts"
          },
          "cryptoEnabledCoins" : {
            "type" : "array",
            "description" : "Public copy of the tenant's coin allow-list.",
            "readOnly" : true,
            "items" : {
              "type" : "string",
              "description" : "Public copy of the tenant's coin allow-list.",
              "readOnly" : true
            }
          },
          "cryptoNativeEnabled" : {
            "type" : "boolean",
            "description" : "Enable MetaCopier-native crypto payments for this white-label."
          },
          "cryptoNativeReady" : {
            "type" : "boolean",
            "description" : "True iff MCC is fully configured for this tenant (public flag).",
            "readOnly" : true
          },
          "cryptoWallet" : {
            "$ref" : "#/components/schemas/CryptoWalletConfigDTO"
          },
          "customCss" : {
            "maxLength" : 50000,
            "minLength" : 0,
            "type" : "string",
            "description" : "Custom CSS that will be injected into the white-label frontend. Use this to customize styling beyond the built-in theme options.",
            "example" : ".my-class { color: red; }"
          },
          "customJavascript" : {
            "maxLength" : 50000,
            "minLength" : 0,
            "type" : "string",
            "description" : "Custom JavaScript that will be injected into the white-label frontend. Use this to integrate third-party tools like chatbots, analytics, or tracking scripts.",
            "example" : "<script src=\"https://cdn.example.com/chatbot.js\"></script>"
          },
          "disableAddingCopiers" : {
            "type" : "boolean",
            "description" : "Disable the ability to add copiers. When enabled, users cannot add new copiers."
          },
          "disableDedicatedIpPurchase" : {
            "type" : "boolean",
            "description" : "Disable the purchase of dedicated IPs. When enabled, users cannot buy dedicated IPs."
          },
          "disableDedicatedProjects" : {
            "type" : "boolean",
            "description" : "Disable the creation of dedicated projects. When enabled, users can only create shared projects."
          },
          "disableInvoicing" : {
            "type" : "boolean",
            "description" : "Disable automatic invoice generation. When enabled, the white-label owner handles invoicing externally."
          },
          "disableMarketplaceSubscription" : {
            "type" : "boolean",
            "description" : "Disable the Subscribe button on the marketplace. When enabled, users cannot subscribe to signals from the marketplace."
          },
          "enableTelegramSignals" : {
            "type" : "boolean",
            "description" : "Enable the Telegram Signals feature for this white-label. When enabled, users can create Telegram connector accounts."
          },
          "enableTradingViewWebhook" : {
            "type" : "boolean",
            "description" : "Enable the TradingView Webhook feature for this white-label. When enabled, users can create TradingView webhook accounts. Requires DNS alias and ingress configuration - contact support to activate."
          },
          "featurePrice" : {
            "maximum" : 1.00,
            "exclusiveMaximum" : false,
            "minimum" : 0.00,
            "exclusiveMinimum" : false,
            "type" : "number",
            "description" : "Price per day (USD) for feature PRO",
            "example" : 0.1
          },
          "hideBrokerInSignalProvider" : {
            "type" : "boolean",
            "description" : "Hide broker information in signal provider listings. When enabled, broker details are not displayed."
          },
          "hideCurrentBalanceInSignalProvider" : {
            "type" : "boolean",
            "description" : "Hide current balance in signal provider listings and detail pages. When enabled, balance and equity values are not displayed."
          },
          "homeLink" : {
            "maxLength" : 255,
            "minLength" : 0,
            "type" : "string",
            "description" : "Optional URL that adds a 'Home' menu item to the navigation. When set, clicking the logo also navigates to this URL.",
            "example" : "https://www.yourbrand.com"
          },
          "layout" : {
            "type" : "string",
            "description" : "Select a layout for the white-label solution."
          },
          "logo" : {
            "type" : "string",
            "description" : "Publicly reachable URL (PNG, SVG, etc.) or a CDN path for the logo displayed in emails and the white-label UI.",
            "example" : "https://cdn.example.com/assets/logo.svg"
          },
          "manualCollection" : {
            "type" : "boolean",
            "description" : "Enable per-customer manual collection. When true, invoices are generated with the real amount in OPEN status, Stripe auto-charging is suppressed, and the white-label owner collects payments externally and marks invoices as paid in the dashboard. Requires disableInvoicing=true."
          },
          "manualCollectionPaymentInstructions" : {
            "maxLength" : 2000,
            "minLength" : 0,
            "type" : "string",
            "description" : "Free-text payment instructions shown to the end customer in the manual-collection statement email (bank account / IBAN, crypto wallet, in-person pickup, etc.). Required when sendManualCollectionEmail=true.",
            "example" : "Bank transfer to IBAN DE89 3704 0044 0532 0130 00 - reference: invoice number"
          },
          "maxAccountsPerProject" : {
            "maximum" : 100,
            "minimum" : 0,
            "type" : "integer",
            "description" : "Maximum number of accounts allowed per project. Set to 0 to use platform default.",
            "format" : "int32",
            "example" : 100
          },
          "maxProjectsPerUser" : {
            "maximum" : 30,
            "minimum" : 0,
            "type" : "integer",
            "description" : "Maximum number of projects a user can create. Set to 0 to use platform default.",
            "format" : "int32",
            "example" : 30
          },
          "name" : {
            "maxLength" : 20,
            "minLength" : 0,
            "type" : "string",
            "description" : "Customer-facing brand or business name, shown as the sender name in emails",
            "example" : "Acme Corp"
          },
          "pro" : {
            "type" : "boolean",
            "description" : "Whether the white-label has PRO enabled"
          },
          "publicMarketplace" : {
            "type" : "boolean",
            "description" : "Marketplace visibility. When true (default), the marketplace is publicly visible to non-authenticated users. When false, only authenticated users can access the marketplace."
          },
          "registrationLink" : {
            "maxLength" : 255,
            "minLength" : 0,
            "type" : "string",
            "description" : "URL to redirect restricted users to a registration/signup page. Required when restrictRegistration is enabled.",
            "example" : "https://www.yourbrand.com/register"
          },
          "restrictRegistration" : {
            "type" : "boolean",
            "description" : "When true, only email addresses listed in allowedRegistrationEmails (or matching allowedEmailDomains) can access this white-label platform."
          },
          "sendManualCollectionEmail" : {
            "type" : "boolean",
            "description" : "When manualCollection=true, send a branded statement email to the end customer containing the outstanding amount and the payment instructions configured by the white-label owner. Requires manualCollection=true and non-empty manualCollectionPaymentInstructions."
          },
          "showScoreOnMarketplace" : {
            "type" : "boolean",
            "description" : "Show signal score on the marketplace. When enabled, signal scores are visible to users on the white-label marketplace."
          },
          "signalProviderAlias" : {
            "maxLength" : 30,
            "minLength" : 0,
            "type" : "string",
            "description" : "Custom label to replace 'Signal Provider' / 'Signal' terminology in the white-label UI. For example, set to 'EA Expert' or 'Strategy' if the word 'Signal' cannot be used for regulatory reasons. When null or empty, the default 'Signal' terminology is used.",
            "example" : "EA Expert"
          },
          "stripeApiKey" : {
            "type" : "string",
            "description" : "Stripe secret API key (sk_live_... or sk_test_...) used to save customers, validate addresses, and handle billing. Note: Using sk_test_ keys will automatically enable disableInvoicing.",
            "example" : "sk_live_...."
          },
          "subdomain" : {
            "maxLength" : 30,
            "minLength" : 0,
            "type" : "string",
            "description" : "Sub-domain used for the white-label solution. Root domains are not allowed.",
            "example" : "trade.yourbrand.com"
          },
          "supportLink" : {
            "maxLength" : 255,
            "minLength" : 0,
            "type" : "string",
            "description" : "Optional URL that adds a 'Support' menu item to the navigation, linking to your help desk or support page.",
            "example" : "https://support.yourbrand.com"
          },
          "theme" : {
            "type" : "string",
            "description" : "Select a theme for the white-label solution."
          },
          "tradeStationClientId" : {
            "type" : "string",
            "description" : "TradeStation OAuth Client ID used to enable support for TradeStation accounts. When set together with the secret, TradeStation becomes an allowed account type for this white-label."
          },
          "tradeStationClientSecret" : {
            "type" : "string",
            "description" : "TradeStation OAuth Client Secret used to enable support for TradeStation accounts. When set together with the client ID, TradeStation becomes an allowed account type for this white-label."
          },
          "tradovateClientId" : {
            "type" : "string",
            "description" : "Tradovate OAuth Client ID used to enable support for Tradovate accounts. When set together with the secret, Tradovate becomes an allowed account type for this white-label."
          },
          "tradovateClientSecret" : {
            "type" : "string",
            "description" : "Tradovate OAuth Client Secret used to enable support for Tradovate accounts. When set together with the client ID, Tradovate becomes an allowed account type for this white-label."
          }
        },
        "description" : "DTO for white-label feature (project)"
      },
      "FieldMetadataDTO" : {
        "type" : "object",
        "properties" : {
          "description" : {
            "type" : "string",
            "description" : "Field description from @Schema annotation if available"
          },
          "dtoClassName" : {
            "type" : "string",
            "description" : "The DTO class name this field belongs to",
            "example" : "AccountInformationDTO"
          },
          "fieldName" : {
            "type" : "string",
            "description" : "Field name",
            "example" : "balance"
          },
          "fieldType" : {
            "type" : "string",
            "description" : "Field Java type",
            "example" : "java.math.BigDecimal"
          }
        },
        "description" : "Represents a field in a DTO that can be included/excluded via API key access policy"
      },
      "FollowerChargeDetailDTO" : {
        "type" : "object",
        "properties" : {
          "billingModel" : {
            "type" : "string",
            "description" : "Billing model applied: MONTHLY_PROFIT or HIGH_WATERMARK"
          },
          "currentCumulativeProfit" : {
            "type" : "number",
            "description" : "HIGH_WATERMARK only: current cumulative profit level from subscription start"
          },
          "followerAccountId" : {
            "type" : "string",
            "description" : "UUID of the follower's trading account",
            "format" : "uuid"
          },
          "followerEmail" : {
            "type" : "string",
            "description" : "Email of the follower's project owner (obfuscated for public providers, full for allowed customers)"
          },
          "followerProfit" : {
            "type" : "number",
            "description" : "Profit generated by this follower's account during the billing period"
          },
          "invoiceId" : {
            "type" : "integer",
            "description" : "Internal invoice ID (integer)",
            "format" : "int32"
          },
          "invoiceNumber" : {
            "type" : "string",
            "description" : "Public invoice number"
          },
          "invoiceStatus" : {
            "type" : "string",
            "description" : "Invoice status: PAID, OPEN, or VOID"
          },
          "monthlySubscriptionFee" : {
            "type" : "number",
            "description" : "Monthly subscription fee charged to this follower for the period"
          },
          "previousHighWatermark" : {
            "type" : "number",
            "description" : "HIGH_WATERMARK only: previous cumulative profit peak before this billing period"
          },
          "profitSharingAmount" : {
            "type" : "number",
            "description" : "Calculated profit sharing charge: followerProfit × profitSharingPercentage / 100"
          },
          "profitSharingPercentage" : {
            "type" : "number",
            "description" : "Profit sharing percentage applied to this follower's profit"
          },
          "totalAmount" : {
            "type" : "number",
            "description" : "Total charge for this follower: monthlySubscriptionFee + profitSharingAmount"
          }
        },
        "description" : "Individual charge details per follower for this month"
      },
      "FollowerCostDetailDTO" : {
        "type" : "object",
        "properties" : {
          "accountNumber" : {
            "type" : "string",
            "description" : "Login account number of the follower account"
          },
          "broker" : {
            "type" : "string",
            "description" : "Broker server of the follower account"
          },
          "cost" : {
            "type" : "number",
            "description" : "Amount the provider paid for this follower in this month"
          },
          "daysActive" : {
            "type" : "integer",
            "description" : "Days the follower subscription was active during this month",
            "format" : "int32"
          },
          "email" : {
            "type" : "string",
            "description" : "Email of the follower, obfuscated or hidden depending on the signal's visibility settings"
          },
          "followerAccountId" : {
            "type" : "string",
            "description" : "UUID of the follower account",
            "format" : "uuid"
          }
        },
        "description" : "One entry per covered follower. Followers with no cost are not listed."
      },
      "ForecastDTO" : {
        "type" : "object",
        "properties" : {
          "currency" : {
            "$ref" : "#/components/schemas/CurrencyTypeDTO"
          },
          "positions" : {
            "type" : "array",
            "readOnly" : true,
            "items" : {
              "type" : "string",
              "readOnly" : true
            }
          },
          "total" : {
            "type" : "number",
            "readOnly" : true
          }
        }
      },
      "FrontendFeatureDTO" : {
        "type" : "object",
        "properties" : {
          "description" : {
            "type" : "string",
            "description" : "Feature description",
            "example" : "Hide financial information like balance, equity, and profit displays"
          },
          "id" : {
            "type" : "string",
            "description" : "Feature enum name",
            "example" : "FINANCIAL_OVERVIEW"
          },
          "name" : {
            "type" : "string",
            "description" : "Feature display name",
            "example" : "Financial Overview"
          }
        },
        "description" : "Represents a frontend feature that can be hidden via API key access policy"
      },
      "GridsterItemDTO" : {
        "type" : "object",
        "properties" : {
          "cols" : {
            "type" : "integer",
            "description" : "Number of columns",
            "format" : "int32",
            "example" : 4
          },
          "dragEnabled" : {
            "type" : "boolean",
            "description" : "Whether dragging is enabled",
            "example" : true
          },
          "maxItemCols" : {
            "type" : "integer",
            "description" : "Maximum number of columns",
            "format" : "int32",
            "example" : 12
          },
          "maxItemRows" : {
            "type" : "integer",
            "description" : "Maximum number of rows",
            "format" : "int32",
            "example" : 10
          },
          "minItemCols" : {
            "type" : "integer",
            "description" : "Minimum number of columns",
            "format" : "int32",
            "example" : 2
          },
          "minItemRows" : {
            "type" : "integer",
            "description" : "Minimum number of rows",
            "format" : "int32",
            "example" : 2
          },
          "resizeEnabled" : {
            "type" : "boolean",
            "description" : "Whether resizing is enabled",
            "example" : true
          },
          "rows" : {
            "type" : "integer",
            "description" : "Number of rows",
            "format" : "int32",
            "example" : 3
          },
          "x" : {
            "type" : "integer",
            "description" : "Column position",
            "format" : "int32",
            "example" : 0
          },
          "y" : {
            "type" : "integer",
            "description" : "Row position",
            "format" : "int32",
            "example" : 0
          }
        },
        "description" : "Grid position and size configuration for a widget"
      },
      "IndicatorHistoryDTO" : {
        "type" : "object",
        "properties" : {
          "countryCode" : {
            "type" : "string"
          },
          "currencyCode" : {
            "type" : "string"
          },
          "indicatorKey" : {
            "type" : "string"
          },
          "inverted" : {
            "type" : "boolean",
            "description" : "A higher number is bad news for this currency, so the surprise sign is flipped for the index"
          },
          "releases" : {
            "type" : "array",
            "description" : "Oldest first, so the list can be charted directly",
            "items" : {
              "$ref" : "#/components/schemas/IndicatorReleaseDTO"
            }
          },
          "samples" : {
            "type" : "integer",
            "description" : "How many past releases carry both an actual and a forecast",
            "format" : "int32"
          },
          "sigmaReliable" : {
            "type" : "boolean",
            "description" : "False when the history is too thin for a standard deviation, in which case no sigma is shown"
          },
          "title" : {
            "type" : "string"
          },
          "unit" : {
            "type" : "string"
          }
        }
      },
      "IndicatorReleaseDTO" : {
        "type" : "object",
        "properties" : {
          "actual" : {
            "type" : "string"
          },
          "actualRaw" : {
            "type" : "number",
            "format" : "double"
          },
          "eventId" : {
            "type" : "string"
          },
          "eventTimeUtc" : {
            "type" : "string",
            "format" : "date-time"
          },
          "forecast" : {
            "type" : "string"
          },
          "forecastRaw" : {
            "type" : "number",
            "format" : "double"
          },
          "period" : {
            "type" : "string"
          },
          "previous" : {
            "type" : "string"
          },
          "previousRaw" : {
            "type" : "number",
            "format" : "double"
          },
          "surprise" : {
            "type" : "number",
            "description" : "actual minus forecast in the unit of the indicator",
            "format" : "double"
          },
          "surpriseSigma" : {
            "type" : "number",
            "description" : "Surprise in standard deviations of this indicator's own history, null when the history is too thin",
            "format" : "double"
          }
        },
        "description" : "Oldest first, so the list can be charted directly"
      },
      "InvoiceDTO" : {
        "required" : [ "currencyType" ],
        "type" : "object",
        "properties" : {
          "amount" : {
            "type" : "number",
            "readOnly" : true
          },
          "created" : {
            "type" : "string",
            "description" : "ISO 8601",
            "format" : "date-time",
            "readOnly" : true
          },
          "currencyType" : {
            "$ref" : "#/components/schemas/CurrencyTypeDTO"
          },
          "description" : {
            "type" : "string",
            "readOnly" : true
          },
          "descriptionPosition" : {
            "type" : "string",
            "readOnly" : true
          },
          "discount" : {
            "type" : "number",
            "readOnly" : true
          },
          "dueDate" : {
            "type" : "string",
            "description" : "ISO 8601",
            "format" : "date-time",
            "readOnly" : true
          },
          "id" : {
            "type" : "string",
            "readOnly" : true
          },
          "invoiceNumber" : {
            "type" : "string",
            "readOnly" : true
          },
          "invoicePaymentUrl" : {
            "type" : "string",
            "readOnly" : true
          },
          "invoicePdfUrl" : {
            "type" : "string",
            "readOnly" : true
          },
          "manualCollection" : {
            "type" : "boolean",
            "description" : "True when this invoice is collected manually by the white-label owner (paymentProviderReference starts with 'Manual|'). Frontend uses this to render the 'mark as paid' action in the white-label dashboard.",
            "readOnly" : true
          },
          "projectId" : {
            "type" : "string",
            "format" : "uuid",
            "readOnly" : true
          },
          "projectName" : {
            "type" : "string",
            "readOnly" : true
          },
          "status" : {
            "type" : "string",
            "readOnly" : true
          },
          "tax" : {
            "$ref" : "#/components/schemas/TaxDTO"
          },
          "vat" : {
            "$ref" : "#/components/schemas/InvoiceVatDTO"
          }
        }
      },
      "InvoiceSummaryDTO" : {
        "type" : "object",
        "properties" : {
          "amount" : {
            "type" : "number",
            "description" : "Invoice amount"
          },
          "created" : {
            "type" : "string",
            "description" : "Invoice creation date",
            "format" : "date-time"
          },
          "customerEmail" : {
            "type" : "string",
            "description" : "Customer email this invoice belongs to. Useful for grouping in the dashboard."
          },
          "description" : {
            "type" : "string",
            "description" : "Invoice description"
          },
          "discount" : {
            "type" : "number",
            "description" : "Invoice discount"
          },
          "dueDate" : {
            "type" : "string",
            "description" : "Invoice due date",
            "format" : "date-time"
          },
          "invoiceNumber" : {
            "type" : "string",
            "description" : "Invoice number"
          },
          "manualCollection" : {
            "type" : "boolean",
            "description" : "True when this invoice is collected manually by the white-label owner (paymentProviderReference starts with 'Manual|')"
          },
          "projectId" : {
            "type" : "string",
            "description" : "Project ID this invoice belongs to",
            "format" : "uuid"
          },
          "status" : {
            "type" : "string",
            "description" : "Invoice status (PAID, UNPAID, etc.)"
          }
        },
        "description" : "Invoice summary information"
      },
      "InvoiceVatDTO" : {
        "type" : "object",
        "properties" : {
          "customerVatNumber" : {
            "type" : "string",
            "readOnly" : true
          },
          "inclusive" : {
            "type" : "boolean",
            "readOnly" : true
          },
          "mode" : {
            "type" : "string",
            "readOnly" : true
          },
          "ratePercent" : {
            "type" : "number",
            "readOnly" : true
          },
          "reverseCharge" : {
            "type" : "boolean",
            "readOnly" : true
          },
          "statement" : {
            "type" : "string",
            "readOnly" : true
          },
          "supplierVatNumber" : {
            "type" : "string",
            "readOnly" : true
          },
          "taxAmount" : {
            "type" : "number",
            "readOnly" : true
          }
        },
        "readOnly" : true
      },
      "JsonNode" : {
        "type" : "object",
        "description" : "Full template payload. Includes a `schemaVersion` discriminator describing its JSON shape; older versions are migrated transparently on read."
      },
      "LinkedAccountSummaryDTO" : {
        "type" : "object",
        "properties" : {
          "accountId" : {
            "type" : "string",
            "format" : "uuid"
          },
          "appliedAt" : {
            "type" : "string",
            "format" : "date-time"
          },
          "appliedRevision" : {
            "type" : "integer",
            "format" : "int64"
          }
        },
        "description" : "One account linked to a template. Compare `appliedRevision` with the template's current revision to detect when the linked account is behind."
      },
      "LogDTO" : {
        "type" : "object",
        "properties" : {
          "accountId" : {
            "type" : "string",
            "format" : "uuid",
            "readOnly" : true
          },
          "acknowledged" : {
            "type" : "boolean"
          },
          "customerEmail" : {
            "type" : "string",
            "readOnly" : true
          },
          "date" : {
            "type" : "string",
            "description" : "ISO 8601",
            "format" : "date-time",
            "readOnly" : true
          },
          "id" : {
            "type" : "integer",
            "format" : "int64",
            "readOnly" : true
          },
          "logType" : {
            "type" : "string",
            "readOnly" : true
          },
          "projectId" : {
            "type" : "string",
            "format" : "uuid",
            "readOnly" : true
          },
          "text" : {
            "type" : "string",
            "readOnly" : true
          }
        }
      },
      "LogTypeDTO" : {
        "required" : [ "id" ],
        "type" : "object",
        "properties" : {
          "id" : {
            "type" : "integer",
            "format" : "int32"
          },
          "name" : {
            "type" : "string",
            "readOnly" : true
          }
        },
        "description" : "You have only to set the id e.g 1 for Telegram. Example: {id:1}"
      },
      "MarkInvoicePaidRequestDTO" : {
        "type" : "object",
        "properties" : {
          "externalReference" : {
            "maxLength" : 100,
            "minLength" : 0,
            "type" : "string",
            "description" : "Optional external payment reference (bank transaction id, crypto tx hash, in-person receipt number, etc.).",
            "example" : "WIRE-2026-04-15-001"
          },
          "note" : {
            "maxLength" : 120,
            "minLength" : 0,
            "type" : "string",
            "description" : "Optional free-text note for audit purposes.",
            "example" : "Paid in cash on 2026-04-15"
          }
        },
        "description" : "Request body for marking a manual-collection invoice as paid by the white-label owner"
      },
      "MarketNewsArticleDTO" : {
        "type" : "object",
        "properties" : {
          "category" : {
            "type" : "string",
            "description" : "Feed category",
            "readOnly" : true,
            "example" : "forex"
          },
          "currencies" : {
            "type" : "array",
            "description" : "Affected ISO-4217 currencies",
            "readOnly" : true,
            "example" : [ "USD" ],
            "items" : {
              "type" : "string",
              "description" : "Affected ISO-4217 currencies",
              "readOnly" : true,
              "example" : "[\"USD\"]"
            }
          },
          "fetchedAt" : {
            "type" : "string",
            "description" : "When we first fetched it",
            "format" : "date-time",
            "readOnly" : true
          },
          "headlineEn" : {
            "type" : "string",
            "description" : "Headline written by us, never the publisher's",
            "readOnly" : true
          },
          "id" : {
            "type" : "string",
            "description" : "MongoDB document id",
            "readOnly" : true
          },
          "impact" : {
            "type" : "string",
            "description" : "Impact classification",
            "readOnly" : true,
            "enum" : [ "HOLIDAY", "LOW", "MEDIUM", "HIGH" ]
          },
          "instruments" : {
            "type" : "array",
            "description" : "Affected non-currency instruments",
            "readOnly" : true,
            "example" : [ "XAU" ],
            "items" : {
              "type" : "string",
              "description" : "Affected non-currency instruments",
              "readOnly" : true,
              "example" : "[\"XAU\"]"
            }
          },
          "publishedAt" : {
            "type" : "string",
            "description" : "Publication time in UTC",
            "format" : "date-time",
            "readOnly" : true
          },
          "sentiment" : {
            "type" : "string",
            "description" : "Sentiment classification, displayed only",
            "readOnly" : true,
            "enum" : [ "BEARISH", "NEUTRAL", "BULLISH" ]
          },
          "sentimentScore" : {
            "type" : "number",
            "description" : "Sentiment score in [-1, 1]",
            "format" : "double",
            "readOnly" : true
          },
          "summaryEn" : {
            "type" : "string",
            "description" : "Summary written by us, at most 40 words",
            "readOnly" : true
          },
          "urlHash" : {
            "type" : "string",
            "description" : "SHA-256 of the canonical article URL, the dedup key",
            "readOnly" : true
          }
        },
        "description" : "Market news article, summarised in our own words with a link to the source",
        "readOnly" : true
      },
      "MarketNewsPageDTO" : {
        "type" : "object",
        "properties" : {
          "items" : {
            "type" : "array",
            "description" : "Articles of this page, newest first",
            "readOnly" : true,
            "items" : {
              "$ref" : "#/components/schemas/MarketNewsArticleDTO"
            }
          },
          "page" : {
            "type" : "integer",
            "description" : "Zero based page index",
            "format" : "int32",
            "readOnly" : true,
            "example" : 0
          },
          "size" : {
            "type" : "integer",
            "description" : "Page size",
            "format" : "int32",
            "readOnly" : true,
            "example" : 25
          },
          "total" : {
            "type" : "integer",
            "description" : "Total number of matching articles",
            "format" : "int64",
            "readOnly" : true,
            "example" : 212
          }
        },
        "description" : "One page of market news articles"
      },
      "MarketQuoteDTO" : {
        "type" : "object",
        "properties" : {
          "ask" : {
            "type" : "number",
            "description" : "Ask price",
            "readOnly" : true
          },
          "bid" : {
            "type" : "number",
            "description" : "Bid price",
            "readOnly" : true
          },
          "symbol" : {
            "type" : "string",
            "description" : "Symbol name",
            "readOnly" : true
          },
          "symbolInfo" : {
            "$ref" : "#/components/schemas/SymbolDTO"
          },
          "timestamp" : {
            "type" : "string",
            "description" : "Quote timestamp (ISO 8601)",
            "format" : "date-time",
            "readOnly" : true
          }
        }
      },
      "MarketplaceDTO" : {
        "type" : "object",
        "properties" : {
          "signals" : {
            "type" : "array",
            "items" : {
              "$ref" : "#/components/schemas/FeatureDTO"
            }
          }
        }
      },
      "MasterAccountSummaryDTO" : {
        "type" : "object",
        "properties" : {
          "master" : {
            "$ref" : "#/components/schemas/AccountDTO"
          },
          "slaveCount" : {
            "type" : "integer",
            "format" : "int32"
          },
          "slaves" : {
            "type" : "array",
            "items" : {
              "$ref" : "#/components/schemas/AccountDTO"
            }
          }
        },
        "description" : "An account that has at least one slave copying from it, together with its slave accounts. `slaves` holds the same payload as GET /accounts/{accountId}/slaves: direct account-to-account copiers plus accounts copying through a strategy of this account. Only direct slaves are listed (no transitive expansion): in a chain A -> B -> C you get one entry for A with slave B and one entry for B with slave C, so an intermediate account appears both as a master and as a slave."
      },
      "MissingSymbolMappingDTO" : {
        "type" : "object",
        "properties" : {
          "copierId" : {
            "type" : "string",
            "format" : "uuid"
          },
          "fromAccount" : {
            "type" : "string"
          },
          "fromAccountId" : {
            "type" : "string",
            "format" : "uuid"
          },
          "lastTimestampDetected" : {
            "type" : "integer",
            "format" : "int64"
          },
          "symbol" : {
            "type" : "string"
          }
        },
        "description" : "List of missing symbol mappings for this account",
        "readOnly" : true
      },
      "MonthlyEarningsDTO" : {
        "type" : "object",
        "properties" : {
          "coveredFollowerCosts" : {
            "type" : "number",
            "description" : "Costs the signal provider covers for hosting follower accounts (only when coverFollowerCosts is enabled)"
          },
          "followerCharges" : {
            "type" : "array",
            "description" : "Individual charge details per follower for this month",
            "items" : {
              "$ref" : "#/components/schemas/FollowerChargeDetailDTO"
            }
          },
          "month" : {
            "type" : "integer",
            "description" : "Month number (1-12)",
            "format" : "int32"
          },
          "totalCreditedNet" : {
            "type" : "number",
            "description" : "Net amount credited to the provider's balance this month"
          },
          "totalEarnedGross" : {
            "type" : "number",
            "description" : "Total gross amount from all follower charges this month"
          },
          "totalEarnedGrossPaid" : {
            "type" : "number",
            "description" : "Gross amount from PAID invoices this month"
          },
          "totalEarnedGrossUnpaid" : {
            "type" : "number",
            "description" : "Gross amount from OPEN invoices this month"
          },
          "totalEarnedGrossVoid" : {
            "type" : "number",
            "description" : "Gross amount from VOID (cancelled) invoices this month"
          },
          "year" : {
            "type" : "integer",
            "description" : "Year (e.g. 2026)",
            "format" : "int32"
          }
        },
        "description" : "Per-month earnings breakdown with individual follower charge details"
      },
      "MonthlyFollowerCostDTO" : {
        "type" : "object",
        "properties" : {
          "coveredFollowers" : {
            "type" : "integer",
            "description" : "Number of followers the provider paid for in this month",
            "format" : "int32"
          },
          "current" : {
            "type" : "boolean",
            "description" : "True for the running month: the amount is month-to-date and not yet invoiced"
          },
          "followers" : {
            "type" : "array",
            "description" : "One entry per covered follower. Followers with no cost are not listed.",
            "items" : {
              "$ref" : "#/components/schemas/FollowerCostDetailDTO"
            }
          },
          "month" : {
            "type" : "integer",
            "description" : "Month of the billing period (1-12)",
            "format" : "int32",
            "example" : 9
          },
          "pricePerAccountPerDay" : {
            "type" : "number",
            "description" : "Rate charged to the provider per covered follower account and day"
          },
          "totalCost" : {
            "type" : "number",
            "description" : "Total covered follower costs of this month"
          },
          "year" : {
            "type" : "integer",
            "description" : "Year of the billing period",
            "format" : "int32",
            "example" : 2026
          }
        },
        "description" : "Per-month breakdown, oldest month first"
      },
      "NewsEventSelectionDTO" : {
        "type" : "object",
        "properties" : {
          "categoryBlacklist" : {
            "type" : "array",
            "description" : "Event categories that are ignored",
            "example" : [ "bnd" ],
            "items" : {
              "type" : "string",
              "description" : "Event categories that are ignored",
              "example" : "[\"bnd\"]"
            }
          },
          "currencyWhitelist" : {
            "type" : "array",
            "description" : "Only these currencies are considered. Empty means the currencies are derived from the symbol.",
            "example" : [ "USD", "EUR" ],
            "items" : {
              "type" : "string",
              "description" : "Only these currencies are considered. Empty means the currencies are derived from the symbol.",
              "example" : "[\"USD\",\"EUR\"]"
            }
          },
          "eventTitleBlacklist" : {
            "type" : "array",
            "description" : "Events whose title contains one of these fragments are ignored (case insensitive)",
            "example" : [ "Bond Auction" ],
            "items" : {
              "type" : "string",
              "description" : "Events whose title contains one of these fragments are ignored (case insensitive)",
              "example" : "[\"Bond Auction\"]"
            }
          },
          "eventTitleWhitelist" : {
            "type" : "array",
            "description" : "If not empty, only events whose title contains one of these fragments are considered (case insensitive)",
            "example" : [ "Non-Farm", "CPI" ],
            "items" : {
              "type" : "string",
              "description" : "If not empty, only events whose title contains one of these fragments are considered (case insensitive)",
              "example" : "[\"Non-Farm\",\"CPI\"]"
            }
          },
          "includeGlobalEvents" : {
            "type" : "boolean",
            "description" : "Whether events without a currency (OPEC, G20, geopolitics) apply to every symbol",
            "example" : true,
            "default" : true
          },
          "includeHolidays" : {
            "type" : "boolean",
            "description" : "Whether bank holidays are treated as events",
            "example" : false,
            "default" : false
          },
          "minImpact" : {
            "type" : "string",
            "description" : "Minimum impact of an event to be considered: HOLIDAY, LOW, MEDIUM or HIGH",
            "example" : "HIGH",
            "default" : "HIGH",
            "enum" : [ "HOLIDAY", "LOW", "MEDIUM", "HIGH" ]
          },
          "symbolMappings" : {
            "type" : "array",
            "description" : "Manual symbol pattern to currency overrides, evaluated top to bottom",
            "items" : {
              "$ref" : "#/components/schemas/SymbolCurrencyMappingDTO"
            }
          }
        },
        "description" : "Selects the calendar events a news feature reacts to"
      },
      "NewsFilterBacktestDTO" : {
        "type" : "object",
        "properties" : {
          "byIndicator" : {
            "type" : "array",
            "description" : "Which indicators cost the most, biggest loss first",
            "items" : {
              "$ref" : "#/components/schemas/NewsFilterBacktestEventDTO"
            }
          },
          "estimatedEffect" : {
            "type" : "number",
            "description" : "What the configuration would have done to the result: the negated profit of the skipped trades"
          },
          "eventsInRange" : {
            "type" : "integer",
            "description" : "Calendar events available in the range. Zero means the archive does not reach back that far, not that nothing would trigger.",
            "format" : "int32"
          },
          "fromUtc" : {
            "type" : "string",
            "format" : "date-time"
          },
          "skippedNetProfit" : {
            "type" : "number",
            "description" : "Combined realised net profit of the skipped trades"
          },
          "skippedTrades" : {
            "type" : "integer",
            "description" : "Trades whose open fell inside a blackout window",
            "format" : "int32"
          },
          "toUtc" : {
            "type" : "string",
            "format" : "date-time"
          },
          "totalNetProfit" : {
            "type" : "number",
            "description" : "Combined realised net profit of the examined trades"
          },
          "totalTrades" : {
            "type" : "integer",
            "description" : "Trades examined in the range",
            "format" : "int32"
          },
          "trades" : {
            "type" : "array",
            "description" : "The skipped trades themselves, newest first and capped",
            "items" : {
              "$ref" : "#/components/schemas/NewsFilterBacktestTradeDTO"
            }
          },
          "tradesTruncated" : {
            "type" : "boolean",
            "description" : "True when the trade list was cut off"
          },
          "unresolvedSymbols" : {
            "type" : "array",
            "description" : "Symbols whose currencies could not be resolved by name, so they were never blocked",
            "items" : {
              "type" : "string",
              "description" : "Symbols whose currencies could not be resolved by name, so they were never blocked"
            }
          }
        }
      },
      "NewsFilterBacktestEventDTO" : {
        "type" : "object",
        "properties" : {
          "currencyCode" : {
            "type" : "string"
          },
          "indicatorKey" : {
            "type" : "string",
            "description" : "Normalised indicator key, so the same release across months groups together"
          },
          "netProfit" : {
            "type" : "number",
            "description" : "Combined realised net profit of those trades"
          },
          "title" : {
            "type" : "string"
          },
          "trades" : {
            "type" : "integer",
            "description" : "How many replayed trades this indicator would have skipped",
            "format" : "int32"
          }
        },
        "description" : "Which indicators cost the most, biggest loss first"
      },
      "NewsFilterBacktestRequestDTO" : {
        "required" : [ "accountId", "configuration" ],
        "type" : "object",
        "properties" : {
          "accountId" : {
            "type" : "string",
            "description" : "Account whose closed trades are replayed",
            "format" : "uuid"
          },
          "configuration" : {
            "$ref" : "#/components/schemas/FeatureNewsFilterDTO"
          },
          "days" : {
            "type" : "integer",
            "description" : "How far back to replay, in days",
            "format" : "int32",
            "example" : 90
          }
        }
      },
      "NewsFilterBacktestTradeDTO" : {
        "type" : "object",
        "properties" : {
          "closeTimeUtc" : {
            "type" : "string",
            "description" : "When the trade was closed",
            "format" : "date-time"
          },
          "currencyCode" : {
            "type" : "string"
          },
          "eventId" : {
            "type" : "string",
            "description" : "Event whose blackout window the open fell into"
          },
          "eventTimeUtc" : {
            "type" : "string",
            "format" : "date-time"
          },
          "eventTitle" : {
            "type" : "string"
          },
          "impact" : {
            "type" : "string",
            "enum" : [ "HOLIDAY", "LOW", "MEDIUM", "HIGH" ]
          },
          "netProfit" : {
            "type" : "number",
            "description" : "Realised net profit of the trade"
          },
          "openTimeUtc" : {
            "type" : "string",
            "description" : "When the trade was opened",
            "format" : "date-time"
          },
          "symbol" : {
            "type" : "string",
            "description" : "Symbol as the account saw it"
          },
          "volume" : {
            "type" : "number",
            "description" : "Traded volume in lots"
          }
        },
        "description" : "The skipped trades themselves, newest first and capped"
      },
      "NewsFilterPreviewDTO" : {
        "type" : "object",
        "properties" : {
          "fromUtc" : {
            "type" : "string",
            "description" : "Start of the previewed range",
            "format" : "date-time",
            "readOnly" : true
          },
          "lastSyncUtc" : {
            "type" : "string",
            "description" : "When the ingestion last wrote anything, null means it never ran",
            "format" : "date-time",
            "readOnly" : true
          },
          "symbols" : {
            "type" : "array",
            "description" : "One entry per requested symbol, in the requested order",
            "readOnly" : true,
            "items" : {
              "$ref" : "#/components/schemas/NewsFilterPreviewSymbolDTO"
            }
          },
          "toUtc" : {
            "type" : "string",
            "description" : "End of the previewed range",
            "format" : "date-time",
            "readOnly" : true
          }
        },
        "description" : "Dry run of a news filter configuration, answers \"will my mapping actually fire?\""
      },
      "NewsFilterPreviewSymbolDTO" : {
        "type" : "object",
        "properties" : {
          "currencies" : {
            "type" : "array",
            "description" : "Currencies the symbol was resolved to, ALL included when global events are on",
            "readOnly" : true,
            "example" : [ "EUR", "CHF", "ALL" ],
            "items" : {
              "type" : "string",
              "description" : "Currencies the symbol was resolved to, ALL included when global events are on",
              "readOnly" : true,
              "example" : "[\"EUR\",\"CHF\",\"ALL\"]"
            }
          },
          "symbol" : {
            "type" : "string",
            "description" : "The symbol as it was requested",
            "readOnly" : true,
            "example" : "EURCHF"
          },
          "unresolved" : {
            "type" : "boolean",
            "description" : "True when the name alone could not be resolved. A node may still resolve it from the broker currency data, so this is a hint and not a verdict.",
            "readOnly" : true,
            "example" : false
          },
          "windows" : {
            "type" : "array",
            "description" : "Blackout windows in the requested range, ascending by event time",
            "readOnly" : true,
            "items" : {
              "$ref" : "#/components/schemas/NewsFilterPreviewWindowDTO"
            }
          }
        },
        "description" : "Preview result for one symbol: what it maps to and what would trigger"
      },
      "NewsFilterPreviewWindowDTO" : {
        "type" : "object",
        "properties" : {
          "blackoutFromUtc" : {
            "type" : "string",
            "description" : "Start of the blackout, eventTimeUtc minus blackoutBeforeMinutes",
            "format" : "date-time",
            "readOnly" : true
          },
          "blackoutToUtc" : {
            "type" : "string",
            "description" : "End of the blackout, eventTimeUtc plus blackoutAfterMinutes",
            "format" : "date-time",
            "readOnly" : true
          },
          "currencyCode" : {
            "type" : "string",
            "description" : "Currency of the event, ALL for global events",
            "readOnly" : true,
            "example" : "EUR"
          },
          "disputed" : {
            "type" : "boolean",
            "description" : "True when the sources disagree on the release time, so the window may move",
            "readOnly" : true,
            "example" : false
          },
          "eventId" : {
            "type" : "string",
            "description" : "Id of the triggering event, the same id the skip log line names",
            "readOnly" : true
          },
          "eventTimeUtc" : {
            "type" : "string",
            "description" : "Release time of the event",
            "format" : "date-time",
            "readOnly" : true
          },
          "impact" : {
            "type" : "string",
            "description" : "Impact rating of the event",
            "readOnly" : true,
            "enum" : [ "HOLIDAY", "LOW", "MEDIUM", "HIGH" ]
          },
          "title" : {
            "type" : "string",
            "description" : "Event title",
            "readOnly" : true,
            "example" : "ECB Interest Rate Decision"
          }
        },
        "description" : "One blackout window a symbol would run into",
        "readOnly" : true
      },
      "NotificationCategoryTypeDTO" : {
        "required" : [ "id" ],
        "type" : "object",
        "properties" : {
          "id" : {
            "type" : "integer",
            "format" : "int32"
          },
          "name" : {
            "type" : "string",
            "readOnly" : true
          }
        }
      },
      "NotificationChannelDTO" : {
        "type" : "object",
        "properties" : {
          "accountId" : {
            "type" : "string",
            "description" : "Set when level is ACCOUNT",
            "format" : "uuid",
            "readOnly" : true
          },
          "channelType" : {
            "type" : "string",
            "description" : "Which channel this is",
            "readOnly" : true,
            "enum" : [ "TELEGRAM", "WEBHOOK" ]
          },
          "displayName" : {
            "type" : "string",
            "description" : "Label for the picker",
            "readOnly" : true,
            "example" : "Telegram"
          },
          "featureId" : {
            "type" : "string",
            "description" : "Id of the channel feature instance, the value for NotificationTargetDTO.featureId",
            "format" : "uuid",
            "readOnly" : true
          },
          "level" : {
            "type" : "string",
            "description" : "Where the channel is attached: PROJECT or ACCOUNT",
            "readOnly" : true,
            "example" : "PROJECT"
          },
          "recipients" : {
            "type" : "array",
            "description" : "Addressable recipients. Empty means the channel has exactly one destination.",
            "readOnly" : true,
            "items" : {
              "$ref" : "#/components/schemas/NotificationRecipientDTO"
            }
          }
        },
        "description" : "A notification channel a feature can address. Nothing here is persisted, it is derived from the channel feature itself."
      },
      "NotificationRecipientDTO" : {
        "type" : "object",
        "properties" : {
          "displayName" : {
            "type" : "string",
            "description" : "Label for the picker",
            "readOnly" : true,
            "example" : "@john"
          },
          "key" : {
            "type" : "string",
            "description" : "The value to store in NotificationTargetDTO.recipient",
            "readOnly" : true,
            "example" : "@john"
          }
        },
        "description" : "One addressable recipient inside a notification channel",
        "readOnly" : true
      },
      "NotificationTargetDTO" : {
        "type" : "object",
        "properties" : {
          "featureId" : {
            "type" : "string",
            "description" : "Id of the channel feature instance, for example the project's Telegram feature",
            "format" : "uuid"
          },
          "recipient" : {
            "type" : "string",
            "description" : "Null means every recipient of that channel. Telegram: the username. Email: the address. Slack, Discord, Teams and webhook always leave this null.",
            "example" : "@john"
          }
        },
        "description" : "One notification destination: a channel feature instance, optionally narrowed to a single recipient of that channel."
      },
      "PaymentMethodDTO" : {
        "type" : "object",
        "properties" : {
          "created" : {
            "type" : "string",
            "format" : "date-time",
            "readOnly" : true
          },
          "currency" : {
            "type" : "string",
            "readOnly" : true
          },
          "expirationDate" : {
            "type" : "string",
            "readOnly" : true
          },
          "id" : {
            "type" : "string",
            "format" : "uuid",
            "readOnly" : true
          },
          "identifier" : {
            "type" : "string",
            "readOnly" : true
          },
          "number" : {
            "type" : "string",
            "readOnly" : true
          },
          "status" : {
            "type" : "boolean",
            "readOnly" : true
          },
          "statusMessage" : {
            "type" : "string",
            "readOnly" : true
          },
          "type" : {
            "type" : "string",
            "readOnly" : true
          }
        }
      },
      "PayoutDTO" : {
        "type" : "object",
        "properties" : {
          "wiseDetails" : {
            "type" : "array",
            "description" : "Wise payout details",
            "items" : {
              "$ref" : "#/components/schemas/WisePayoutDetailsDTO"
            }
          }
        }
      },
      "PerformanceMetricsDTO" : {
        "type" : "object",
        "properties" : {
          "accountType" : {
            "$ref" : "#/components/schemas/AccountTypeDTO"
          },
          "advancedAnalyticsAvailable" : {
            "type" : "boolean",
            "description" : "True if collected balance/equity history exists and advanced analytics can be shown",
            "readOnly" : true
          },
          "avgCommissionPerTrade" : {
            "type" : "number",
            "description" : "Average commission paid per trade",
            "readOnly" : true
          },
          "avgDrawdown" : {
            "type" : "number",
            "description" : "Average drawdown percentage during trading period (%)",
            "readOnly" : true
          },
          "avgHoldingTimeSeconds" : {
            "type" : "integer",
            "description" : "Average holding time for closed trades in seconds (duration)",
            "format" : "int64",
            "readOnly" : true
          },
          "avgLoss" : {
            "type" : "number",
            "description" : "Average loss of losing trades as positive amount",
            "readOnly" : true
          },
          "avgLotSize" : {
            "type" : "number",
            "description" : "Average lot size per trade",
            "readOnly" : true
          },
          "avgNetProfitPerTrade" : {
            "type" : "number",
            "description" : "Average profit per trade in account currency (amount)",
            "readOnly" : true
          },
          "avgProfitPerMonth" : {
            "type" : "object",
            "additionalProperties" : {
              "type" : "number",
              "description" : "Monthly average profit amount - key: YYYY-MM format, value: average profit per trade (amount)",
              "readOnly" : true
            },
            "description" : "Monthly average profit amount - key: YYYY-MM format, value: average profit per trade (amount)",
            "readOnly" : true
          },
          "avgRecoveryTimeHours" : {
            "type" : "number",
            "description" : "Average number of hours to recover from a drawdown back to a new equity peak",
            "readOnly" : true
          },
          "avgRiskReward" : {
            "type" : "number",
            "description" : "Average risk/reward ratio",
            "readOnly" : true
          },
          "avgSwapPerTrade" : {
            "type" : "number",
            "description" : "Average swap per trade in account currency",
            "readOnly" : true
          },
          "avgWin" : {
            "type" : "number",
            "description" : "Average profit of winning trades",
            "readOnly" : true
          },
          "balanceEquityDivergencePerDay" : {
            "type" : "object",
            "additionalProperties" : {
              "type" : "number",
              "description" : "Daily balance-to-equity divergence ratio — key: YYYY-MM-DD, value: abs(equity - balance) / balance as percentage (%)",
              "readOnly" : true
            },
            "description" : "Daily balance-to-equity divergence ratio — key: YYYY-MM-DD, value: abs(equity - balance) / balance as percentage (%)",
            "readOnly" : true
          },
          "bestDay" : {
            "$ref" : "#/components/schemas/PeriodPerformanceDTO"
          },
          "bestMonth" : {
            "$ref" : "#/components/schemas/PeriodPerformanceDTO"
          },
          "bestWeek" : {
            "$ref" : "#/components/schemas/PeriodPerformanceDTO"
          },
          "breakevenTrades" : {
            "type" : "integer",
            "description" : "Number of breakeven trades",
            "format" : "int32",
            "readOnly" : true
          },
          "broker" : {
            "type" : "string",
            "description" : "Broker name or identifier",
            "readOnly" : true
          },
          "currency" : {
            "type" : "string",
            "description" : "Account currency code (e.g., USD, EUR, GBP)",
            "readOnly" : true
          },
          "currentEquityDrawdown" : {
            "type" : "number",
            "description" : "Current equity drawdown from the previous peak (%)",
            "readOnly" : true
          },
          "currentFloatingPnl" : {
            "type" : "number",
            "description" : "Current floating profit/loss in account currency (amount)",
            "readOnly" : true
          },
          "dailyBalance" : {
            "type" : "object",
            "additionalProperties" : {
              "type" : "number",
              "description" : "Daily account balance - key: YYYY-MM-DD format, value: end-of-day balance UTC in account currency (amount)",
              "readOnly" : true
            },
            "description" : "Daily account balance - key: YYYY-MM-DD format, value: end-of-day balance UTC in account currency (amount)",
            "readOnly" : true
          },
          "dailyBalanceTransactions" : {
            "type" : "object",
            "additionalProperties" : {
              "type" : "number",
              "description" : "Daily balance transactions - key: YYYY-MM-DD format, value: net transaction amount (positive for deposits, negative for withdrawals) in account currency (amount)",
              "readOnly" : true
            },
            "description" : "Daily balance transactions - key: YYYY-MM-DD format, value: net transaction amount (positive for deposits, negative for withdrawals) in account currency (amount)",
            "readOnly" : true
          },
          "dailyEquity" : {
            "type" : "object",
            "additionalProperties" : {
              "type" : "number",
              "description" : "Daily account equity - key: YYYY-MM-DD format, value: end-of-day equity UTC in account currency (amount)",
              "readOnly" : true
            },
            "description" : "Daily account equity - key: YYYY-MM-DD format, value: end-of-day equity UTC in account currency (amount)",
            "readOnly" : true
          },
          "dataCollectorEnabled" : {
            "type" : "boolean",
            "description" : "True if the Data Collector feature is enabled for the account",
            "readOnly" : true
          },
          "dataCollectorHistoryEndAt" : {
            "type" : "string",
            "description" : "Timestamp of the most recent Data Collector sample",
            "format" : "date-time",
            "readOnly" : true
          },
          "dataCollectorHistoryStartAt" : {
            "type" : "string",
            "description" : "Timestamp of the first available Data Collector sample",
            "format" : "date-time",
            "readOnly" : true
          },
          "dataCollectorSamples" : {
            "type" : "integer",
            "description" : "Number of Data Collector samples used for advanced analytics",
            "format" : "int32",
            "readOnly" : true
          },
          "directionPerformance" : {
            "$ref" : "#/components/schemas/DirectionPerformanceDTO"
          },
          "equityCurveSmoothness" : {
            "type" : "number",
            "description" : "R-squared of equity curve vs. time linear regression (0-1). Higher means smoother equity growth.",
            "readOnly" : true
          },
          "equityDrawdownPerDay" : {
            "type" : "object",
            "additionalProperties" : {
              "type" : "number",
              "description" : "Daily equity drawdown from Data Collector - key: YYYY-MM-DD format, value: drawdown from previous equity peak (%)",
              "readOnly" : true
            },
            "description" : "Daily equity drawdown from Data Collector - key: YYYY-MM-DD format, value: drawdown from previous equity peak (%)",
            "readOnly" : true
          },
          "equityVolatility" : {
            "type" : "number",
            "description" : "Intraday equity volatility — standard deviation of per-sample equity changes as percentage of equity (%)",
            "readOnly" : true
          },
          "expectancy" : {
            "type" : "number",
            "description" : "Mathematical expectancy per trade in account currency (amount)",
            "readOnly" : true
          },
          "firstTradeAt" : {
            "type" : "string",
            "description" : "Timestamp of the first trade in the history window",
            "format" : "date-time",
            "readOnly" : true
          },
          "floatingPnlPerDay" : {
            "type" : "object",
            "additionalProperties" : {
              "type" : "number",
              "description" : "Daily floating PnL from Data Collector - key: YYYY-MM-DD format, value: end-of-day floating profit/loss in account currency (amount)",
              "readOnly" : true
            },
            "description" : "Daily floating PnL from Data Collector - key: YYYY-MM-DD format, value: end-of-day floating profit/loss in account currency (amount)",
            "readOnly" : true
          },
          "grossLoss" : {
            "type" : "number",
            "description" : "Absolute sum of all losing trades",
            "readOnly" : true
          },
          "grossProfit" : {
            "type" : "number",
            "description" : "Sum of all profitable trades",
            "readOnly" : true
          },
          "intradayMaxDrawdown" : {
            "type" : "number",
            "description" : "Worst intraday peak-to-trough equity drawdown from granular Data Collector samples (%)",
            "readOnly" : true
          },
          "largestLoss" : {
            "type" : "number",
            "description" : "Largest single losing trade in account currency (amount, negative value)",
            "readOnly" : true
          },
          "largestWin" : {
            "type" : "number",
            "description" : "Largest single winning trade in account currency (amount)",
            "readOnly" : true
          },
          "lastTradeAt" : {
            "type" : "string",
            "description" : "Timestamp of the last trade in the history window",
            "format" : "date-time",
            "readOnly" : true
          },
          "longestLossStreak" : {
            "type" : "integer",
            "description" : "Longest consecutive losing trades streak (count)",
            "format" : "int32",
            "readOnly" : true
          },
          "longestWinStreak" : {
            "type" : "integer",
            "description" : "Longest consecutive winning trades streak (count)",
            "format" : "int32",
            "readOnly" : true
          },
          "losingTrades" : {
            "type" : "integer",
            "description" : "Number of losing trades",
            "format" : "int32",
            "readOnly" : true
          },
          "maxCollectorDrawdown" : {
            "type" : "number",
            "description" : "Maximum equity drawdown observed in collected history (%)",
            "readOnly" : true
          },
          "maxDrawdown" : {
            "type" : "number",
            "description" : "Maximum drawdown percentage - worst peak-to-trough decline (%)",
            "readOnly" : true
          },
          "maxFloatingLoss" : {
            "type" : "number",
            "description" : "Maximum adverse floating loss observed in Data Collector history (amount, negative value)",
            "readOnly" : true
          },
          "maxFloatingProfit" : {
            "type" : "number",
            "description" : "Maximum favorable floating profit observed in Data Collector history (amount)",
            "readOnly" : true
          },
          "maxLotSize" : {
            "type" : "number",
            "description" : "Maximum lot size used in a single trade",
            "readOnly" : true
          },
          "maxRecoveryTimeHours" : {
            "type" : "number",
            "description" : "Maximum number of hours to recover from a drawdown back to a new equity peak",
            "readOnly" : true
          },
          "monthsActive" : {
            "type" : "integer",
            "description" : "Active months from first to last trade (count)",
            "format" : "int32",
            "readOnly" : true
          },
          "peakFloatingPnl" : {
            "type" : "number",
            "description" : "Maximum favorable floating PnL ever observed in granular Data Collector samples (amount)",
            "readOnly" : true
          },
          "profitAmountPerMonth" : {
            "type" : "object",
            "additionalProperties" : {
              "type" : "number",
              "description" : "Monthly profit amount in account currency - key: YYYY-MM format, value: total profit (amount)",
              "readOnly" : true
            },
            "description" : "Monthly profit amount in account currency - key: YYYY-MM format, value: total profit (amount)",
            "readOnly" : true
          },
          "profitFactor" : {
            "type" : "number",
            "description" : "Profit factor as ratio",
            "readOnly" : true
          },
          "profitPerHour" : {
            "type" : "object",
            "additionalProperties" : {
              "type" : "number",
              "description" : "Net profit by hour of day (UTC)",
              "readOnly" : true
            },
            "description" : "Net profit by hour of day (UTC)",
            "readOnly" : true
          },
          "profitPerWeekday" : {
            "type" : "object",
            "additionalProperties" : {
              "type" : "number",
              "description" : "Net profit by weekday",
              "readOnly" : true
            },
            "description" : "Net profit by weekday",
            "readOnly" : true
          },
          "profitPercentagePerMonth" : {
            "type" : "object",
            "additionalProperties" : {
              "type" : "number",
              "description" : "Monthly profit percentage - key: YYYY-MM format, value: profit percentage (%)",
              "readOnly" : true
            },
            "description" : "Monthly profit percentage - key: YYYY-MM format, value: profit percentage (%)",
            "readOnly" : true
          },
          "score" : {
            "type" : "number",
            "description" : "Composite signal quality score (0-100) based on multiple performance metrics",
            "readOnly" : true
          },
          "scoreBreakdown" : {
            "$ref" : "#/components/schemas/ScoreBreakdownDTO"
          },
          "symbolAnalytics" : {
            "type" : "array",
            "description" : "Detailed analytics per traded symbol",
            "readOnly" : true,
            "items" : {
              "$ref" : "#/components/schemas/SymbolAnalyticsDTO"
            }
          },
          "timeInDrawdownPercent" : {
            "type" : "number",
            "description" : "Percentage of time equity was below its previous peak, based on Data Collector samples (%)",
            "readOnly" : true
          },
          "totalCommissions" : {
            "type" : "number",
            "description" : "Total commissions paid across all trades in account currency (amount)",
            "readOnly" : true
          },
          "totalLotSize" : {
            "type" : "number",
            "description" : "Total lot size traded across all trades (lots)",
            "readOnly" : true
          },
          "totalNetProfit" : {
            "type" : "number",
            "description" : "Total net profit in account currency (amount)",
            "readOnly" : true
          },
          "totalSwap" : {
            "type" : "number",
            "description" : "Total swap across all trades in account currency",
            "readOnly" : true
          },
          "totalTrades" : {
            "type" : "integer",
            "description" : "Total number of closed trades in history window (count)",
            "format" : "int32",
            "readOnly" : true
          },
          "tradesByHoldingBucket" : {
            "type" : "object",
            "additionalProperties" : {
              "type" : "integer",
              "description" : "Trade count by holding-time bucket",
              "format" : "int32",
              "readOnly" : true
            },
            "description" : "Trade count by holding-time bucket",
            "readOnly" : true
          },
          "tradesPerDay" : {
            "type" : "object",
            "additionalProperties" : {
              "type" : "integer",
              "description" : "Trade count per day - key: YYYY-MM-DD format, value: number of trades (count)",
              "format" : "int32",
              "readOnly" : true
            },
            "description" : "Trade count per day - key: YYYY-MM-DD format, value: number of trades (count)",
            "readOnly" : true
          },
          "tradesPerHour" : {
            "type" : "object",
            "additionalProperties" : {
              "type" : "integer",
              "description" : "Trade count by hour of day (UTC)",
              "format" : "int32",
              "readOnly" : true
            },
            "description" : "Trade count by hour of day (UTC)",
            "readOnly" : true
          },
          "tradesPerSymbol" : {
            "type" : "object",
            "additionalProperties" : {
              "type" : "integer",
              "description" : "Trade count per symbol - key: symbol name (e.g. EURUSD, GBPUSD), value: number of trades (count)",
              "format" : "int32",
              "readOnly" : true
            },
            "description" : "Trade count per symbol - key: symbol name (e.g. EURUSD, GBPUSD), value: number of trades (count)",
            "readOnly" : true
          },
          "tradesPerWeekday" : {
            "type" : "object",
            "additionalProperties" : {
              "type" : "integer",
              "description" : "Trade count by weekday",
              "format" : "int32",
              "readOnly" : true
            },
            "description" : "Trade count by weekday",
            "readOnly" : true
          },
          "troughFloatingPnl" : {
            "type" : "number",
            "description" : "Maximum adverse floating PnL ever observed in granular Data Collector samples (amount, negative)",
            "readOnly" : true
          },
          "winRate" : {
            "type" : "number",
            "description" : "Win rate in percentage [0..100] (%)",
            "readOnly" : true,
            "example" : 62.5
          },
          "winningTrades" : {
            "type" : "integer",
            "description" : "Number of winning trades",
            "format" : "int32",
            "readOnly" : true
          },
          "worstDay" : {
            "$ref" : "#/components/schemas/PeriodPerformanceDTO"
          },
          "worstMonth" : {
            "$ref" : "#/components/schemas/PeriodPerformanceDTO"
          },
          "worstWeek" : {
            "$ref" : "#/components/schemas/PeriodPerformanceDTO"
          }
        },
        "description" : "Performance metrics"
      },
      "PeriodPerformanceDTO" : {
        "type" : "object",
        "properties" : {
          "label" : {
            "type" : "string",
            "description" : "Period label, for example 2026-04 or 2026-W14",
            "readOnly" : true
          },
          "netProfit" : {
            "type" : "number",
            "description" : "Net profit for the period",
            "readOnly" : true
          }
        },
        "description" : "Performance summary for a named period",
        "readOnly" : true
      },
      "PositionDTO" : {
        "type" : "object",
        "properties" : {
          "brokerTimeClose" : {
            "type" : "string",
            "description" : "Original time string from the broker",
            "readOnly" : true
          },
          "brokerTimeOpen" : {
            "type" : "string",
            "description" : "Original time string from the broker",
            "readOnly" : true
          },
          "closePrice" : {
            "type" : "number",
            "readOnly" : true
          },
          "closeTime" : {
            "type" : "string",
            "description" : "ISO 8601",
            "format" : "date-time",
            "readOnly" : true
          },
          "comment" : {
            "type" : "string",
            "readOnly" : true
          },
          "commission" : {
            "type" : "number",
            "readOnly" : true
          },
          "dealType" : {
            "type" : "string",
            "readOnly" : true,
            "enum" : [ "DealBuy", "DealSell", "Balance", "Credit", "Charge", "Correction", "Bonus", "Commission", "DailyCommission", "MonthlyCommission", "DailyAgentCommission", "MonthlyAgentCommission", "InterestRate", "CanceledBuy", "CanceledSell", "Dividend", "FrankedDividend", "Tax", "AgentCommission", "SoCompensation", "SoCreditCompensation" ]
          },
          "id" : {
            "type" : "string",
            "readOnly" : true
          },
          "magicNumber" : {
            "type" : "string",
            "description" : "Magic number carried by the position, as a string. Absent/null when no magic number was set on the order (a magic of 0 on the broker side is reported as absent rather than as the string \"0\").",
            "readOnly" : true
          },
          "netProfit" : {
            "type" : "number",
            "readOnly" : true
          },
          "openPrice" : {
            "type" : "number",
            "readOnly" : true
          },
          "openTime" : {
            "type" : "string",
            "description" : "ISO 8601",
            "format" : "date-time",
            "readOnly" : true
          },
          "orderType" : {
            "type" : "string",
            "readOnly" : true,
            "enum" : [ "Buy", "Sell", "BuyLimit", "SellLimit", "BuyStop", "SellStop" ]
          },
          "placedType" : {
            "type" : "string",
            "readOnly" : true,
            "enum" : [ "Manually", "Mobile", "Web", "ByExpert", "OnSL", "OnTP", "OnStopOut", "OnRollover", "OnVmargin", "OnSplit", "ByDealer", "Gateway", "Signal", "Settlement", "Transfer", "Sync", "ExternalService", "Migration" ]
          },
          "profit" : {
            "type" : "number",
            "readOnly" : true
          },
          "requestId" : {
            "type" : "string",
            "readOnly" : true
          },
          "state" : {
            "type" : "string",
            "readOnly" : true
          },
          "stopLoss" : {
            "type" : "number",
            "readOnly" : true
          },
          "swap" : {
            "type" : "number",
            "readOnly" : true
          },
          "symbol" : {
            "type" : "string",
            "readOnly" : true
          },
          "takeProfit" : {
            "type" : "number",
            "readOnly" : true
          },
          "volume" : {
            "type" : "number",
            "readOnly" : true
          }
        },
        "description" : "List of historical positions relevant to the account's performance as of the recorded date.",
        "readOnly" : true
      },
      "PositionRequestDTO" : {
        "required" : [ "openPrice", "orderType", "requestId", "stopLoss", "symbol", "takeProfit", "volume" ],
        "type" : "object",
        "properties" : {
          "comment" : {
            "maxLength" : 31,
            "minLength" : 0,
            "type" : "string",
            "description" : "Max 31 characters (broker limit). When opening a position via /rest/api/v1/accounts/{accountId}/positions, an 'API|YOUR_REQUEST_ID|' prefix (5-8 chars) is prepended, so the effective user comment is ~23 chars before truncation. For modify requests, the full 31 characters are available."
          },
          "magicNumber" : {
            "maxLength" : 19,
            "minLength" : 0,
            "type" : "string",
            "description" : "At the moment, only numbers as string are supported"
          },
          "openPrice" : {
            "type" : "number",
            "description" : "Used for pending orders (buy limit, stop limit, ...). For buy or sell you can enter 0.",
            "default" : 0
          },
          "orderType" : {
            "type" : "string",
            "enum" : [ "Buy", "Sell", "BuyLimit", "SellLimit", "BuyStop", "SellStop" ]
          },
          "pendingExpirySeconds" : {
            "type" : "integer",
            "description" : "Native pending order expiry, in seconds from now. Only applies to pending orders (buyLimit, sellLimit, buyStop, sellStop) on MT4/MT5. The broker cancels the order automatically if it has not been filled within this time. Ignored for market orders and unsupported account types. Note: enforcement is broker-dependent; some brokers require a minimum expiry (e.g. at least a few minutes) or reject order expiry entirely. 0 or omitted means good-till-cancelled (no expiry).",
            "format" : "int32",
            "default" : 0
          },
          "relativeTpSl" : {
            "type" : "boolean",
            "description" : "When true, stop loss and take profit values are interpreted as distance in points from the fill price. The position will be opened first, then automatically modified with the calculated absolute SL/TP prices. For cTrader accounts, the platform handles this natively. For all other account types (MT4, MT5, etc.), the SL/TP is set via a fire-and-forget modify order after the position is opened.",
            "default" : false
          },
          "requestId" : {
            "maximum" : 999,
            "type" : "integer",
            "description" : "A client request ID to avoid the request being executed multiple times due to network or client errors. The IDs start at 0 and increment up to 999, then begin again at 0.",
            "format" : "int64"
          },
          "stopLoss" : {
            "type" : "number",
            "description" : "A value of 0 means no stop loss",
            "default" : 0
          },
          "symbol" : {
            "maxLength" : 20,
            "minLength" : 0,
            "type" : "string"
          },
          "takeProfit" : {
            "type" : "number",
            "description" : "A value of 0 means no take profit",
            "default" : 0
          },
          "volume" : {
            "type" : "number",
            "description" : "In lots. The volume will be automatically adjusted according to the symbol data."
          }
        }
      },
      "ProfitTargetStatusDTO" : {
        "type" : "object",
        "properties" : {
          "balanceLastUpdate" : {
            "type" : "string",
            "format" : "date-time",
            "readOnly" : true
          },
          "profitTargetFeatureId" : {
            "type" : "string",
            "format" : "uuid",
            "readOnly" : true
          },
          "profitTargetIsHit" : {
            "type" : "boolean",
            "readOnly" : true
          },
          "referenceBalance" : {
            "type" : "number",
            "readOnly" : true
          }
        },
        "readOnly" : true
      },
      "ProjectDTO" : {
        "required" : [ "billingCity", "billingCompanyName", "billingCountry", "billingCountryIsoAlpha2", "billingIdentification", "billingName", "billingPostcode", "billingStreet", "currencyType", "dedicated", "name" ],
        "type" : "object",
        "properties" : {
          "b2b" : {
            "type" : "boolean",
            "readOnly" : true,
            "example" : false
          },
          "balance" : {
            "type" : "number",
            "readOnly" : true
          },
          "billingCity" : {
            "maxLength" : 255,
            "minLength" : 0,
            "type" : "string"
          },
          "billingCompanyName" : {
            "maxLength" : 255,
            "minLength" : 0,
            "type" : "string"
          },
          "billingCountry" : {
            "maxLength" : 255,
            "minLength" : 0,
            "type" : "string"
          },
          "billingCountryIsoAlpha2" : {
            "maxLength" : 255,
            "minLength" : 0,
            "type" : "string"
          },
          "billingIdentification" : {
            "maxLength" : 255,
            "minLength" : 0,
            "type" : "string"
          },
          "billingName" : {
            "maxLength" : 255,
            "minLength" : 0,
            "type" : "string"
          },
          "billingPostcode" : {
            "maxLength" : 255,
            "minLength" : 0,
            "type" : "string"
          },
          "billingRegion" : {
            "maxLength" : 255,
            "minLength" : 0,
            "type" : "string",
            "description" : "Billing region / state. Mandatory for the United Arab Emirates (billingCountryIsoAlpha2 = AE), where the emirate is required for the VAT calculation. Expected as ISO 3166-2 subdivision code without country prefix, e.g. DU for Dubai.",
            "example" : "DU"
          },
          "billingStreet" : {
            "maxLength" : 255,
            "minLength" : 0,
            "type" : "string"
          },
          "billingVatIdentification" : {
            "type" : "string",
            "description" : "Company VAT number (read-only).",
            "readOnly" : true
          },
          "blocked" : {
            "type" : "boolean",
            "readOnly" : true
          },
          "currencyType" : {
            "$ref" : "#/components/schemas/CurrencyTypeDTO"
          },
          "dedicated" : {
            "type" : "boolean",
            "description" : "You have to set it during resource creation, after that, it is only read-only. See pricing on our webpage for more information",
            "example" : false,
            "default" : false
          },
          "id" : {
            "type" : "string",
            "format" : "uuid",
            "readOnly" : true
          },
          "name" : {
            "maxLength" : 255,
            "minLength" : 0,
            "type" : "string"
          },
          "owner" : {
            "$ref" : "#/components/schemas/CustomerDTO"
          },
          "paymentMethod" : {
            "$ref" : "#/components/schemas/PaymentMethodDTO"
          }
        }
      },
      "ProxyDTO" : {
        "type" : "object",
        "properties" : {
          "id" : {
            "type" : "integer",
            "format" : "int32",
            "readOnly" : true
          },
          "ipAddress" : {
            "type" : "string",
            "readOnly" : true
          },
          "region" : {
            "$ref" : "#/components/schemas/ProxyRegionDTO"
          },
          "usedByAccounts" : {
            "type" : "array",
            "readOnly" : true,
            "items" : {
              "type" : "string",
              "format" : "uuid",
              "readOnly" : true
            }
          }
        },
        "description" : "Read-only. The system will reserve the proxy servers per region and list them in this field.",
        "readOnly" : true
      },
      "ProxyRegionDTO" : {
        "required" : [ "id" ],
        "type" : "object",
        "properties" : {
          "id" : {
            "type" : "integer",
            "format" : "int32"
          },
          "name" : {
            "type" : "string",
            "readOnly" : true
          }
        },
        "readOnly" : true
      },
      "RateOutlookDTO" : {
        "type" : "object",
        "properties" : {
          "centralBank" : {
            "type" : "string",
            "description" : "Name of the central bank",
            "example" : "European Central Bank"
          },
          "currencyCode" : {
            "type" : "string",
            "description" : "Currency the central bank issues",
            "example" : "EUR"
          },
          "currentRate" : {
            "type" : "number",
            "description" : "Policy rate in percent",
            "format" : "double",
            "example" : 2.15
          },
          "currentRateAsOf" : {
            "type" : "string",
            "description" : "When that rate was published",
            "format" : "date-time"
          },
          "expectedChange" : {
            "type" : "number",
            "description" : "Expected change in percentage points, negative means a cut",
            "format" : "double"
          },
          "nextEventId" : {
            "type" : "string",
            "description" : "Id of the next scheduled rate decision"
          },
          "nextEventTimeUtc" : {
            "type" : "string",
            "description" : "When the next decision is released",
            "format" : "date-time"
          },
          "nextEventTitle" : {
            "type" : "string",
            "description" : "Title of the next scheduled rate decision"
          },
          "nextForecast" : {
            "type" : "number",
            "description" : "Market forecast for the next decision, in percent",
            "format" : "double"
          },
          "previousRate" : {
            "type" : "number",
            "description" : "Policy rate before the last decision, in percent",
            "format" : "double",
            "example" : 2.4
          },
          "source" : {
            "type" : "string",
            "description" : "Where the current rate came from: ecb or calendar"
          }
        },
        "description" : "Current policy rate and the next scheduled decision for one currency"
      },
      "RecentActivityDTO" : {
        "type" : "object",
        "properties" : {
          "ownerEmail" : {
            "type" : "string",
            "description" : "Owner email"
          },
          "projectId" : {
            "type" : "string",
            "description" : "Project ID",
            "format" : "uuid"
          },
          "projectName" : {
            "type" : "string",
            "description" : "Project name"
          },
          "timestamp" : {
            "type" : "string",
            "description" : "Activity timestamp",
            "format" : "date-time"
          }
        },
        "description" : "Recent activity entry",
        "readOnly" : true
      },
      "RecentInvoiceDTO" : {
        "type" : "object",
        "properties" : {
          "amount" : {
            "type" : "number",
            "description" : "Amount"
          },
          "created" : {
            "type" : "string",
            "description" : "Creation date",
            "format" : "date-time"
          },
          "invoiceNumber" : {
            "type" : "string",
            "description" : "Invoice number"
          },
          "projectName" : {
            "type" : "string",
            "description" : "Project name"
          },
          "status" : {
            "type" : "string",
            "description" : "Status"
          }
        },
        "description" : "Recent invoice entry",
        "readOnly" : true
      },
      "RefundInvoiceRequestDTO" : {
        "type" : "object",
        "properties" : {
          "reason" : {
            "maxLength" : 200,
            "minLength" : 0,
            "type" : "string",
            "description" : "Optional free-text reason for the refund, stored in the admin log for audit purposes.",
            "example" : "Customer requested a refund within the trial period"
          }
        },
        "description" : "Request body for voiding or refunding an invoice by the white-label owner"
      },
      "RegionDTO" : {
        "required" : [ "id" ],
        "type" : "object",
        "properties" : {
          "id" : {
            "type" : "integer",
            "format" : "int32"
          },
          "name" : {
            "type" : "string",
            "readOnly" : true
          }
        },
        "description" : "Select allowed regions for the white-label solution. If empty or not specified, all regions are allowed."
      },
      "ReorderDashboardsRequestDTO" : {
        "required" : [ "dashboardIds" ],
        "type" : "object",
        "properties" : {
          "dashboardIds" : {
            "type" : "array",
            "description" : "Ordered list of dashboard IDs",
            "items" : {
              "type" : "string",
              "description" : "Ordered list of dashboard IDs",
              "format" : "uuid"
            }
          }
        },
        "description" : "Request to reorder dashboards"
      },
      "ReportPerformanceDTO" : {
        "type" : "object",
        "properties" : {
          "accounts" : {
            "type" : "array",
            "description" : "List of performance metrics for each account, as defined in AccountPerformanceDTO.",
            "readOnly" : true,
            "items" : {
              "$ref" : "#/components/schemas/AccountPerformanceDTO"
            }
          }
        },
        "description" : "DTO representing requested performance metrics for a list of accounts."
      },
      "ReportPerformanceParametersDTO" : {
        "required" : [ "id", "idType", "start", "stop" ],
        "type" : "object",
        "properties" : {
          "id" : {
            "type" : "array",
            "description" : "List of unique identifiers for the resources (e.g., account IDs, project IDs, or feature IDs) for which the performance report is requested.",
            "items" : {
              "type" : "string",
              "description" : "List of unique identifiers for the resources (e.g., account IDs, project IDs, or feature IDs) for which the performance report is requested.",
              "format" : "uuid"
            }
          },
          "idType" : {
            "type" : "string",
            "description" : "Type of resource identified by the IDs, indicating whether the report pertains to accounts, projects, or specific features.",
            "enum" : [ "ACCOUNT", "PROJECT", "FEATURE" ]
          },
          "start" : {
            "type" : "string",
            "description" : "Start date for the reporting period.",
            "format" : "date-time"
          },
          "stop" : {
            "type" : "string",
            "description" : "End date for the reporting period.",
            "format" : "date-time"
          }
        },
        "description" : "Parameters required for generating a performance report over a specified time period for one or more resources."
      },
      "RequestSymbolMappingsDTO" : {
        "required" : [ "symbols" ],
        "type" : "object",
        "properties" : {
          "loginServer" : {
            "type" : "string"
          },
          "symbols" : {
            "type" : "array",
            "items" : {
              "type" : "string"
            }
          }
        }
      },
      "RestEndpointMetadataDTO" : {
        "type" : "object",
        "properties" : {
          "method" : {
            "type" : "string",
            "description" : "HTTP method",
            "example" : "GET"
          },
          "path" : {
            "type" : "string",
            "description" : "Endpoint path pattern",
            "example" : "/rest/api/v1/projects/{projectId}/strategies"
          },
          "summary" : {
            "type" : "string",
            "description" : "Operation summary/description if available"
          }
        },
        "description" : "Represents a REST endpoint that can be allowed/blocked via API key access policy"
      },
      "RiskHeatCellDTO" : {
        "type" : "object",
        "properties" : {
          "currencyCode" : {
            "type" : "string"
          },
          "day" : {
            "type" : "string",
            "format" : "date"
          },
          "highImpact" : {
            "type" : "integer",
            "format" : "int32"
          },
          "mediumImpact" : {
            "type" : "integer",
            "format" : "int32"
          },
          "score" : {
            "type" : "integer",
            "description" : "Impact weighted event load, 0 to 100, normalised against the busiest cell in the range",
            "format" : "int32"
          },
          "topEventTitle" : {
            "type" : "string",
            "description" : "The heaviest release of that day, so the cell can name what makes it dangerous"
          }
        },
        "description" : "Only cells that carry at least one event are returned"
      },
      "RiskHeatmapDTO" : {
        "type" : "object",
        "properties" : {
          "cells" : {
            "type" : "array",
            "description" : "Only cells that carry at least one event are returned",
            "items" : {
              "$ref" : "#/components/schemas/RiskHeatCellDTO"
            }
          },
          "currencies" : {
            "type" : "array",
            "description" : "Busiest currency first",
            "items" : {
              "type" : "string",
              "description" : "Busiest currency first"
            }
          },
          "days" : {
            "type" : "array",
            "description" : "Ascending, one entry per day in the range",
            "items" : {
              "type" : "string",
              "description" : "Ascending, one entry per day in the range",
              "format" : "date"
            }
          },
          "fromUtc" : {
            "type" : "string",
            "format" : "date-time"
          },
          "toUtc" : {
            "type" : "string",
            "format" : "date-time"
          }
        }
      },
      "RiskLimitDTO" : {
        "required" : [ "riskLimit", "riskType" ],
        "type" : "object",
        "properties" : {
          "absoluteRiskLimit" : {
            "minimum" : 0.00,
            "exclusiveMinimum" : false,
            "type" : "number",
            "description" : "Enter an absolute risk limit in account currency. Set to 0 to deactivate.",
            "default" : 0
          },
          "accountId" : {
            "type" : "string",
            "description" : "You have to set it during resource creation, after that, it is only read-only",
            "format" : "uuid"
          },
          "active" : {
            "type" : "boolean",
            "default" : true
          },
          "closeAllOpenPositions" : {
            "type" : "boolean",
            "description" : "If set to 'true', all positions will be closed immediately when the primary risk limit is reached. If set to 'false', new trades will not be opened when the primary limit is reached, but the fallback limits become active as a secondary safety measure.",
            "default" : true
          },
          "copierId" : {
            "type" : "string",
            "description" : "You have to set it during resource creation, after that, it is only read-only",
            "format" : "uuid"
          },
          "fallbackAbsoluteRiskLimit" : {
            "minimum" : 0.00,
            "exclusiveMinimum" : false,
            "type" : "number",
            "description" : "Fallback absolute risk limit in account currency. Only applies when closeAllOpenPositions is false. When this limit is reached, all positions will be closed. Set to 0 to deactivate.",
            "default" : 0
          },
          "fallbackRelativeRiskLimit" : {
            "minimum" : 0.00,
            "exclusiveMinimum" : false,
            "type" : "number",
            "description" : "Fallback relative risk limit in account currency. Only applies when closeAllOpenPositions is false. When this limit is reached, all positions will be closed. Set to 0 to deactivate.",
            "default" : 0
          },
          "fallbackRiskLimit" : {
            "maximum" : 1.000,
            "exclusiveMaximum" : false,
            "minimum" : 0.000,
            "exclusiveMinimum" : false,
            "type" : "number",
            "description" : "Fallback risk limit (percentage). Only applies when closeAllOpenPositions is false. When this limit is reached, all positions will be closed. Set to 0 to deactivate.",
            "default" : 0
          },
          "fulfillSeconds" : {
            "type" : "integer",
            "description" : "If set to 5, it means that if the limit is reached and stays over the limit for 5 seconds, the risk limit will be activated; otherwise, the limit will remain deactivated",
            "format" : "int32",
            "default" : 60
          },
          "id" : {
            "type" : "string",
            "format" : "uuid",
            "readOnly" : true
          },
          "relativeRiskLimit" : {
            "minimum" : 0.00,
            "exclusiveMinimum" : false,
            "type" : "number",
            "description" : "Enter an relative risk limit in account currency. Set to 0 to deactivate.",
            "default" : 0
          },
          "resetTime" : {
            "type" : "string",
            "description" : "ISO 8601. Set the reset time for calculation (see riskType). Only used for 1-3 risk type. Only the time is considered, and the date is ignored.",
            "format" : "date-time",
            "default" : "2023-12-30T00:00:00Z"
          },
          "riskLimit" : {
            "maximum" : 1.000,
            "exclusiveMaximum" : false,
            "minimum" : 0.000,
            "exclusiveMinimum" : false,
            "type" : "number",
            "description" : "0.215 for 21.5% (set to 0 to deactivate)"
          },
          "riskType" : {
            "$ref" : "#/components/schemas/RiskTypeDTO"
          }
        }
      },
      "RiskLimitStatusDTO" : {
        "type" : "object",
        "properties" : {
          "balanceLastUpdate" : {
            "type" : "string",
            "format" : "date-time",
            "readOnly" : true
          },
          "limitIsHit" : {
            "type" : "boolean",
            "readOnly" : true
          },
          "referenceBalance" : {
            "type" : "number",
            "readOnly" : true
          },
          "riskLimitId" : {
            "type" : "string",
            "format" : "uuid",
            "readOnly" : true
          }
        },
        "readOnly" : true
      },
      "RiskTypeDTO" : {
        "required" : [ "id" ],
        "type" : "object",
        "properties" : {
          "id" : {
            "type" : "integer",
            "format" : "int32"
          },
          "name" : {
            "type" : "string",
            "readOnly" : true
          }
        },
        "description" : "    You have to set it during resource creation, after that, it is only read-only.\n    You have only to set the id, e.g. 4 for actual drawdown.\n    1: Daily, 2: Weekly, 3: Monthly, 4: Actual, 5: Equity-equity daily, 6: Equity-equity weekly, 7: Equity-equity monthly, 8: Smart reference daily,\n    9: Smart reference weekly, 10: Smart reference monthly.\n\n    When you set a daily risk limit of 0.5 (50%), it means that if the ratio of the balance\n    at a specific timepoint (see resetTime) to equity reaches 50%, the copy trading will be\n    paused, and if specified, all trades will be closed (see closeAllOpenPositions).\n\n    The limit reference type depends on the selected risk type:\n    • Balance-based limits use the balance as reference.\n    • Equity-based limits use the equity as reference.\n    • Smart limits use the greater of balance and equity as reference.\n\n    Example: {id: 1}\n"
      },
      "ScaleTypeDTO" : {
        "required" : [ "id" ],
        "type" : "object",
        "properties" : {
          "id" : {
            "type" : "integer",
            "format" : "int32"
          },
          "name" : {
            "type" : "string",
            "readOnly" : true
          }
        },
        "description" : "You have only to set the id e.g 1 for scale by balance. 1: Balance 2: Equity 3: Fixed lot size 4: No scaling. Example: {id:1}"
      },
      "ScoreBreakdownDTO" : {
        "type" : "object",
        "properties" : {
          "accountBalanceScore" : {
            "type" : "number",
            "description" : "Account balance score (0-7 points, Live only)",
            "example" : 7.0
          },
          "accountTypeScore" : {
            "type" : "number",
            "description" : "Account type score (0-8 points)",
            "example" : 8.0
          },
          "consistencyScore" : {
            "type" : "number",
            "description" : "Consistency score (0-6 points)",
            "example" : 5.0
          },
          "diversificationScore" : {
            "type" : "number",
            "description" : "Portfolio diversification score (0-8 points)",
            "example" : 6.5
          },
          "expectancyScore" : {
            "type" : "number",
            "description" : "Expectancy score (0-5 points)",
            "example" : 4.0
          },
          "isLiveAccount" : {
            "type" : "boolean",
            "description" : "Whether this is a live account",
            "example" : true
          },
          "martingalePenalty" : {
            "type" : "number",
            "description" : "Martingale penalty (0 to -6 points)",
            "example" : -3.0
          },
          "maxDrawdownScore" : {
            "type" : "number",
            "description" : "Max drawdown score (0-12 points)",
            "example" : 9.5
          },
          "monthsActiveScore" : {
            "type" : "number",
            "description" : "Months active score (0-2 points)",
            "example" : 1.8
          },
          "overtradingPenalty" : {
            "type" : "number",
            "description" : "Overtrading penalty (0 to -5 points)",
            "example" : -2.5
          },
          "profitFactorScore" : {
            "type" : "number",
            "description" : "Profit factor score (0-12 points)",
            "example" : 10.0
          },
          "recoveryFactorScore" : {
            "type" : "number",
            "description" : "Recovery factor score (0-10 points)",
            "example" : 8.0
          },
          "riskRewardScore" : {
            "type" : "number",
            "description" : "Risk/reward ratio score (0-7 points)",
            "example" : 5.5
          },
          "totalTradesScore" : {
            "type" : "number",
            "description" : "Total trades score (0-4 points)",
            "example" : 3.5
          },
          "uniqueAssetClasses" : {
            "type" : "integer",
            "description" : "Number of unique asset classes traded",
            "format" : "int32",
            "example" : 3
          },
          "uniqueInstruments" : {
            "type" : "integer",
            "description" : "Number of unique instruments traded",
            "format" : "int32",
            "example" : 12
          },
          "winRateScore" : {
            "type" : "number",
            "description" : "Win rate score (0-8 points)",
            "example" : 6.0
          }
        },
        "description" : "Detailed breakdown of signal score calculation showing contribution of each component",
        "readOnly" : true
      },
      "SignalFollowerCostDTO" : {
        "type" : "object",
        "properties" : {
          "coverFollowerCosts" : {
            "type" : "boolean",
            "description" : "Whether this signal provider currently covers the costs of its followers. If false, no costs are reported."
          },
          "currency" : {
            "type" : "string",
            "description" : "Currency of all monetary amounts"
          },
          "months" : {
            "type" : "array",
            "description" : "Per-month breakdown, oldest month first",
            "items" : {
              "$ref" : "#/components/schemas/MonthlyFollowerCostDTO"
            }
          },
          "signalProviderId" : {
            "type" : "string",
            "description" : "UUID of the signal provider feature",
            "format" : "uuid"
          },
          "signalProviderName" : {
            "type" : "string",
            "description" : "Display name of the signal provider"
          },
          "totalCost" : {
            "type" : "number",
            "description" : "Total covered follower costs across all reported months"
          }
        },
        "description" : "Follower costs covered by a signal provider"
      },
      "SignalProviderEarningsDTO" : {
        "type" : "object",
        "properties" : {
          "billingModel" : {
            "type" : "string",
            "description" : "Billing model: MONTHLY_PROFIT or HIGH_WATERMARK"
          },
          "currency" : {
            "type" : "string",
            "description" : "Currency of all monetary amounts"
          },
          "monthlyBreakdown" : {
            "type" : "array",
            "description" : "Per-month earnings breakdown with individual follower charge details",
            "items" : {
              "$ref" : "#/components/schemas/MonthlyEarningsDTO"
            }
          },
          "monthlySubscriptionFee" : {
            "type" : "number",
            "description" : "Configured monthly subscription fee charged to each follower"
          },
          "profitSharingFee" : {
            "type" : "number",
            "description" : "Configured profit sharing percentage charged to each follower"
          },
          "signalProviderId" : {
            "type" : "string",
            "description" : "UUID of the signal provider feature",
            "format" : "uuid"
          },
          "signalProviderName" : {
            "type" : "string",
            "description" : "Display name of the signal provider"
          },
          "summary" : {
            "$ref" : "#/components/schemas/EarningsSummaryDTO"
          }
        },
        "description" : "Signal provider earnings breakdown"
      },
      "StrategyDTO" : {
        "required" : [ "active", "key", "name", "projectId" ],
        "type" : "object",
        "properties" : {
          "active" : {
            "type" : "boolean"
          },
          "id" : {
            "type" : "string",
            "format" : "uuid",
            "readOnly" : true
          },
          "key" : {
            "type" : "integer",
            "description" : "You can define a positive number as key. This key will be saved in the \"magic number\" field for each trade",
            "format" : "int32"
          },
          "name" : {
            "maxLength" : 255,
            "minLength" : 0,
            "type" : "string"
          },
          "projectId" : {
            "type" : "string",
            "format" : "uuid"
          }
        }
      },
      "SurpriseIndexDTO" : {
        "type" : "object",
        "properties" : {
          "currencies" : {
            "type" : "array",
            "description" : "Strongest currency first",
            "items" : {
              "$ref" : "#/components/schemas/SurpriseIndexEntryDTO"
            }
          },
          "fromUtc" : {
            "type" : "string",
            "format" : "date-time"
          },
          "toUtc" : {
            "type" : "string",
            "format" : "date-time"
          }
        }
      },
      "SurpriseIndexEntryDTO" : {
        "type" : "object",
        "properties" : {
          "averageSigma" : {
            "type" : "number",
            "description" : "Mean directional sigma. Positive means the data has been beating expectations.",
            "format" : "double"
          },
          "beats" : {
            "type" : "integer",
            "format" : "int32"
          },
          "currencyCode" : {
            "type" : "string"
          },
          "misses" : {
            "type" : "integer",
            "format" : "int32"
          },
          "samples" : {
            "type" : "integer",
            "description" : "Releases that carried a usable sigma in the window",
            "format" : "int32"
          }
        },
        "description" : "Strongest currency first"
      },
      "SymbolAnalyticsDTO" : {
        "type" : "object",
        "properties" : {
          "avgProfitPerTrade" : {
            "type" : "number",
            "description" : "Average profit per trade for the symbol",
            "readOnly" : true
          },
          "netProfit" : {
            "type" : "number",
            "description" : "Net profit for the symbol",
            "readOnly" : true
          },
          "symbol" : {
            "type" : "string",
            "description" : "Symbol name",
            "readOnly" : true
          },
          "trades" : {
            "type" : "integer",
            "description" : "Trade count for the symbol",
            "format" : "int32",
            "readOnly" : true
          },
          "winRate" : {
            "type" : "number",
            "description" : "Win rate for the symbol (%)",
            "readOnly" : true
          }
        },
        "description" : "Analytics for a single traded symbol",
        "readOnly" : true
      },
      "SymbolCurrencyMappingDTO" : {
        "type" : "object",
        "properties" : {
          "currencies" : {
            "type" : "array",
            "description" : "Calendar currency codes this pattern resolves to",
            "example" : [ "USD" ],
            "items" : {
              "type" : "string",
              "description" : "Calendar currency codes this pattern resolves to",
              "example" : "[\"USD\"]"
            }
          },
          "pattern" : {
            "type" : "string",
            "description" : "Symbol pattern, '*' matches any sequence of characters",
            "example" : "XAU*"
          }
        },
        "description" : "Maps a symbol pattern to the calendar currencies that affect it. Evaluated top to bottom, first match wins, and the automatic resolution from the broker metadata is the implicit last entry."
      },
      "SymbolDTO" : {
        "type" : "object",
        "properties" : {
          "baseCurrency" : {
            "type" : "string"
          },
          "digits" : {
            "type" : "integer",
            "format" : "int32"
          },
          "disabled" : {
            "type" : "boolean"
          },
          "lotSize" : {
            "type" : "integer",
            "format" : "int32"
          },
          "maximalVolume" : {
            "type" : "number",
            "format" : "double"
          },
          "minimalVolume" : {
            "type" : "number",
            "format" : "double"
          },
          "name" : {
            "type" : "string"
          },
          "points" : {
            "type" : "number",
            "format" : "double"
          },
          "quoteCurrency" : {
            "type" : "string"
          },
          "stepVolume" : {
            "type" : "number",
            "format" : "double"
          },
          "tradeType" : {
            "type" : "string",
            "enum" : [ "REQUEST", "INSTANT", "MARKET", "ECHANGE" ]
          }
        }
      },
      "SymbolMappingDTO" : {
        "required" : [ "brokerFrom", "brokerTo", "from", "priority", "to" ],
        "type" : "object",
        "properties" : {
          "brokerFrom" : {
            "maxLength" : 255,
            "minLength" : 0,
            "type" : "string",
            "description" : "This symbol mapping is only applied if the trade comes from a specific broker, for example, 'ICMarkets.*'. For all brokers, you can enter '.*' (this is a regex)"
          },
          "brokerTo" : {
            "maxLength" : 255,
            "minLength" : 0,
            "type" : "string",
            "description" : "This symbol mapping is only applied if the trade is copied to a specific broker, for example, 'ICMarkets.*'. For all brokers, you can enter '.*' (this is a regex)"
          },
          "brokerToSuggestion" : {
            "type" : "array",
            "description" : "This is read-only. The system attempts to automatically map symbols, but if there are multiple findings, they will be listed here. (This member is used only for the endpoint symbolMappings/current)",
            "readOnly" : true,
            "items" : {
              "type" : "string",
              "description" : "This is read-only. The system attempts to automatically map symbols, but if there are multiple findings, they will be listed here. (This member is used only for the endpoint symbolMappings/current)",
              "readOnly" : true
            }
          },
          "from" : {
            "maxLength" : 255,
            "minLength" : 0,
            "type" : "string",
            "description" : "Enter a symbol e.g. GBPUSD (is not a regex)"
          },
          "id" : {
            "type" : "integer",
            "format" : "int64",
            "readOnly" : true
          },
          "priority" : {
            "type" : "integer",
            "description" : "The priority is ascending, which means that 0 has a higher priority than 1. Priority is always positive",
            "format" : "int32"
          },
          "projectId" : {
            "type" : "string",
            "format" : "uuid",
            "readOnly" : true
          },
          "to" : {
            "maxLength" : 255,
            "minLength" : 0,
            "type" : "string",
            "description" : "Enter a symbol e.g. GBPEUR (is not a regex)"
          }
        }
      },
      "TaxBreakdownDTO" : {
        "type" : "object",
        "properties" : {
          "amount" : {
            "type" : "integer",
            "format" : "int64"
          },
          "inclusive" : {
            "type" : "boolean"
          },
          "taxRateDetails" : {
            "$ref" : "#/components/schemas/TaxRateDetailsDTO"
          },
          "taxabilityReason" : {
            "type" : "string"
          },
          "taxableAmount" : {
            "type" : "integer",
            "format" : "int64"
          },
          "vatNumber" : {
            "type" : "string"
          }
        }
      },
      "TaxDTO" : {
        "type" : "object",
        "properties" : {
          "breakdown" : {
            "type" : "array",
            "items" : {
              "$ref" : "#/components/schemas/TaxBreakdownDTO"
            }
          }
        },
        "readOnly" : true
      },
      "TaxRateDetailsDTO" : {
        "type" : "object",
        "properties" : {
          "country" : {
            "type" : "string"
          },
          "flatAmount" : {
            "type" : "integer",
            "format" : "int64"
          },
          "percentageDecimal" : {
            "type" : "string"
          },
          "rateType" : {
            "type" : "string"
          },
          "state" : {
            "type" : "string"
          },
          "taxType" : {
            "type" : "string"
          }
        }
      },
      "TelegramChatDTO" : {
        "type" : "object",
        "properties" : {
          "chatId" : {
            "type" : "integer",
            "description" : "Telegram chat ID",
            "format" : "int64"
          },
          "chatType" : {
            "type" : "string",
            "description" : "Chat type (private, group, supergroup, channel)"
          },
          "forumTopicId" : {
            "type" : "integer",
            "description" : "Forum topic ID within the chat. Null means the whole chat (all topics). Forum groups are listed flat: the group itself plus one entry per topic.",
            "format" : "int32"
          },
          "memberCount" : {
            "type" : "integer",
            "description" : "Number of members (for groups/channels)",
            "format" : "int32"
          },
          "title" : {
            "type" : "string",
            "description" : "Chat title/name. For a forum topic this is \"Group -> Topic\""
          },
          "username" : {
            "type" : "string",
            "description" : "Username if available (without @)"
          }
        },
        "description" : "Telegram chat information",
        "readOnly" : true
      },
      "TelegramNotificationDTO" : {
        "required" : [ "logLevel", "username" ],
        "type" : "object",
        "properties" : {
          "accountIds" : {
            "type" : "array",
            "description" : "Only the account IDs listed here will receive notifications",
            "items" : {
              "type" : "string",
              "description" : "Only the account IDs listed here will receive notifications",
              "format" : "uuid"
            }
          },
          "aliasMapping" : {
            "type" : "object",
            "additionalProperties" : {
              "type" : "string",
              "readOnly" : true
            },
            "readOnly" : true
          },
          "logLevel" : {
            "$ref" : "#/components/schemas/LogTypeDTO"
          },
          "useAlias" : {
            "type" : "boolean",
            "description" : "Use alias instead of UUID for identification"
          },
          "username" : {
            "type" : "string",
            "description" : "Enter the Telegram username (e.g. @john98734)"
          }
        },
        "description" : "List of telegram notifications"
      },
      "TradingViewWebhookResponseDTO" : {
        "type" : "object",
        "properties" : {
          "attemptCount" : {
            "type" : "integer",
            "description" : "Number of processing attempts (for queued requests)",
            "format" : "int32",
            "example" : 1
          },
          "cached" : {
            "type" : "boolean",
            "description" : "Whether this is a cached response from idempotency",
            "example" : false
          },
          "closedPositions" : {
            "type" : "array",
            "description" : "List of closed positions (for close operations)",
            "items" : {
              "$ref" : "#/components/schemas/ClosedPositionInfo"
            }
          },
          "code" : {
            "type" : "string",
            "description" : "Error code for failed requests",
            "example" : "AMBIGUOUS_MATCH"
          },
          "data" : {
            "type" : "object",
            "additionalProperties" : {
              "type" : "object",
              "description" : "Additional data returned with the response"
            },
            "description" : "Additional data returned with the response"
          },
          "hint" : {
            "type" : "string",
            "description" : "Hint for resolving errors",
            "example" : "Add 'force: true' to proceed or use more specific matching criteria"
          },
          "matchCount" : {
            "type" : "integer",
            "description" : "Number of positions matched (for close/modify operations)",
            "format" : "int32",
            "example" : 3
          },
          "message" : {
            "type" : "string",
            "description" : "Human-readable message describing the result",
            "example" : "Position opened successfully"
          },
          "originalRequestId" : {
            "type" : "string",
            "description" : "Original request ID if this is a cached response",
            "example" : "req_xyz789"
          },
          "requestId" : {
            "type" : "string",
            "description" : "Unique request ID for tracking and debugging",
            "example" : "req_abc123def456"
          },
          "status" : {
            "type" : "string",
            "description" : "Processing status (for queued requests)",
            "example" : "PROCESSING"
          },
          "success" : {
            "type" : "boolean",
            "description" : "Whether the request was successful",
            "example" : true
          },
          "timestamp" : {
            "type" : "string",
            "description" : "Response timestamp",
            "format" : "date-time"
          }
        },
        "description" : "Response from TradingView webhook endpoint"
      },
      "TradingWindowDTO" : {
        "required" : [ "endTime", "startTime" ],
        "type" : "object",
        "properties" : {
          "activeDays" : {
            "type" : "array",
            "description" : "Specific days when this trading window is active, represented as integers (e.g., 1 for Monday, 7 for Sunday).",
            "example" : [ 1, 2, 3, 4, 5 ],
            "items" : {
              "type" : "integer",
              "description" : "Specific days when this trading window is active, represented as integers (e.g., 1 for Monday, 7 for Sunday).",
              "format" : "int32"
            }
          },
          "endTime" : {
            "type" : "string",
            "description" : "End time of the trading window. Note: The date component is ignored.",
            "format" : "date-time",
            "example" : "2025-01-01T16:00:00Z"
          },
          "startTime" : {
            "type" : "string",
            "description" : "Start time of the trading window. Note: The date component is ignored.",
            "format" : "date-time",
            "example" : "2025-01-01T08:00:00Z"
          }
        },
        "description" : "DTO for defining a single trading window (copier/account) (PRO)"
      },
      "TransactionDTO" : {
        "required" : [ "amount", "currencyType", "projectId", "reference", "remark" ],
        "type" : "object",
        "properties" : {
          "amount" : {
            "type" : "number"
          },
          "currencyType" : {
            "$ref" : "#/components/schemas/CurrencyTypeDTO"
          },
          "date" : {
            "type" : "string",
            "description" : "ISO 8601",
            "format" : "date-time",
            "readOnly" : true
          },
          "id" : {
            "type" : "integer",
            "format" : "int32",
            "readOnly" : true
          },
          "projectId" : {
            "type" : "string",
            "format" : "uuid"
          },
          "reference" : {
            "type" : "string"
          },
          "remark" : {
            "type" : "string"
          }
        }
      },
      "UserDashboardConfigDTO" : {
        "required" : [ "name" ],
        "type" : "object",
        "properties" : {
          "createdAt" : {
            "type" : "string",
            "description" : "Creation timestamp",
            "format" : "date-time",
            "readOnly" : true,
            "example" : "2026-01-15T10:30:00Z"
          },
          "description" : {
            "maxLength" : 500,
            "minLength" : 0,
            "type" : "string",
            "description" : "Optional description",
            "example" : "My primary trading dashboard"
          },
          "id" : {
            "type" : "string",
            "description" : "Unique identifier for the dashboard",
            "format" : "uuid",
            "readOnly" : true,
            "example" : "550e8400-e29b-41d4-a716-446655440000"
          },
          "isDefault" : {
            "type" : "boolean",
            "description" : "Whether this is the default dashboard",
            "example" : true
          },
          "modifiedAt" : {
            "type" : "string",
            "description" : "Last modification timestamp",
            "format" : "date-time",
            "readOnly" : true,
            "example" : "2026-01-20T14:25:00Z"
          },
          "name" : {
            "maxLength" : 100,
            "minLength" : 1,
            "type" : "string",
            "description" : "Dashboard name",
            "example" : "Main Dashboard"
          },
          "projectId" : {
            "type" : "string",
            "description" : "Project ID this dashboard belongs to",
            "format" : "uuid",
            "readOnly" : true,
            "example" : "123e4567-e89b-12d3-a456-426614174000"
          },
          "sortOrder" : {
            "type" : "integer",
            "description" : "Display order in dashboard list",
            "format" : "int32",
            "example" : 0
          },
          "widgets" : {
            "type" : "array",
            "description" : "List of widgets in this dashboard",
            "items" : {
              "$ref" : "#/components/schemas/WidgetConfigDTO"
            }
          }
        },
        "description" : "Project dashboard configuration"
      },
      "WalletDTO" : {
        "type" : "object",
        "properties" : {
          "asset" : {
            "type" : "string",
            "readOnly" : true
          },
          "balance" : {
            "type" : "number",
            "readOnly" : true
          }
        },
        "readOnly" : true
      },
      "WhiteLabelDashboardDTO" : {
        "type" : "object",
        "properties" : {
          "currency" : {
            "type" : "string",
            "description" : "Currency used for all financial calculations",
            "readOnly" : true
          },
          "isTestStripeKey" : {
            "type" : "boolean",
            "description" : "True when the white-label is configured with an sk_test_ Stripe key. Read-only mirror used to drive frontend warnings.",
            "readOnly" : true
          },
          "manualCollection" : {
            "type" : "boolean",
            "description" : "True when the white-label has opted in to per-customer manual collection (mirrors FeatureWhiteLabelDTO.manualCollection)",
            "readOnly" : true
          },
          "projects" : {
            "type" : "array",
            "description" : "Detailed list of all projects linked to this WhiteLabel",
            "readOnly" : true,
            "items" : {
              "$ref" : "#/components/schemas/WhiteLabelProjectSummaryDTO"
            }
          },
          "recentInvoices" : {
            "type" : "array",
            "description" : "Recent invoices (last 10)",
            "readOnly" : true,
            "items" : {
              "$ref" : "#/components/schemas/RecentInvoiceDTO"
            }
          },
          "recentProjects" : {
            "type" : "array",
            "description" : "Recently created projects (last 10)",
            "readOnly" : true,
            "items" : {
              "$ref" : "#/components/schemas/RecentActivityDTO"
            }
          },
          "totalAccounts" : {
            "type" : "integer",
            "description" : "Total number of accounts across all projects",
            "format" : "int32",
            "readOnly" : true
          },
          "totalActiveAccounts" : {
            "type" : "integer",
            "description" : "Total number of active accounts",
            "format" : "int32",
            "readOnly" : true
          },
          "totalCustomers" : {
            "type" : "integer",
            "description" : "Total number of unique customers across all projects",
            "format" : "int32",
            "readOnly" : true
          },
          "totalInvoices" : {
            "type" : "integer",
            "description" : "Total number of invoices across all projects",
            "format" : "int32",
            "readOnly" : true
          },
          "totalManualOutstanding" : {
            "type" : "number",
            "description" : "Sum of OPEN invoice amounts across all customers that are eligible for manual collection. Zero when manualCollection=false.",
            "readOnly" : true
          },
          "totalOutstanding" : {
            "type" : "number",
            "description" : "Total outstanding amount from unpaid invoices",
            "readOnly" : true
          },
          "totalPaidInvoices" : {
            "type" : "integer",
            "description" : "Total number of paid invoices",
            "format" : "int32",
            "readOnly" : true
          },
          "totalProjects" : {
            "type" : "integer",
            "description" : "Total number of projects linked to this WhiteLabel",
            "format" : "int32",
            "readOnly" : true
          },
          "totalRevenue" : {
            "type" : "number",
            "description" : "Total revenue from all paid invoices in the WhiteLabel currency",
            "readOnly" : true
          },
          "totalUnpaidInvoices" : {
            "type" : "integer",
            "description" : "Total number of unpaid invoices",
            "format" : "int32",
            "readOnly" : true
          }
        },
        "description" : "Comprehensive dashboard for WhiteLabel owners showing all linked projects, customers, accounts and invoices"
      },
      "WhiteLabelProjectSummaryDTO" : {
        "type" : "object",
        "properties" : {
          "accountCount" : {
            "type" : "integer",
            "description" : "Number of accounts in this project",
            "format" : "int32"
          },
          "activeAccountCount" : {
            "type" : "integer",
            "description" : "Number of active accounts",
            "format" : "int32"
          },
          "balance" : {
            "type" : "number",
            "description" : "Current project balance"
          },
          "blocked" : {
            "type" : "boolean",
            "description" : "Whether the project is blocked"
          },
          "created" : {
            "type" : "string",
            "description" : "Project creation date",
            "format" : "date-time",
            "example" : "2024-01-15T10:30:00Z"
          },
          "customerCount" : {
            "type" : "integer",
            "description" : "Number of customers in this project",
            "format" : "int32"
          },
          "customers" : {
            "type" : "array",
            "description" : "List of customers in this project",
            "items" : {
              "$ref" : "#/components/schemas/CustomerSummaryDTO"
            }
          },
          "dedicated" : {
            "type" : "boolean",
            "description" : "Whether this is a dedicated project"
          },
          "invoiceCount" : {
            "type" : "integer",
            "description" : "Number of invoices for this project",
            "format" : "int32"
          },
          "invoices" : {
            "type" : "array",
            "description" : "List of invoices for this project",
            "items" : {
              "$ref" : "#/components/schemas/InvoiceSummaryDTO"
            }
          },
          "outstandingAmount" : {
            "type" : "number",
            "description" : "Outstanding amount for this project"
          },
          "ownerEmail" : {
            "type" : "string",
            "description" : "Project owner email"
          },
          "projectId" : {
            "type" : "string",
            "description" : "Project unique identifier",
            "format" : "uuid"
          },
          "projectName" : {
            "type" : "string",
            "description" : "Project name"
          },
          "totalRevenue" : {
            "type" : "number",
            "description" : "Total revenue from this project"
          }
        },
        "description" : "Detailed information about a project linked to the WhiteLabel",
        "readOnly" : true
      },
      "WidgetConfigDTO" : {
        "required" : [ "gridsterItem", "type" ],
        "type" : "object",
        "properties" : {
          "config" : {
            "$ref" : "#/components/schemas/JsonNode"
          },
          "gridsterItem" : {
            "$ref" : "#/components/schemas/GridsterItemDTO"
          },
          "id" : {
            "type" : "string",
            "description" : "Unique identifier for the widget",
            "example" : "widget-001"
          },
          "title" : {
            "maxLength" : 100,
            "minLength" : 0,
            "type" : "string",
            "description" : "Widget title",
            "example" : "Account Status"
          },
          "type" : {
            "type" : "string",
            "description" : "Widget type",
            "enum" : [ "ACCOUNT_STATUS", "REAL_TIME_PNL", "ACCOUNT", "TERMINAL", "OPEN_INVOICES", "PROJECT_BALANCE", "FINANCIAL_OVERVIEW", "LOGS", "AUDIT_LOGS", "NOTES", "DIVIDER", "CLOCK", "WEATHER" ]
          }
        },
        "description" : "Widget configuration within a dashboard"
      },
      "WisePayoutDetailsDTO" : {
        "required" : [ "email" ],
        "type" : "object",
        "properties" : {
          "email" : {
            "type" : "string",
            "description" : "Wise email address"
          }
        },
        "description" : "Wise payout details"
      }
    },
    "securitySchemes" : {
      "ApiKeyAuth" : {
        "in" : "header",
        "name" : "X-API-KEY",
        "type" : "apiKey"
      }
    }
  }
}