{
  "openapi": "3.1.0",
  "info": {
    "title": "WakeTrades API",
    "version": "1.0.0",
    "summary": "Non-custodial copy trading on Hyperliquid, usable end to end by an AI agent with its own wallet.",
    "description": "Flow: deposit USDC on Hyperliquid → POST /session/nonce + sign (EIP-191) → POST /session/verify → GET /levels (recommendedLevel for your balance) → PUT /settings {level} → GET /leaders/suggested (one trader of our Monthly Report for that level, or your own choice; check each one's live positions at liveCheck) → PUT /settings {leaders} → PUT /webhook → POST /agent → sign approveAgent (EIP-712; hyperliquidChain from POST /agent, signatureChainId = domain chainId) → POST /agent/approve → POST /agent/verify {tosAccepted:true} → 14-day free trial → POST /account/unified {} (Unified Account, no signature) → optional PUT /order-mode {mode: market} (default limit) → GET /me: copiesOnHold.held false → GET /pay/prepare → sign typedData (usdSend or sendAsset, EIP-712) → POST /pay. Unified Account rule: at prudent, equilibre and risque, new copies open only on a Hyperliquid Unified Account with no position opened outside WakeTrades (otherwise each new trade is skipped with skip code not_unified and an account_blocked event is sent at most once a day); at advanced, a standard account copies except the xyz markets (stocks, indices, commodities), which always need a Unified Account. An account needs a minimum balance to copy, because Hyperliquid has a minimum order size: 1,100 USDC at prudent, 550 at equilibre, 300 at risque; copies under the minimum open at 11 USDC. Funds stay on the agent's Hyperliquid account; the trading key can never withdraw. Not available to Restricted Persons (US, CA, GB, CN, UA, VE and sanctioned countries; see the Terms): calling the API confirms you are not one. No location filter today, but write requests from restricted locations may get 451 geo_blocked at any time, based on the request's IP address. Every error answer is { error, message, fix, docs } (fix: what to do next; docs: the page to read). Start with GET /hello. Writes that move money or change the account accept an Idempotency-Key header; PUT /settings and POST /pay accept dryRun. Guides: https://waketrades.com/docs/api/",
    "termsOfService": "https://waketrades.com/terms"
  },
  "externalDocs": {
    "description": "WakeTrades for AI agents",
    "url": "https://waketrades.com/docs/api/"
  },
  "servers": [
    {
      "url": "https://waketrades.com/api/v1"
    }
  ],
  "components": {
    "securitySchemes": {
      "session": {
        "type": "http",
        "scheme": "bearer",
        "description": "Session token from POST /session/verify. From a script or agent (no Origin header): valid until your plan or free trial ends, 6 months at most, 7 days before the trial starts; from the website: 7 days. POST /session/revoke-all signs out every session."
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "required": [
          "error",
          "message",
          "fix",
          "docs"
        ],
        "properties": {
          "error": {
            "type": "string",
            "description": "Stable code (snake_case)."
          },
          "message": {
            "type": "string"
          },
          "fix": {
            "type": "string",
            "description": "What to do next, in one sentence."
          },
          "docs": {
            "type": "string",
            "format": "uri",
            "description": "The documentation section to read for this error."
          },
          "detail": {
            "type": "string"
          }
        }
      },
      "Signature": {
        "type": "object",
        "required": [
          "r",
          "s",
          "v"
        ],
        "properties": {
          "r": {
            "type": "string"
          },
          "s": {
            "type": "string"
          },
          "v": {
            "type": "integer",
            "enum": [
              27,
              28
            ]
          }
        }
      },
      "ApproveAgentAction": {
        "type": "object",
        "required": [
          "type",
          "hyperliquidChain",
          "signatureChainId",
          "agentAddress",
          "agentName",
          "nonce"
        ],
        "properties": {
          "type": {
            "const": "approveAgent"
          },
          "hyperliquidChain": {
            "enum": [
              "Mainnet",
              "Testnet"
            ]
          },
          "signatureChainId": {
            "type": "string",
            "examples": [
              "0xa4b1"
            ]
          },
          "agentAddress": {
            "type": "string",
            "pattern": "^0x[0-9a-fA-F]{40}$"
          },
          "agentName": {
            "type": "string",
            "examples": [
              "WakeTrades valid_until 1806000000000"
            ]
          },
          "nonce": {
            "type": "integer",
            "description": "Now, in ms (less than 10 minutes old)."
          }
        }
      },
      "UsdSendAction": {
        "type": "object",
        "required": [
          "type",
          "hyperliquidChain",
          "signatureChainId",
          "destination",
          "amount",
          "time"
        ],
        "properties": {
          "type": {
            "const": "usdSend"
          },
          "hyperliquidChain": {
            "enum": [
              "Mainnet",
              "Testnet"
            ]
          },
          "signatureChainId": {
            "type": "string",
            "examples": [
              "0xa4b1"
            ]
          },
          "destination": {
            "type": "string",
            "pattern": "^0x[0-9a-fA-F]{40}$"
          },
          "amount": {
            "type": "string",
            "examples": [
              "15"
            ]
          },
          "time": {
            "type": "integer"
          }
        }
      },
      "SendAssetAction": {
        "type": "object",
        "required": [
          "type",
          "hyperliquidChain",
          "signatureChainId",
          "destination",
          "sourceDex",
          "destinationDex",
          "token",
          "amount",
          "fromSubAccount",
          "nonce"
        ],
        "description": "Payment from spot USDC (unified account), returned by GET /pay/prepare when perps don't cover the price.",
        "properties": {
          "type": {
            "const": "sendAsset"
          },
          "hyperliquidChain": {
            "enum": [
              "Mainnet",
              "Testnet"
            ]
          },
          "signatureChainId": {
            "type": "string",
            "examples": [
              "0xa4b1"
            ]
          },
          "destination": {
            "type": "string",
            "pattern": "^0x[0-9a-fA-F]{40}$"
          },
          "sourceDex": {
            "const": "spot"
          },
          "destinationDex": {
            "const": "spot"
          },
          "token": {
            "type": "string",
            "description": "USDC token id (name:tokenId), as returned by GET /pay/prepare."
          },
          "amount": {
            "type": "string",
            "examples": [
              "15"
            ]
          },
          "fromSubAccount": {
            "const": ""
          },
          "nonce": {
            "type": "integer",
            "description": "Now, in ms (less than 10 minutes old)."
          }
        }
      },
      "Warning": {
        "type": "object",
        "description": "Non-blocking: the request succeeded. At prudent, equilibre or risque, at least 90% of a followed leader's trades would copy under Hyperliquid's minimum order at this balance; they open at minOrderUsd (11 USDC), larger than the level's share.",
        "properties": {
          "code": {
            "const": "copies_too_small"
          },
          "leader": {
            "type": "string",
            "pattern": "^0x[0-9a-fA-F]{40}$"
          },
          "tooSmallPct": {
            "type": "number"
          },
          "equity": {
            "type": "number"
          },
          "minOrderUsd": {
            "type": "number"
          },
          "minPracticalBalanceUsd": {
            "type": "number"
          },
          "message": {
            "type": "string"
          }
        }
      },
      "LevelPreview": {
        "type": "object",
        "description": "One level applied to your balance and your first leader. Fields are null without a balance (or planned amount) or without the leader's statistics.",
        "properties": {
          "nextCopyUsd": {
            "type": [
              "number",
              "null"
            ],
            "description": "Size in USDC of a copy of the leader's median trade at this level, at the trade's full size (the largest size the leader's position reached, adds included: copies follow adds). Never below the 11 USDC floor: a proportional copy under Hyperliquid's minimum opens at 11 USDC (so nextCopyUsd: 11 with tooSmallPct: 100 is expected on a small balance). Lower only when the level's exposure cap leaves less room."
          },
          "tooSmallPct": {
            "type": [
              "number",
              "null"
            ],
            "description": "Share (%) of the leader's trades over 30 days whose copy, at the trade's full size, would stay under the minimum order at your balance and level (it falls as the level's size rises). They are not skipped: they open at 11 USDC, larger than your level's share."
          },
          "exposureX": {
            "type": [
              "number",
              "null"
            ],
            "description": "Estimated peak total exposure, in times your balance: 3 leaders each holding their largest position at this scale, capped by the level's maxExposureX."
          },
          "liquidationDistancePct": {
            "type": [
              "number",
              "null"
            ],
            "description": "Approximate adverse price move (%) that would liquidate the account at exposureX, in cross margin (maintenance margin = half the initial margin at 40x)."
          },
          "copiesPerMonth": {
            "type": [
              "number",
              "null"
            ],
            "description": "The leader's trades per month."
          },
          "scale": {
            "type": [
              "number",
              "null"
            ],
            "description": "Copy ratio: your balance ÷ the leader's × the level's size ÷ 3."
          },
          "minPracticalBalanceUsd": {
            "type": "number",
            "description": "Balance from which a typical leader's median trade copies above the minimum order at this level (11 USDC ÷ (size per leader × 1/8)); a guide, the real share is tooSmallPct."
          }
        }
      },
      "Recommendation": {
        "type": "object",
        "description": "Recommended level for a balance (null fields when the balance is unknown or 0). The most prudent of prudent → equilibre → risque whose minimum practical balance (1,100 / 550 / 300 USDC) the balance covers; under every minimum, risque with belowAllMinimums: true (copies under Hyperliquid's minimum order open at 11 USDC whatever the level; risque, with the largest share per leader, stays closest to the leaders' proportions). advanced is never recommended. Advice only: any level can be saved.",
        "properties": {
          "recommendedLevel": {
            "enum": [
              "prudent",
              "equilibre",
              "risque",
              null
            ]
          },
          "belowAllMinimums": {
            "type": [
              "boolean",
              "null"
            ]
          },
          "recommendationNote": {
            "type": [
              "string",
              "null"
            ],
            "description": "One sentence: why this level."
          },
          "spotUsdc": {
            "type": "number",
            "description": "Only with a session and USDC in spot on a standard account (equity 0): the spot balance the recommendation is based on."
          },
          "equitySource": {
            "enum": [
              "spot"
            ],
            "description": "Present when the recommendation uses spot USDC (account not unified yet)."
          }
        }
      },
      "CopiesOnHold": {
        "type": "object",
        "description": "Why new copies would not open now, from what GET /me already reads (no extra Hyperliquid read). held: true when the leaders' next trades would not be copied.",
        "properties": {
          "held": {
            "type": "boolean"
          },
          "reasons": {
            "type": "array",
            "items": {
              "enum": [
                "not_activated",
                "paused",
                "trial_expired",
                "plan_expired",
                "key_invalid",
                "platform_paused",
                "no_leaders",
                "no_margin",
                "not_unified",
                "manual_positions",
                "xyz_not_unified"
              ]
            },
            "description": "not_activated: sign-up not finished; paused: POST /resume; trial_expired, plan_expired: pay a plan; key_invalid: sign a new trading key; platform_paused: WakeTrades paused new copies for everyone; no_leaders: PUT /settings; no_margin: deposit USDC; not_unified (prudent, equilibre, risque): POST /account/unified; manual_positions (prudent, equilibre, risque): close the positions in coins; xyz_not_unified (advanced on a standard account): only the xyz markets are held, held stays false."
          },
          "coins": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Positions opened outside WakeTrades (with manual_positions)."
          }
        }
      },
      "Suggestion": {
        "type": "object",
        "properties": {
          "level": {
            "type": "string"
          },
          "list": {
            "type": "string"
          },
          "rank": {
            "type": "integer"
          },
          "address": {
            "type": "string",
            "pattern": "^0x[0-9a-fA-F]{40}$"
          },
          "month": {
            "type": "string"
          },
          "stats": {
            "type": "object",
            "properties": {
              "winRatePct": {
                "type": [
                  "number",
                  "null"
                ]
              },
              "profitFactor": {
                "type": [
                  "number",
                  "null"
                ]
              },
              "tradesPerMonth": {
                "type": [
                  "number",
                  "null"
                ]
              },
              "medianHoldHours": {
                "type": [
                  "number",
                  "null"
                ]
              }
            }
          },
          "note": {
            "type": "string"
          },
          "liveCheck": {
            "type": "string",
            "examples": [
              "GET /api/v1/leader/0x…/positions"
            ],
            "description": "Report figures are month-end: read the trader's positions now before choosing."
          }
        }
      },
      "WebhookEvent": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "type": {
            "type": "string",
            "examples": [
              "open",
              "close",
              "stop_hit",
              "key_expiring",
              "plan_expiring",
              "trial_started",
              "plan_paid",
              "account_unified",
              "paused",
              "resumed",
              "announcement",
              "webhook.test"
            ]
          },
          "created": {
            "type": "integer"
          },
          "account": {
            "type": "string",
            "pattern": "^0x[0-9a-fA-F]{40}$"
          },
          "data": {
            "type": "object"
          }
        },
        "description": "Sent as POST with header WakeTrades-Signature: t=<ms>,v1=<hex HMAC-SHA256 of '<t>.<raw body>'>."
      }
    }
  },
  "paths": {
    "/session/nonce": {
      "post": {
        "summary": "Get the sign-in message",
        "security": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "address"
                ],
                "properties": {
                  "address": {
                    "type": "string",
                    "pattern": "^0x[0-9a-fA-F]{40}$"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Nonce (10 min) and message to sign",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "nonce": {
                      "type": "string"
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/session/verify": {
      "post": {
        "summary": "Sign in (creates the account the first time)",
        "description": "Signature = EIP-191 personal_sign of the exact message. 3 new accounts per IP address per day.",
        "security": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "address",
                  "nonce",
                  "message",
                  "signature"
                ],
                "properties": {
                  "address": {
                    "type": "string",
                    "pattern": "^0x[0-9a-fA-F]{40}$"
                  },
                  "nonce": {
                    "type": "string"
                  },
                  "message": {
                    "type": "string"
                  },
                  "signature": {
                    "type": "string"
                  },
                  "lang": {
                    "enum": [
                      "en",
                      "fr",
                      "zh",
                      "ko",
                      "es",
                      "vi"
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Session",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "token": {
                      "type": "string"
                    },
                    "client": {
                      "type": "object"
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/agent-link/nonce": {
      "post": {
        "summary": "Connect an AI agent (website only): the message to sign",
        "description": "Used by the website's Profile › AI Agent, signed in with the wallet. Body { access }: view (View only) or manage (Manage copying). Returns an EIP-4361 message from waketrades.com that says what the agent may do. Needs an active free trial or plan (403 access_required). Agent and Telegram sessions get 403 wallet_required: a person connects their agent from the website.",
        "security": [
          {
            "session": []
          }
        ],
        "responses": {
          "200": {
            "description": "Message to sign",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "nonce": {
                      "type": "string"
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "access"
                ],
                "properties": {
                  "access": {
                    "type": "string",
                    "enum": [
                      "view",
                      "manage"
                    ],
                    "description": "view = View only (reads and backtests), manage = Manage copying"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/agent-link": {
      "post": {
        "summary": "Connect an AI agent (website only): get the agent's code",
        "description": "Body { access, nonce, message, signature }: the message from /agent-link/nonce for the same access, signed by the wallet (personal_sign). Returns the agent's code, shown once: valid until the plan or free trial ends, 180 days at most (limit), and never again after a plan stop (401 agent_code_expired). A View only code answers 403 view_only to anything but reads and backtests. One Profile code at a time: a new code signs out the previous agent. Sent to Telegram and the webhook as agent_linked.",
        "security": [
          {
            "session": []
          }
        ],
        "responses": {
          "200": {
            "description": "Agent code",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "token": {
                      "type": "string"
                    },
                    "validUntil": {
                      "type": "integer"
                    },
                    "access": {
                      "type": "string",
                      "enum": [
                        "view",
                        "manage"
                      ]
                    },
                    "limit": {
                      "type": "integer",
                      "description": "Code limit: 180 days after its creation (ms)"
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "access",
                  "nonce",
                  "message",
                  "signature"
                ],
                "properties": {
                  "access": {
                    "type": "string",
                    "enum": [
                      "view",
                      "manage"
                    ],
                    "description": "The same access as in /agent-link/nonce"
                  },
                  "nonce": {
                    "type": "string"
                  },
                  "message": {
                    "type": "string",
                    "description": "The message from /agent-link/nonce, unchanged"
                  },
                  "signature": {
                    "type": "string",
                    "description": "EIP-191 (personal_sign) signature by the signed-in wallet, 0x-prefixed"
                  }
                }
              }
            }
          }
        }
      },
      "delete": {
        "summary": "Disconnect the AI agent",
        "description": "Signs out every AI agent session of this wallet at once (also callable by the agent itself). The website stays signed in and copying goes on. Sent as agent_unlinked.",
        "security": [
          {
            "session": []
          }
        ],
        "responses": {
          "200": {
            "description": "Disconnected",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "disconnected": {
                      "type": "boolean"
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/session/revoke-all": {
      "post": {
        "summary": "Sign out of all sessions",
        "description": "Signs out every session of this wallet (browsers, AI agents, links opened from the Telegram bot), this one included. Use it if a session token may have leaked. Copying is not affected.",
        "security": [
          {
            "session": []
          }
        ],
        "responses": {
          "200": {
            "description": "Signed out",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "revoked": {
                      "type": "boolean"
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/me": {
      "get": {
        "summary": "Account, copy status, positions, balance",
        "description": "client: address, state, lang, level, leaders, leader_names, wallet_name, agent_address, agent_approved_at, agent_valid_until, telegram_chat_id, telegram_username, trial_started_at, plan_kind, plan_expires_at, paused_reason, tos_accepted_at, tos_version, created_at. status: the copier (state, level, accountMode, notices, trial_ends_at, plan_expires_at, advanced (effective Advanced settings, null at other levels), advancedRulesActive (number of Advanced settings that differ from the defaults), dailyLossUntil (ms, or null when no daily loss limit is in progress)…; notices [\"standard_account\"] = the account isn't unified yet, POST /account/unified). equity: Hyperliquid balance (read at most every 10 minutes, refreshed after a payment or a switch). unified: true when status.accountMode is unifiedAccount or portfolioMargin (before activation, read from Hyperliquid); null if unknown. copiesOnHold: see CopiesOnHold. renewal: { days, until, planKind, founderPrice } while a paid plan is close to its end (6-month plan: 30 days, 3 months: 14, 1 month: 7), else null; renew before until to keep the founder price (plan_expiring webhook event at the start and the day before). States (client.state): setup, awaiting_signature, awaiting_telegram, trial, active, paused_user, paused_auto, trial_expired, expired, key_invalid. Paying during the trial switches state to active at once while status.trial_ends_at is still in the future: the plan starts when the trial ends (plan_expires_at = trial end + plan length).",
        "security": [
          {
            "session": []
          }
        ],
        "responses": {
          "200": {
            "description": "Account",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "client": {
                      "type": "object"
                    },
                    "status": {
                      "type": "object"
                    },
                    "copiesOnHold": {
                      "$ref": "#/components/schemas/CopiesOnHold"
                    },
                    "renewal": {
                      "type": [
                        "object",
                        "null"
                      ]
                    },
                    "positions": {
                      "type": "array"
                    },
                    "equity": {
                      "type": [
                        "number",
                        "null"
                      ]
                    },
                    "unified": {
                      "type": [
                        "boolean",
                        "null"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/preview": {
      "get": {
        "summary": "Exposure levels applied to your balance",
        "security": [
          {
            "session": []
          }
        ],
        "parameters": [
          {
            "name": "planned",
            "in": "query",
            "required": false,
            "description": "Amount (USDC) you plan to deposit, used when the account has no balance yet.",
            "schema": {
              "type": "number"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Preview for each level",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "equity": {
                      "type": "number",
                      "description": "Balance used: your Hyperliquid balance, or planned."
                    },
                    "walletEquity": {
                      "type": "number"
                    },
                    "planned": {
                      "type": "boolean"
                    },
                    "leader": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "Your first leader."
                    },
                    "hasStats": {
                      "type": "boolean"
                    },
                    "minOrderUsd": {
                      "type": "number",
                      "examples": [
                        11
                      ]
                    },
                    "levels": {
                      "type": "object",
                      "properties": {
                        "prudent": {
                          "$ref": "#/components/schemas/LevelPreview"
                        },
                        "equilibre": {
                          "$ref": "#/components/schemas/LevelPreview"
                        },
                        "risque": {
                          "$ref": "#/components/schemas/LevelPreview"
                        },
                        "advanced": {
                          "$ref": "#/components/schemas/LevelPreview"
                        }
                      }
                    },
                    "riskAckAboveUsd": {
                      "type": "number"
                    },
                    "recommendedLevel": {
                      "enum": [
                        "prudent",
                        "equilibre",
                        "risque",
                        null
                      ]
                    },
                    "belowAllMinimums": {
                      "type": [
                        "boolean",
                        "null"
                      ]
                    },
                    "recommendationNote": {
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  },
                  "description": "recommendedLevel, belowAllMinimums, recommendationNote: see Recommendation (for equity)."
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/settings": {
      "put": {
        "summary": "Leaders, exposure level, language",
        "description": "During sign-up, send the level alone first, then the leaders (GET /leaders/suggested proposes one); the next step needs at least one leader. dryRun: the same checks and errors, and the answer the call would give (dryRun: true, client as it would be, activeLeaders, warning, equity and the recommended level for it), with nothing saved and no event sent. ",
        "security": [
          {
            "session": []
          }
        ],
        "parameters": [
          {
            "name": "dryRun",
            "in": "query",
            "required": false,
            "description": "true: run every check and return what the call would do, without saving, sending or relaying anything (also accepted as \"dryRun\": true in the body).",
            "schema": {
              "type": "boolean"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "leaders": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "pattern": "^0x[0-9a-fA-F]{40}$"
                    },
                    "description": "Followed in order: up to 3 at prudent, equilibre and risque (at least 2 strongly recommended at risque), up to 5 at advanced; more gives 400 too_many_leaders. The size is set per leader. A list already longer after a move to a level with a lower maximum is kept: the extra leaders stay saved, on standby."
                  },
                  "level": {
                    "enum": [
                      "prudent",
                      "equilibre",
                      "risque",
                      "advanced"
                    ],
                    "description": "advanced: every plan, free trial included."
                  },
                  "lang": {
                    "enum": [
                      "en",
                      "fr",
                      "zh",
                      "ko",
                      "es",
                      "vi"
                    ]
                  },
                  "riskAck": {
                    "type": "boolean",
                    "description": "Required to move to risque above 10,000 USDC."
                  },
                  "dryRun": {
                    "type": "boolean"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Saved",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "client": {
                      "type": "object"
                    },
                    "warning": {
                      "$ref": "#/components/schemas/Warning"
                    },
                    "dryRun": {
                      "type": "boolean"
                    },
                    "activeLeaders": {
                      "type": "array",
                      "items": {
                        "type": "string",
                        "pattern": "^0x[0-9a-fA-F]{40}$"
                      }
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/leaders/name": {
      "put": {
        "summary": "Private name for one of your leaders",
        "security": [
          {
            "session": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "leader": {
                    "type": "string",
                    "pattern": "^0x[0-9a-fA-F]{40}$"
                  },
                  "name": {
                    "type": "string",
                    "maxLength": 24
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/leaders/suggested": {
      "get": {
        "summary": "Suggested traders for a level",
        "description": "Traders of our latest Monthly Report for the level (advanced uses risque's list). Rule: each more prudent level's suggestion is set aside first (prudent, then equilibre); then, among the level's #3 to #5 not set aside, the one who opened the most positions in the 30 days before the report is suggested (a tie goes to the better rank), never #1 or #2; if #3 to #5 were all set aside, the most active of them anyway. One suggestion per level, for every account (paid or not): three traders of the report in all; the full lists are in the monthly report with a paid plan (get_report). count above 1 is ignored (the answer adds countLimited: true). risque strongly recommends 2 leaders: choose the second one yourself. Top-level fields = the suggestion (unchanged shape); suggestions = [the suggestion]. Report figures are month-end: read each trader's live positions at liveCheck before choosing. The rest of the list is for subscribers. 404 no_suggestion: no report published yet; 400 invalid_level, invalid_count.",
        "security": [
          {
            "session": []
          }
        ],
        "parameters": [
          {
            "name": "level",
            "in": "query",
            "schema": {
              "enum": [
                "prudent",
                "equilibre",
                "risque",
                "advanced"
              ]
            },
            "description": "Default: the level saved with PUT /settings"
          },
          {
            "name": "count",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 3,
              "default": 1
            },
            "description": "Kept for compatibility: always one suggestion (countLimited: true above 1)"
          }
        ],
        "responses": {
          "200": {
            "description": "Suggested traders",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Suggestion"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "suggestions": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/Suggestion"
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/leaders/stats": {
      "get": {
        "summary": "Statistics of your leaders",
        "description": "From the cards already computed, no Hyperliquid read. A leader is null until their card exists: GET /leader/{address} computes it (if statsBusy, retry after retryAfter seconds); cards are refreshed every 24 hours.",
        "security": [
          {
            "session": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/agent": {
      "post": {
        "summary": "Trading key to authorize",
        "security": [
          {
            "session": []
          }
        ],
        "responses": {
          "200": {
            "description": "Key generated by WakeTrades",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "agentAddress": {
                      "type": "string",
                      "pattern": "^0x[0-9a-fA-F]{40}$"
                    },
                    "agentName": {
                      "const": "WakeTrades"
                    },
                    "hyperliquidChain": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/agent/approve": {
      "post": {
        "summary": "Relay your signed approveAgent to Hyperliquid",
        "description": "EIP-712: domain {name:'HyperliquidSignTransaction', version:'1', chainId: parseInt(signatureChainId), verifyingContract: 0x0…0}, primaryType 'HyperliquidTransaction:ApproveAgent' (hyperliquidChain string, agentAddress address, agentName string, nonce uint64). 502 hyperliquid_refused with reason no_deposit | too_many_agents | other.",
        "security": [
          {
            "session": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "action",
                  "signature"
                ],
                "properties": {
                  "action": {
                    "$ref": "#/components/schemas/ApproveAgentAction"
                  },
                  "signature": {
                    "$ref": "#/components/schemas/Signature"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "pattern": "^[\\x20-\\x7e]+$"
            },
            "description": "Optional. Retrying with the same key and the same request within 24 hours returns the first answer with the header Idempotent-Replayed: true and runs nothing again. Same key, different request: 422 idempotency_key_reused. First request still running: 409 idempotency_in_progress. 5xx and 429 answers are not kept. Ignored with dryRun. Keys are per account."
          }
        ]
      }
    },
    "/agent/verify": {
      "post": {
        "summary": "Accept the Terms and confirm the key",
        "description": "tosAccepted: true accepts https://waketrades.com/terms on behalf of the wallet owner. 409 agent_not_registered_yet: retry in 10 s. Starts the free trial if a webhook (or Telegram) is linked.",
        "security": [
          {
            "session": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "tosAccepted"
                ],
                "properties": {
                  "tosAccepted": {
                    "const": true
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Key approved",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "approved": {
                      "type": "boolean"
                    },
                    "validUntil": {
                      "type": "integer"
                    },
                    "state": {
                      "type": "string"
                    },
                    "warning": {
                      "$ref": "#/components/schemas/Warning"
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/webhook": {
      "get": {
        "summary": "Linked webhook (never the secret)",
        "security": [
          {
            "session": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "put": {
        "summary": "Link a webhook alert channel",
        "description": "https, port 443, public host. A webhook.test event must get a 2xx answer within 5 s. Returns the signing secret once. Starts the free trial if the key is already approved.",
        "security": [
          {
            "session": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "url"
                ],
                "properties": {
                  "url": {
                    "type": "string",
                    "format": "uri"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Linked",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "linked": {
                      "type": "boolean"
                    },
                    "url": {
                      "type": "string"
                    },
                    "secret": {
                      "type": "string"
                    },
                    "signatureHeader": {
                      "const": "WakeTrades-Signature"
                    },
                    "state": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "delete": {
        "summary": "Remove the webhook (copying pauses if no channel is left)",
        "security": [
          {
            "session": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/notifications": {
      "put": {
        "summary": "Mute position-move alerts",
        "security": [
          {
            "session": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "muted": {
                    "type": "boolean"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/order-mode": {
      "put": {
        "summary": "Market or limit entries for copies",
        "description": "status.orderMode in GET /me. limit (default for new accounts): a post-only order at the leader's entry price; unfilled after 1 minute, it is cancelled and the copy opens at market unless the price is more than 1% from the leader's entry; if the leader exits first, nothing is copied (limit_missed event). market: at market right away, skipped (late) beyond 1% from the leader's entry. Orders already waiting keep their mode.",
        "security": [
          {
            "session": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "mode": {
                    "enum": [
                      "market",
                      "limit"
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/max-positions": {
      "put": {
        "summary": "Advanced only: maximum number of open positions",
        "description": "Applies at the advanced level only (400 advanced_only otherwise; the other levels have no fixed number: one position per coin under their exposure cap). null = no limit. Same as maxOpenPositions in PUT /advanced.",
        "security": [
          {
            "session": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "maxPositions"
                ],
                "properties": {
                  "maxPositions": {
                    "type": [
                      "integer",
                      "null"
                    ],
                    "minimum": 1,
                    "maximum": 50
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/positions": {
      "get": {
        "summary": "Copied positions",
        "security": [
          {
            "session": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/orders": {
      "get": {
        "summary": "Copy orders, including skipped trades",
        "security": [
          {
            "session": []
          }
        ],
        "parameters": [
          {
            "name": "n",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            }
          },
          {
            "name": "before",
            "in": "query",
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/journal": {
      "get": {
        "summary": "Recent events (same as webhook events)",
        "security": [
          {
            "session": []
          }
        ],
        "parameters": [
          {
            "name": "n",
            "in": "query",
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/feedback": {
      "get": {
        "summary": "Your messages to the team and the team's replies",
        "security": [
          {
            "session": []
          }
        ],
        "responses": {
          "200": {
            "description": "Messages, oldest first",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "canWrite": {
                      "type": "boolean"
                    },
                    "unread": {
                      "type": "integer"
                    },
                    "messages": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "from": {
                            "enum": [
                              "you",
                              "team"
                            ]
                          },
                          "text": {
                            "type": "string"
                          },
                          "at": {
                            "type": "integer"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Send feedback, a bug report or a feature idea to the team",
        "description": "For activated accounts (trial, plan or expired; 403 account_required before). Free text, 1–2000 characters; email is optional and lets the team answer by email. Up to 10 messages per 24 h (429 feedback_limit). The team may reply: replies appear in GET /feedback.",
        "security": [
          {
            "session": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "message"
                ],
                "properties": {
                  "message": {
                    "type": "string",
                    "maxLength": 2000
                  },
                  "email": {
                    "type": "string",
                    "format": "email"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Sent",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "sent": {
                      "type": "boolean"
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/feedback/read": {
      "post": {
        "summary": "Mark the team's replies as read",
        "security": [
          {
            "session": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/history.csv": {
      "get": {
        "summary": "Closed copies as CSV (after a first payment)",
        "security": [
          {
            "session": []
          }
        ],
        "responses": {
          "200": {
            "description": "CSV",
            "content": {
              "text/csv": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/pause": {
      "post": {
        "summary": "Stop opening new copies",
        "security": [
          {
            "session": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "pattern": "^[\\x20-\\x7e]+$"
            },
            "description": "Optional. Retrying with the same key and the same request within 24 hours returns the first answer with the header Idempotent-Replayed: true and runs nothing again. Same key, different request: 422 idempotency_key_reused. First request still running: 409 idempotency_in_progress. 5xx and 429 answers are not kept. Ignored with dryRun. Keys are per account."
          }
        ]
      }
    },
    "/resume": {
      "post": {
        "summary": "Resume copying (needs Telegram or a webhook)",
        "security": [
          {
            "session": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "pattern": "^[\\x20-\\x7e]+$"
            },
            "description": "Optional. Retrying with the same key and the same request within 24 hours returns the first answer with the header Idempotent-Replayed: true and runs nothing again. Same key, different request: 422 idempotency_key_reused. First request still running: 409 idempotency_in_progress. 5xx and 429 answers are not kept. Ignored with dryRun. Keys are per account."
          }
        ]
      }
    },
    "/close-position": {
      "post": {
        "summary": "Close one copy at market",
        "security": [
          {
            "session": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "coin"
                ],
                "properties": {
                  "coin": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "pattern": "^[\\x20-\\x7e]+$"
            },
            "description": "Optional. Retrying with the same key and the same request within 24 hours returns the first answer with the header Idempotent-Replayed: true and runs nothing again. Same key, different request: 422 idempotency_key_reused. First request still running: 409 idempotency_in_progress. 5xx and 429 answers are not kept. Ignored with dryRun. Keys are per account."
          }
        ]
      }
    },
    "/close-all": {
      "post": {
        "summary": "Close every copy and pause",
        "security": [
          {
            "session": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "pattern": "^[\\x20-\\x7e]+$"
            },
            "description": "Optional. Retrying with the same key and the same request within 24 hours returns the first answer with the header Idempotent-Replayed: true and runs nothing again. Same key, different request: 422 idempotency_key_reused. First request still running: 409 idempotency_in_progress. 5xx and 429 answers are not kept. Ignored with dryRun. Keys are per account."
          }
        ]
      }
    },
    "/close-losing": {
      "post": {
        "summary": "Close the copies currently in loss",
        "description": "One of the actions of a drawdown_alert. Returns closed and failed coins; the other copies keep running.",
        "security": [
          {
            "session": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/advanced": {
      "put": {
        "summary": "Advanced settings",
        "description": "Every field optional; missing fields keep their value. Every filter and limit is off by default. markets (OR between groups) AND minMarketLeverage AND sides decide which NEW copies open; adds, reductions and closes of open copies are always followed. A trade not copied by these rules appears in GET /orders as a skip with code market_filtered, leverage_filtered, side_filtered or daily_loss_limit. GET /me returns the effective settings in status.advanced, status.advancedRulesActive (settings that differ from the defaults) and status.dailyLossUntil. 400 bad_input with a message.",
        "security": [
          {
            "session": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "sizePct": {
                    "type": "number",
                    "minimum": 5,
                    "maximum": 300,
                    "description": "Size of your copies in % of your leaders' size across 3 leaders (100 = risque)."
                  },
                  "maxExposureX": {
                    "type": [
                      "number",
                      "null"
                    ],
                    "minimum": 1,
                    "maximum": 50
                  },
                  "maxOpenPositions": {
                    "type": [
                      "integer",
                      "null"
                    ],
                    "minimum": 1,
                    "maximum": 50
                  },
                  "alertsPct": {
                    "type": "array",
                    "items": {
                      "type": "number",
                      "minimum": 1,
                      "maximum": 90
                    },
                    "minItems": 1,
                    "maxItems": 2
                  },
                  "autoStopPct": {
                    "type": [
                      "number",
                      "null"
                    ],
                    "minimum": 5,
                    "maximum": 90,
                    "description": "Drawdown from your highest balance at which every copy is closed and copying pauses."
                  },
                  "followAdds": {
                    "type": "boolean"
                  },
                  "copyLeaderTpSl": {
                    "type": "boolean"
                  },
                  "markets": {
                    "type": "array",
                    "uniqueItems": true,
                    "items": {
                      "enum": [
                        "crypto",
                        "btc",
                        "xyz",
                        "gold",
                        "wti",
                        "indexes"
                      ]
                    },
                    "default": [],
                    "description": "Markets new copies may open on, combined with OR; [] = all markets. crypto: any market of Hyperliquid's main perp dex (not xyz); btc: BTC only; xyz: any market of the xyz dex (tokenized stocks, indices, commodities); gold: xyz:GOLD; wti: xyz:CL only (not Brent); indexes: xyz:SP500, xyz:XYZ100, xyz:JP225, xyz:KR200. Skip code market_filtered."
                  },
                  "minMarketLeverage": {
                    "type": [
                      "integer",
                      "null"
                    ],
                    "minimum": 1,
                    "maximum": 50,
                    "default": null,
                    "description": "Copy only markets whose Hyperliquid max leverage is at least this, AND the markets filter. Skip code leverage_filtered."
                  },
                  "maxLeverage": {
                    "type": [
                      "integer",
                      "null"
                    ],
                    "minimum": 1,
                    "maximum": 50,
                    "default": null,
                    "description": "Cap on the leverage set on your copies (otherwise the market's max leverage, cross margin): it changes the margin used, not the copy size."
                  },
                  "sides": {
                    "enum": [
                      "both",
                      "long",
                      "short"
                    ],
                    "default": "both",
                    "description": "Copy only new positions on this side. Skip code side_filtered."
                  },
                  "copyStopPct": {
                    "type": [
                      "number",
                      "null"
                    ],
                    "minimum": 1,
                    "maximum": 90,
                    "default": null,
                    "description": "Your own stop on each new copy, reduce-only, at the entry price -X% (long) or +X% (short), kept at that price and resized after adds and reductions. If the leader's copied stop is closer to the entry, it is kept instead. Capped at 80% of the distance to liquidation; under 1%, the trade is skipped (liq_close). Copies already open keep the rule they opened with."
                  },
                  "tp1Pct": {
                    "type": [
                      "number",
                      "null"
                    ],
                    "minimum": 1,
                    "maximum": 1000,
                    "default": null,
                    "description": "Take profit 1 on each new copy, at this PnL % of the copy (leverage included, as Hyperliquid shows it): at 10x, 20 = +2% price. Closes tp1ClosePct % of the copy. null = off."
                  },
                  "tp1ClosePct": {
                    "type": "number",
                    "minimum": 1,
                    "maximum": 100,
                    "default": 50
                  },
                  "tp2Pct": {
                    "type": [
                      "number",
                      "null"
                    ],
                    "minimum": 1,
                    "maximum": 1000,
                    "default": null,
                    "description": "Take profit 2, above tp1Pct; closes tp2ClosePct % of what is left."
                  },
                  "tp2ClosePct": {
                    "type": "number",
                    "minimum": 1,
                    "maximum": 100,
                    "default": 100
                  },
                  "slPct": {
                    "type": [
                      "number",
                      "null"
                    ],
                    "minimum": 1,
                    "maximum": 100,
                    "default": null,
                    "description": "Your own stop loss on each new copy, at this PnL % loss of the copy (leverage included); closes slClosePct % of the copy (100 = all, then the closest of your stop, your leader's and copyStopPct is kept). After a partial close the copy keeps following the leader on what is left. null = off."
                  },
                  "slClosePct": {
                    "type": "number",
                    "minimum": 1,
                    "maximum": 100,
                    "default": 100
                  },
                  "breakEvenAfterTp1": {
                    "type": "boolean",
                    "default": false,
                    "description": "After take profit 1, move the copy's stop to break-even (entry price plus 0.1% of fees)."
                  },
                  "dailyLossPct": {
                    "type": [
                      "number",
                      "null"
                    ],
                    "minimum": 1,
                    "maximum": 50,
                    "default": null,
                    "description": "When your balance, deposits and withdrawals of the day excluded, falls this % below its first reading of the UTC day, no new copies for 24 hours from that moment (event daily_loss_limit, skip code daily_loss_limit); open copies stay managed. Setting it to null lifts a limit in progress."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/emergency-stop": {
      "post": {
        "summary": "Emergency stop: close every copy and pause, in one call",
        "description": "Same as /close-all, with stopped: true, state, closed, failed, keyRevoked: false and how to revoke the trading key yourself (only your wallet can, on Hyperliquid › API). Resume with POST /resume.",
        "security": [
          {
            "session": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "pattern": "^[\\x20-\\x7e]+$"
            },
            "description": "Optional. Retrying with the same key and the same request within 24 hours returns the first answer with the header Idempotent-Replayed: true and runs nothing again. Same key, different request: 422 idempotency_key_reused. First request still running: 409 idempotency_in_progress. 5xx and 429 answers are not kept. Ignored with dryRun. Keys are per account."
          }
        ]
      }
    },
    "/stream": {
      "get": {
        "summary": "Real-time stream (WebSocket): events, leader moves and commands",
        "description": "Open with Upgrade: websocket (426 upgrade_required otherwise) and Authorization: Bearer <session>. First message: hello. Pushes every journal event in the webhook shape {id, type, created, account, data}, plus leader_open / leader_add / leader_cut / leader_close / leader_flip / leader_tpsl for the leaders you follow. Commands in: {id, type} with type ping, status, positions, orders, journal, pause, resume, close_position (coin), close_all, emergency_stop; answer {type: result, id, ok, data | error, message}. 3 streams per account (429 too_many_streams), 60 commands per minute per stream (rate_limited); write commands refused from restricted jurisdictions (geo_blocked); closed with code 4001 when the session expires. Guide: https://waketrades.com/docs/api/stream",
        "security": [
          {
            "session": []
          }
        ],
        "responses": {
          "101": {
            "description": "Switching Protocols: the WebSocket is open"
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/report": {
      "get": {
        "summary": "Monthly report: up to 5 traders per exposure level",
        "description": "The latest edition, or ?month=YYYY-MM; ?level=prudent|equilibre|risque for one level. access: full with a paid plan in progress, preview otherwise (free trial included). Preview: rank, type, the copy figures, the trader's 90-day and 6-month returns, win rate (rounded down to 1%) and profit factor (1 decimal); no names, addresses or other account figures (entries marked locked: true). Both accesses also return yourCopy (the top 3 of each level copied together, by balance), market (the month's market: coins, who made money, where), texts (the month's notes) and annex.topReturns (the month's biggest returns and why they are not listed). In preview, texts drop any sentence with a name or an address and the per-leader notes; annex keeps up to 3 reasons, without address or equity. 404 no_edition before the first edition (online on 1 November 2026, covering October).",
        "security": [
          {
            "session": []
          }
        ],
        "parameters": [
          {
            "name": "level",
            "in": "query",
            "schema": {
              "enum": [
                "prudent",
                "equilibre",
                "risque"
              ]
            }
          },
          {
            "name": "month",
            "in": "query",
            "schema": {
              "type": "string",
              "pattern": "^\\d{4}-(0[1-9]|1[0-2])$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/report.md": {
      "get": {
        "summary": "Monthly report as Markdown, for agents and assistants",
        "description": "Same edition, same access rules and same parameters as GET /report (full with a paid plan, preview without names or addresses otherwise), as text/markdown, in the page's order: the lists per level with Your Copy by balance, the notes, the month's market, the biggest returns and why they are not listed.",
        "security": [
          {
            "session": []
          }
        ],
        "parameters": [
          {
            "name": "month",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "level",
            "in": "query",
            "required": false,
            "schema": {
              "enum": [
                "prudent",
                "equilibre",
                "risque"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Markdown",
            "content": {
              "text/markdown": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/hello": {
      "get": {
        "summary": "Hello: what WakeTrades is and how to start",
        "description": "Public, no session, no Hyperliquid read. name, what (one sentence), quickStart (3 steps with their endpoints), network (Mainnet or Testnet), copying (on, pause or halt: the switch for every account), links (docs, openapi, llms, mcp, skills, terms), version.",
        "security": [],
        "responses": {
          "200": {
            "description": "Hello",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "name": {
                      "const": "WakeTrades"
                    },
                    "what": {
                      "type": "string"
                    },
                    "quickStart": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "step": {
                            "type": "string"
                          },
                          "endpoint": {
                            "type": "string"
                          }
                        }
                      }
                    },
                    "network": {
                      "enum": [
                        "Mainnet",
                        "Testnet"
                      ]
                    },
                    "copying": {
                      "enum": [
                        "on",
                        "pause",
                        "halt"
                      ]
                    },
                    "links": {
                      "type": "object",
                      "properties": {
                        "docs": {
                          "type": "string"
                        },
                        "openapi": {
                          "type": "string"
                        },
                        "llms": {
                          "type": "string"
                        },
                        "mcp": {
                          "type": "string"
                        },
                        "skills": {
                          "type": "string"
                        },
                        "terms": {
                          "type": "string"
                        }
                      }
                    },
                    "version": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/teapot": {
      "get": {
        "summary": "I'm a teapot",
        "description": "Answers 418 with a haiku about copy trading. Harmless, constant, for fun.",
        "security": [],
        "responses": {
          "418": {
            "description": "A haiku",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "teapot": {
                      "const": true
                    },
                    "haiku": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "next": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/levels": {
      "get": {
        "summary": "The four exposure levels, and the recommended one for a balance",
        "description": "Public. For each level: sizeOfLeadersPct, sizePerLeaderPct, leaders {min, max}, maxExposureX, drawdownAlertsPct, margin, unifiedAccount ('required' at prudent, equilibre and risque; 'xyz_only' at advanced: only the xyz markets need it), noManualPositions, minPracticalBalanceUsd (balance from which a typical leader's median trade copies above the 11 USDC minimum: 1100, 550, 300, 300), plans; advanced adds customizable, defaults and fields. With ?equity= or a session token (the account's Hyperliquid balance): equity and the Recommendation fields; otherwise null. 400 invalid_equity.",
        "security": [],
        "parameters": [
          {
            "name": "equity",
            "in": "query",
            "required": false,
            "description": "Balance in USDC to recommend a level for (0 to 1e9). Default: the signed-in account's balance, if a bearer token is sent.",
            "schema": {
              "type": "number",
              "minimum": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Levels",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "type": "object",
                      "properties": {
                        "levels": {
                          "type": "array",
                          "items": {
                            "type": "object"
                          }
                        },
                        "equity": {
                          "type": [
                            "number",
                            "null"
                          ]
                        }
                      }
                    },
                    {
                      "$ref": "#/components/schemas/Recommendation"
                    }
                  ]
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/offer": {
      "get": {
        "summary": "Prices and the founder rule",
        "description": "prices and listPrices (struck regular prices) in USDC for 1m / 3m / 6m; founderOpen; founderRule: 50% off for as long as you renew before your plan ends, regular prices if a paid plan lapses; founderAvailability: first members only, can close without notice; bestValue: 6m (same length as the 180-day trading key).",
        "security": [],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/subscription": {
      "get": {
        "summary": "Receiver, offers, founder rule, trial and plan dates",
        "description": "founder: true if your founder price applies; founderOnActivation: true before activation while founder seats remain (same rule as GET /offer): the offers then show the founder price the account will get when its trial starts; founderRule; bestValue: 6m; offers: kind, months, price, perMonth, savePct, listPrice, discountPct. payments: applied plans; tx_hash is null until the hourly reconciliation with Hyperliquid's ledger fills it (within the hour).",
        "security": [
          {
            "session": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/pay/prepare": {
      "get": {
        "summary": "Prepare a plan payment: action and typedData to sign",
        "description": "Picks the source of the USDC: your free perps balance first (usdSend), otherwise your spot balance (sendAsset from spot to spot; a unified account keeps its USDC in spot). Returns plan, price, source ('perps' or 'spot'), action and typedData (EIP-712) to sign, then POST /pay with the action and the signature. 409 insufficient_usdc with perps, spot and price when neither covers the plan.",
        "security": [
          {
            "session": []
          }
        ],
        "parameters": [
          {
            "name": "plan",
            "in": "query",
            "required": true,
            "schema": {
              "enum": [
                "1m",
                "3m",
                "6m"
              ]
            }
          },
          {
            "name": "chainId",
            "in": "query",
            "required": false,
            "description": "Hex chain id your wallet signs on (default 0xa4b1).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Payment to sign",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "plan": {
                      "enum": [
                        "1m",
                        "3m",
                        "6m"
                      ]
                    },
                    "price": {
                      "type": "number"
                    },
                    "source": {
                      "enum": [
                        "perps",
                        "spot"
                      ]
                    },
                    "action": {
                      "oneOf": [
                        {
                          "$ref": "#/components/schemas/UsdSendAction"
                        },
                        {
                          "$ref": "#/components/schemas/SendAssetAction"
                        }
                      ]
                    },
                    "typedData": {
                      "type": "object",
                      "description": "EIP-712 data to sign as is (eth_signTypedData_v4)."
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/pay": {
      "post": {
        "summary": "Pay a plan with your signed usdSend or sendAsset",
        "description": "Send the action from GET /pay/prepare and its signature. usdSend: EIP-712 'HyperliquidTransaction:UsdSend' (hyperliquidChain, destination, amount, time); sendAsset: 'HyperliquidTransaction:SendAsset' (hyperliquidChain, destination, sourceDex 'spot', destinationDex 'spot', token USDC, amount, fromSubAccount '', nonce). amount = exact plan price; destination = receiver from /subscription. dryRun: every check of the real call (action, plan and amount, receiver, token, signer, age) plus the balance of the signed source (409 insufficient_usdc), answering { dryRun: true, ok: true, plan, amount, from, source, balanceChecked, wouldRelay: true } or the same error; nothing is relayed, applied or written. Then send the same action without dryRun within its 10 minutes.",
        "security": [
          {
            "session": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "pattern": "^[\\x20-\\x7e]+$"
            },
            "description": "Optional. Retrying with the same key and the same request within 24 hours returns the first answer with the header Idempotent-Replayed: true and runs nothing again. Same key, different request: 422 idempotency_key_reused. First request still running: 409 idempotency_in_progress. 5xx and 429 answers are not kept. Ignored with dryRun. Keys are per account."
          },
          {
            "name": "dryRun",
            "in": "query",
            "required": false,
            "description": "true: run every check and return what the call would do, without saving, sending or relaying anything (also accepted as \"dryRun\": true in the body).",
            "schema": {
              "type": "boolean"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "plan",
                  "action",
                  "signature"
                ],
                "properties": {
                  "plan": {
                    "enum": [
                      "1m",
                      "3m",
                      "6m"
                    ]
                  },
                  "action": {
                    "oneOf": [
                      {
                        "$ref": "#/components/schemas/UsdSendAction"
                      },
                      {
                        "$ref": "#/components/schemas/SendAssetAction"
                      }
                    ]
                  },
                  "signature": {
                    "$ref": "#/components/schemas/Signature"
                  },
                  "dryRun": {
                    "type": "boolean"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Paid (or, with dryRun, what would happen)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "paid": {
                      "type": "boolean"
                    },
                    "planExpiresAt": {
                      "type": "integer"
                    },
                    "dryRun": {
                      "type": "boolean"
                    },
                    "ok": {
                      "type": "boolean"
                    },
                    "plan": {
                      "type": "string"
                    },
                    "amount": {
                      "type": "number"
                    },
                    "from": {
                      "type": "string",
                      "pattern": "^0x[0-9a-fA-F]{40}$"
                    },
                    "source": {
                      "enum": [
                        "perps",
                        "spot"
                      ]
                    },
                    "balanceChecked": {
                      "type": "boolean"
                    },
                    "wouldRelay": {
                      "type": "boolean"
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/leader/{address}": {
      "get": {
        "summary": "A Hyperliquid trader's card",
        "description": "stats: computed from the trader's last 2,000 trades and kept 24 hours (type: scalp, day, swing or unknown); stats.d90: the same figures over 90 days with pnlUsd and pnlPct (perps only); stats.pnl30Usd / pnl30Pct: 30-day gain on perps. Signed in: activity.closed, the 5 latest closed positions (coin, side, value, entryPx, exitPx, pnl after fees, holdMs, closedAt), newest first. Without a session, activity has only lastTradeAt when the trader's trades were read in the last 10 minutes, otherwise null. statsBusy: true when no live read is free to compute a new card (5 per minute for the whole service): retry after retryAfter seconds (60).",
        "security": [],
        "parameters": [
          {
            "name": "address",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^0x[0-9a-fA-F]{40}$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/leader/{address}/positions": {
      "get": {
        "summary": "A trader's open positions now",
        "description": "coin, side, sizeUsd, entryPx, markPx, leverage, leverageType, pnl (unrealized), liquidationPx, notCopied, and openedAt (ms) or openedBefore. Read from Hyperliquid, kept 60 seconds. Read it before choosing a suggested trader: report figures are month-end. notCopied: true would mark a market WakeTrades never copies; only copied markets are listed, so it is false. It does not say whether that position is copied: positions a leader already holds when you start copying are never copied, only the trades they open afterwards. orders: open orders, newest first — kind (limit, sl, tp), coin, side (1 buy, -1 sell), reduceOnly, wholePosition, value (USDC), px (trigger price for sl / tp, else limit price), tp and sl (trigger prices of the take profit and stop loss attached to that order, or null), placedAt. Reads not already kept: 2 per minute per account (429 beyond).",
        "security": [
          {
            "session": []
          }
        ],
        "parameters": [
          {
            "name": "address",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^0x[0-9a-fA-F]{40}$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/backtest": {
      "post": {
        "summary": "Backtest a trader: what copying them would have done",
        "description": "What copying one Hyperliquid trader would have done over the last 30 or 90 days at an exposure level (prudent, equilibre or risque; not advanced) and a starting balance. Same method as the Monthly Report's Simulated Copy column, for this one trader at the level's full size (in your account the size is split across 3 leaders): the trader's own fill prices plus our measured average copy delay cost, 0.0258% fees per side, adds and reductions followed, one position per coin, the level's exposure cap (3x, 10x, 20x), a margin check, a stop at -90%, positions valued every hour; funding not counted. maxDrawdownPct: worst drop from a peak, in % of the starting balance. coverage.truncated: Hyperliquid no longer serves the trader's oldest fills; trades opened before coverage.from are not simulated. The trader's data is read from Hyperliquid and kept 1 hour. Limits: 5 backtests per 24 hours during the free trial (or before activation), 20 with a paid plan (429 backtest_limit); one fresh Hyperliquid read per minute for the whole service (429 backtest_busy, Retry-After: 60). A simulation on past data, not a promise. Guide: https://waketrades.com/docs/api/backtest",
        "security": [
          {
            "session": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "leader",
                  "level"
                ],
                "properties": {
                  "leader": {
                    "type": "string",
                    "pattern": "^0x[0-9a-fA-F]{40}$"
                  },
                  "level": {
                    "enum": [
                      "prudent",
                      "equilibre",
                      "risque"
                    ]
                  },
                  "balance": {
                    "type": "number",
                    "minimum": 100,
                    "maximum": 10000000,
                    "default": 5000,
                    "description": "Starting balance in USDC."
                  },
                  "days": {
                    "enum": [
                      30,
                      90
                    ],
                    "default": 90
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Backtest",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "leader": {
                      "type": "string",
                      "pattern": "^0x[0-9a-fA-F]{40}$"
                    },
                    "level": {
                      "type": "string"
                    },
                    "balance": {
                      "type": "number"
                    },
                    "days": {
                      "type": "integer"
                    },
                    "period": {
                      "type": "object",
                      "properties": {
                        "from": {
                          "type": "string",
                          "format": "date-time"
                        },
                        "to": {
                          "type": "string",
                          "format": "date-time"
                        }
                      }
                    },
                    "result": {
                      "type": "object",
                      "properties": {
                        "returnPct": {
                          "type": "number"
                        },
                        "pnlUsd": {
                          "type": "number"
                        },
                        "endBalance": {
                          "type": "number"
                        },
                        "maxDrawdownPct": {
                          "type": "number"
                        },
                        "feesUsd": {
                          "type": "number"
                        },
                        "ruined": {
                          "type": "boolean"
                        }
                      }
                    },
                    "trades": {
                      "type": "object",
                      "properties": {
                        "leader": {
                          "type": "integer",
                          "description": "Trades the trader opened in the period (copied markets)."
                        },
                        "copied": {
                          "type": "integer"
                        },
                        "skipped": {
                          "type": "object",
                          "additionalProperties": {
                            "type": "integer"
                          },
                          "description": "Count per reason: already_in_coin, exposure_cap, insufficient_margin, order_below_minimum, market_not_copied, price_moved_over_1pct, no_mark_price."
                        },
                        "openAtEnd": {
                          "type": "integer"
                        }
                      }
                    },
                    "coverage": {
                      "type": "object",
                      "properties": {
                        "truncated": {
                          "type": "boolean"
                        },
                        "from": {
                          "type": "string",
                          "format": "date-time"
                        },
                        "days": {
                          "type": "number"
                        },
                        "fills": {
                          "type": "integer"
                        },
                        "note": {
                          "type": "string"
                        },
                        "valuedAtEntry": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        },
                        "valuedAtEntryNote": {
                          "type": "string"
                        }
                      }
                    },
                    "assumptions": {
                      "type": "string"
                    },
                    "disclaimer": {
                      "type": "string"
                    },
                    "dataAt": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "usage": {
                      "type": "object",
                      "properties": {
                        "used": {
                          "type": "integer"
                        },
                        "limit": {
                          "type": "integer"
                        },
                        "window": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/account/unified": {
      "post": {
        "summary": "Switch the Hyperliquid account to a Unified Account",
        "description": "Call it right after POST /agent/verify. At prudent, equilibre and risque, new copies open only on a Unified Account with no position opened outside WakeTrades; at advanced, only the xyz markets need it. WakeTrades switches it with its trading key (Hyperliquid agentSetAbstraction): no wallet signature; your USDC moves from perps to spot on Hyperliquid. Body: {} (ignored). Returns { mode, unified }; already unified → nothing is sent. Sends an account_unified event. Errors: key_required (sign the trading key first), switch_failed (Hyperliquid refused: switch it in your Hyperliquid settings).",
        "security": [
          {
            "session": []
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "description": "Empty object."
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "mode": {
                      "type": "string"
                    },
                    "unified": {
                      "type": "boolean"
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "pattern": "^[\\x20-\\x7e]+$"
            },
            "description": "Optional. Retrying with the same key and the same request within 24 hours returns the first answer with the header Idempotent-Replayed: true and runs nothing again. Same key, different request: 422 idempotency_key_reused. First request still running: 409 idempotency_in_progress. 5xx and 429 answers are not kept. Ignored with dryRun. Keys are per account."
          }
        ]
      }
    },
    "/account/delete-check": {
      "get": {
        "summary": "Can the account be deleted?",
        "security": [
          {
            "session": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/account/delete/nonce": {
      "post": {
        "summary": "Message to sign to delete the account",
        "security": [
          {
            "session": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/account/delete": {
      "post": {
        "summary": "Delete the account (signed message)",
        "security": [
          {
            "session": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    }
  },
  "webhooks": {
    "copyEvent": {
      "post": {
        "summary": "Copy event sent to your webhook",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookEvent"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx acknowledges the event."
          }
        }
      }
    }
  }
}
