{"openapi":"3.0.0","info":{"title":"Superior Trade API","version":"1.0.0","description":"API for managing trading strategies, backtesting, and live deployments. This API allows you to create trading strategies, run historical backtests to validate them, and deploy strategies to live trading environments."},"servers":[{"url":"https://api.superior.trade","description":"Production"},{"url":"https://api-staging.superior.trade","description":"Staging"},{"url":"http://localhost:3000","description":"Development"}],"security":[{"ApiKeyAuth":[]},{"BearerAuth":[]}],"components":{"securitySchemes":{"ApiKeyAuth":{"type":"apiKey","in":"header","name":"x-api-key","description":"API key authentication"},"BearerAuth":{"type":"http","scheme":"bearer","description":"JWT token from Privy embedded wallet authentication"}},"schemas":{"Error":{"type":"object","properties":{"error":{"type":"string","description":"Error code identifier"},"message":{"type":"string","description":"Human-readable error message"}}},"Backtest":{"type":"object","properties":{"id":{"type":"string"},"config":{"type":"object","description":"Freqtrade configuration (exchange, stake_currency, etc.)"},"code":{"type":"string","description":"Strategy code/implementation"},"timerange":{"type":"object","properties":{"start":{"type":"string","description":"Start date (YYYY-MM-DD)"},"end":{"type":"string","description":"End date (YYYY-MM-DD)"}}},"status":{"type":"string","enum":["pending","running","completed","failed"]},"results":{"type":"object","deprecated":true,"properties":{"total_trades":{"type":"number"},"winning_trades":{"type":"number"},"losing_trades":{"type":"number"},"win_rate":{"type":"string"},"total_profit":{"type":"string"},"max_drawdown":{"type":"string"},"sharpe_ratio":{"type":"number"}},"description":"Deprecated. Use `result_url` to download full backtest results as JSON."},"result_url":{"type":"string","description":"Signed URL to download backtest results as JSON (valid for 7 days). Only available when status is \"completed\"."},"started_at":{"type":"string","format":"date-time"},"completed_at":{"type":"string","format":"date-time"},"k8s_job_name":{"type":"string","description":"Kubernetes Job name"}}},"Deployment":{"type":"object","properties":{"id":{"type":"string"},"config":{"type":"object","description":"Freqtrade configuration"},"code":{"type":"string","description":"Strategy code/implementation"},"name":{"type":"string","description":"Human-readable deployment name"},"replicas":{"type":"number","description":"Number of running instances (always 1)"},"status":{"type":"string","enum":["pending","running","stopped"]},"available_replicas":{"type":"number"},"pods":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"status":{"type":"string"},"restarts":{"type":"number"}}}},"credentials_status":{"type":"string","enum":["stored","missing"]},"exchange":{"type":"string","description":"Exchange name","enum":["hyperliquid","aerodrome","binance"]},"execution_mode":{"type":"string","enum":["live","dry-run"],"description":"Execution mode for this deployment"},"k8s_deployment_name":{"type":"string"},"k8s_namespace":{"type":"string"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"DeploymentHistory":{"type":"object","properties":{"id":{"type":"string"},"deployment_id":{"type":"string","description":"Associated deployment ID (survives deletion)"},"created_by":{"type":"string","description":"User who owns this history record"},"updated_by":{"type":"string","description":"User who last updated this record"},"wallet_address":{"type":"string","description":"Wallet or subaccount address used during this session"},"pnl":{"type":"string","description":"Aggregated realized PnL from all fills (decimal string)"},"trades":{"type":"array","description":"Individual trade fills from the exchange","items":{"type":"object","properties":{"coin":{"type":"string","description":"Asset symbol (e.g., BTC, ETH)"},"px":{"type":"string","description":"Fill price"},"sz":{"type":"string","description":"Fill size"},"side":{"type":"string","description":"B for Bid/Buy, A for Ask/Sell"},"time":{"type":"number","description":"Timestamp in milliseconds"},"closed_pnl":{"type":"string","description":"Realized PnL from this fill"},"dir":{"type":"string","description":"Direction (e.g., Open Long, Close Short)"},"fee":{"type":"string","description":"Trading fee"}}}},"started_at":{"type":"string","format":"date-time","description":"When the deployment session started"},"ended_at":{"type":"string","format":"date-time","description":"When the deployment session ended (null if still active)"},"created_at":{"type":"string","format":"date-time"}}},"CopyTradingTraderSummary":{"type":"object","properties":{"trades":{"type":"number","description":"Number of trades in the validation backtest"},"win_rate":{"type":"number","description":"Backtest win rate as a decimal fraction"},"profit_pct":{"type":"number","description":"Backtest profit percentage"},"max_dd_pct":{"type":"number","description":"Backtest max drawdown percentage"},"sharpe":{"type":"number","nullable":true,"description":"Backtest Sharpe ratio when available"},"profit_factor_str":{"type":"string","description":"Display-ready profit factor, or \"infinity\""}}},"CopyTradingTraderListItem":{"type":"object","properties":{"wallet_address":{"type":"string","description":"Trader wallet address"},"truncated_address":{"type":"string","description":"Short display address"},"display_name":{"type":"string","nullable":true,"description":"Reserved display name slot"},"template_chip":{"type":"string","description":"Fitted strategy template label"},"target_pair":{"type":"string","description":"Target trading pair selected by synthesis"},"trust_tier":{"type":"string","enum":["green","yellow","red"],"description":"Copy-trading trust tier"},"validated_at":{"type":"string","format":"date-time","description":"Validation timestamp"},"summary":{"$ref":"#/components/schemas/CopyTradingTraderSummary"}}},"CopyTradingTraderList":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/CopyTradingTraderListItem"}},"total":{"type":"number","description":"Total matching traders before pagination"},"next_offset":{"type":"number","nullable":true,"description":"Offset for the next page, or null when no more results exist"}}},"CopyTradingTraderCard":{"allOf":[{"$ref":"#/components/schemas/CopyTradingTraderListItem"},{"type":"object","properties":{"profile":{"type":"object","nullable":true,"properties":{"pair_count":{"type":"number"},"top_pair":{"type":"string"},"taker_fraction":{"type":"number"},"wins":{"type":"number"},"losses":{"type":"number"},"win_rate":{"type":"number"},"median_notional_usd":{"type":"number"},"median_hold_sec":{"type":"number","nullable":true},"long_fraction":{"type":"number"},"last_fill_at":{"type":"string","format":"date-time"},"copyability_score":{"type":"number"},"copyability_reasons":{"type":"array","items":{"type":"string"}}}},"synthesis":{"type":"object","properties":{"fitted_template":{"type":"string"},"fitted_params":{"type":"object","additionalProperties":true},"target_pair":{"type":"string"},"strategy_code":{"type":"string"},"strategy_config":{"type":"object","additionalProperties":true},"audit":{"type":"object","properties":{"why_this_template":{"type":"string"},"regime_gate_explanation":{"type":"string"},"exit_explanation":{"type":"string"}}}}},"backtest":{"type":"object","properties":{"backtest_id":{"type":"string"},"window":{"type":"object","properties":{"start":{"type":"string"},"end":{"type":"string"}}},"trades":{"type":"number"},"win_rate":{"type":"number"},"profit_pct":{"type":"number"},"profit_factor_str":{"type":"string"},"max_dd_pct":{"type":"number"},"sharpe":{"type":"number","nullable":true},"exit_reason_summary":{"type":"array","items":{"type":"object","additionalProperties":true}}}},"deployment_template":{"type":"object","properties":{"config":{"type":"object","additionalProperties":true},"stake_amount_recommended":{"type":"number"},"max_open_trades":{"type":"number"},"risk_envelope":{"type":"object","properties":{"max_daily_loss_pct":{"type":"number"},"max_drawdown_halt_pct":{"type":"number"}}}}},"prompt_seed":{"type":"string","description":"Prompt text for confirming and deploying the copied strategy"}}}]}}},"paths":{"/auth/sign-in/magic-link":{"post":{"tags":["Authentication"],"summary":"Request API key","description":"Send your email to receive an API key directly. The API key will be sent to your inbox. Use the key in the x-api-key header for authenticated requests. We will verify the email once the API key is used","security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["email"],"properties":{"email":{"type":"string","format":"email","description":"Your email address"}}}}}},"responses":{"200":{"description":"Magic link sent successfully","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"boolean","example":true}}}}}}}}},"/auth/api-key":{"post":{"tags":["Authentication"],"summary":"Create API key","description":"Create a new API key for authenticated users. Returns the API key value which can be used in the x-api-key header for authenticated requests.","security":[{"BearerAuth":[]}],"responses":{"200":{"description":"API key created successfully","content":{"application/json":{"schema":{"type":"object","properties":{"key":{"type":"string","description":"The API key value"},"id":{"type":"string","description":"The API key ID"},"name":{"type":"string","description":"Optional name for the key"},"prefix":{"type":"string","description":"Key prefix for identification"},"expiresAt":{"type":"string","format":"date-time","nullable":true,"description":"Expiration date"},"createdAt":{"type":"string","format":"date-time","description":"Creation date"}}}}}}}},"get":{"tags":["Authentication"],"summary":"List API keys","description":"List all API keys associated with the authenticated user.","security":[{"BearerAuth":[]}],"responses":{"200":{"description":"List of API keys","content":{"application/json":{"schema":{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"The API key ID"},"name":{"type":"string","nullable":true,"description":"Optional name for the key"},"prefix":{"type":"string","description":"Key prefix for identification"},"refillInterval":{"type":"integer","nullable":true,"description":"Auto-refill interval in milliseconds"},"refillAmount":{"type":"integer","nullable":true,"description":"Auto-refill amount"},"lastRefillAt":{"type":"string","format":"date-time","nullable":true,"description":"Last refill timestamp"},"enabled":{"type":"boolean","description":"Whether the key is enabled"},"rateLimitEnabled":{"type":"boolean","description":"Whether rate limiting is enabled"},"rateLimitTimeWindow":{"type":"integer","description":"Rate limit time window in milliseconds"},"rateLimitMax":{"type":"integer","description":"Maximum requests per time window"},"requestCount":{"type":"integer","description":"Current request count"},"remaining":{"type":"integer","nullable":true,"description":"Remaining requests"},"expiresAt":{"type":"string","format":"date-time","nullable":true,"description":"Expiration date"},"createdAt":{"type":"string","format":"date-time","description":"Creation date"}}}},"nextCursor":{"type":"string","nullable":true,"description":"Cursor for next page"}}}}}}}}},"/auth/api-key/{id}":{"patch":{"tags":["Authentication"],"summary":"Rename API key","description":"Update the name of an API key. Only the owner (matching referenceId) can rename their own API key.","security":[{"BearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The ID of the API key to rename"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name"],"properties":{"name":{"type":"string","description":"New name for the API key (must be non-empty)"}}}}}},"responses":{"200":{"description":"API key renamed successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"name":{"type":"string","description":"The updated name"}}}}}},"400":{"description":"Invalid request - name is empty","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"API key not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"tags":["Authentication"],"summary":"Delete API key","description":"Delete an API key by providing its ID in the path.","security":[{"BearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The ID of the API key to delete"}],"responses":{"200":{"description":"API key deleted successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true}}}}}}}}},"/health":{"get":{"summary":"Health check","description":"Returns the health status of the API server. Use this endpoint to verify the service is running and accessible.","security":[],"responses":{"200":{"description":"Service is healthy","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","example":"ok"},"timestamp":{"type":"string","format":"date-time"}}}}}}}}},"/v1/backtesting":{"get":{"tags":["Backtesting"],"summary":"List all backtests","description":"Retrieves a paginated list of all backtest runs. Each backtest represents a historical simulation of a strategy on a specific trading pair and time range.","security":[{"ApiKeyAuth":[]}],"parameters":[{"name":"status","in":"query","required":false,"schema":{"type":"string","enum":["pending","running","completed","failed"]},"description":"Filter by backtest status"},{"name":"limit","in":"query","required":false,"schema":{"type":"number","default":10},"description":"Number of results to return"},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"Pagination cursor from previous response"},{"name":"with_code","in":"query","required":false,"schema":{"type":"string","enum":["true","false"]},"description":"Include strategy code in response (default: true)"},{"name":"with_config","in":"query","required":false,"schema":{"type":"string","enum":["true","false"]},"description":"Include config in response (default: true)"}],"responses":{"200":{"description":"List of backtests with pagination","content":{"application/json":{"schema":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/Backtest"}},"nextCursor":{"type":"string","nullable":true}}}}}}}},"post":{"tags":["Backtesting"],"summary":"Create and start a new backtest","description":"Creates a new backtest run and immediately starts execution. The backtest simulates the strategy on historical data for the specified trading pair and time range. Returns immediately with the backtest ID and initial status.","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["config","code","timerange"],"properties":{"config":{"type":"object","description":"Freqtrade configuration (exchange, stake_currency, etc.)"},"code":{"type":"string","description":"Strategy code/implementation (Python with freqtrade IStrategy)"},"timerange":{"type":"object","description":"Historical time range for the backtest","required":["start","end"],"properties":{"start":{"type":"string","description":"Start date","example":"2025-01-01"},"end":{"type":"string","description":"End date","example":"2025-12-31"}}}}}}}},"responses":{"201":{"description":"Backtest created successfully","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"status":{"type":"string","example":"pending"},"message":{"type":"string","description":"Instructions for starting the backtest"}}}}}},"400":{"description":"Invalid request - missing required fields","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/backtesting/{id}":{"get":{"tags":["Backtesting"],"summary":"Get backtest by ID","description":"Retrieves complete details of a specific backtest including current status and results (if completed).","security":[{"ApiKeyAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Backtest ID"}],"responses":{"200":{"description":"Backtest details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Backtest"}}}},"404":{"description":"Backtest not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"tags":["Backtesting"],"summary":"Delete a backtest","description":"Deletes a backtest and cleans up its Kubernetes job if present. Completed backtests are soft deleted; pending, running, and failed backtests are hard deleted.","security":[{"ApiKeyAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Backtest ID"}],"responses":{"200":{"description":"Backtest deleted successfully","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}}},"404":{"description":"Backtest not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/backtesting/{id}/status":{"get":{"tags":["Backtesting"],"summary":"Get backtest status","description":"Retrieves the current status of a backtest. Use this endpoint to poll for updates while a backtest is running.","security":[{"ApiKeyAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Backtest ID"}],"responses":{"200":{"description":"Backtest status","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"status":{"type":"string","enum":["pending","running","completed","failed"]}}}}}},"404":{"description":"Backtest not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"put":{"tags":["Backtesting"],"summary":"Update backtest status","description":"Controls the execution of a backtest. Use \"start\" to begin a pending backtest, or \"stop\" to cancel a running or pending backtest. Stopping will terminate the Kubernetes pod and mark the backtest as cancelled.","security":[{"ApiKeyAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Backtest ID"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["action"],"properties":{"action":{"type":"string","enum":["start","stop"],"description":"Action to perform: \"start\" begins a pending backtest, \"stop\" cancels a running/pending backtest"}}}}}},"responses":{"200":{"description":"Status updated successfully","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"status":{"type":"string"},"previous_status":{"type":"string"},"k8s_job_name":{"type":"string","description":"Kubernetes Job name"}}}}}},"400":{"description":"Invalid request - cannot perform action on current status","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Backtest not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/backtesting/{id}/logs":{"get":{"tags":["Backtesting"],"summary":"Get backtest logs","description":"Retrieves logs from Cloud Logging for a specific backtest job. Supports pagination with pageSize and pageToken query parameters.","security":[{"ApiKeyAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Backtest ID"},{"name":"pageSize","in":"query","schema":{"type":"number","default":100},"description":"Number of log entries to return"},{"name":"pageToken","in":"query","schema":{"type":"string"},"description":"Token for pagination"}],"responses":{"200":{"description":"Backtest logs","content":{"application/json":{"schema":{"type":"object","properties":{"backtest_id":{"type":"string"},"items":{"type":"array","items":{"type":"object","properties":{"timestamp":{"type":"string","description":"Log timestamp"},"message":{"type":"string","description":"Log message"},"severity":{"type":"string","description":"Log severity level"}}}},"nextCursor":{"type":"string","nullable":true}}}}}},"404":{"description":"Backtest not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/deployment":{"get":{"tags":["Deployment"],"summary":"List all deployments","description":"Retrieves a paginated list of all live trading deployments. Each deployment represents a strategy running in a live trading environment.","security":[{"ApiKeyAuth":[]}],"parameters":[{"name":"status","in":"query","required":false,"schema":{"type":"string","enum":["pending","running","stopped"]},"description":"Filter by deployment status"},{"name":"credentials_status","in":"query","required":false,"schema":{"type":"string","enum":["stored","missing"]},"description":"Filter by credentials status"},{"name":"wallet_address","in":"query","required":false,"schema":{"type":"string"},"description":"Filter by wallet address"},{"name":"limit","in":"query","required":false,"schema":{"type":"number","default":10},"description":"Number of results to return"},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"Pagination cursor from previous response"},{"name":"with_code","in":"query","required":false,"schema":{"type":"string","enum":["true","false"]},"description":"Include strategy code in response (default: true)"},{"name":"with_config","in":"query","required":false,"schema":{"type":"string","enum":["true","false"]},"description":"Include config in response (default: true)"}],"responses":{"200":{"description":"List of deployments with pagination","content":{"application/json":{"schema":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/Deployment"}},"nextCursor":{"type":"string","nullable":true}}}}}}}},"post":{"tags":["Deployment"],"summary":"Create a new deployment","description":"Creates a new live trading deployment. The deployment will be created in \"pending\" status and a Kubernetes deployment will be provisioned. Add exchange credentials before starting the deployment.","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["config","code","name"],"properties":{"config":{"type":"object","description":"Freqtrade configuration"},"code":{"type":"string","description":"Strategy code/implementation"},"name":{"type":"string","description":"Human-readable name for this deployment","example":"Production BTC/USDT"}}}}}},"responses":{"201":{"description":"Deployment created successfully","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"config":{"type":"object"},"code":{"type":"string"},"name":{"type":"string"},"replicas":{"type":"number","example":1},"status":{"type":"string","example":"running"},"k8s_deployment_name":{"type":"string"},"created_at":{"type":"string","format":"date-time"}}}}}},"400":{"description":"Invalid request - missing required fields","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/deployment/{id}":{"get":{"tags":["Deployment"],"summary":"Get deployment by ID","description":"Retrieves complete details of a specific deployment including status, replica count, and Kubernetes metadata.","security":[{"ApiKeyAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Deployment ID"}],"responses":{"200":{"description":"Deployment details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Deployment"}}}},"404":{"description":"Deployment not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"tags":["Deployment"],"summary":"Delete a deployment","description":"Permanently deletes a deployment and removes the Kubernetes resources. Ensure the deployment is stopped before deletion.","security":[{"ApiKeyAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Deployment ID"}],"responses":{"200":{"description":"Deployment deleted successfully","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}}},"404":{"description":"Deployment not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/deployment/{id}/status":{"get":{"tags":["Deployment"],"summary":"Get deployment status","description":"Retrieves the current status of a deployment including live Kubernetes status, replica counts, and pod information. Use this to monitor deployment health.","security":[{"ApiKeyAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Deployment ID"}],"responses":{"200":{"description":"Deployment status with live K8s data","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"status":{"type":"string","enum":["pending","running","stopped"]},"replicas":{"type":"number"},"available_replicas":{"type":"number"},"pods":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"status":{"type":"string"},"restarts":{"type":"number"}}}}}}}}},"404":{"description":"Deployment not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"put":{"tags":["Deployment"],"summary":"Update deployment status","description":"Controls the execution of a live deployment. Use \"start\" to begin trading (scales Kubernetes replicas to 1), or \"stop\" to halt trading (scales to 0). The deployment must have exchange credentials configured before starting.","security":[{"ApiKeyAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Deployment ID"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["action"],"properties":{"action":{"type":"string","enum":["start","stop"],"description":"Action to perform: \"start\" begins live trading, \"stop\" halts trading"}}}}}},"responses":{"200":{"description":"Status updated successfully","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"status":{"type":"string"},"previous_status":{"type":"string"}}}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Deployment not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/deployment/{id}/credentials":{"post":{"tags":["Deployment"],"summary":"Add exchange credentials","description":"Stores exchange API credentials for a deployment. Supports two modes:\n\n1. **Account Main Private Key**: Use the main account's private key - both `private_key` and `wallet_address` should be from the main account.\n\n2. **API Wallet Private Key**: Use an API wallet's private key - `private_key` is from the API wallet, but `wallet_address` must still be from the main account (for signing transactions).","security":[{"ApiKeyAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Deployment ID"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["exchange"],"properties":{"exchange":{"type":"string","description":"Exchange name","enum":["hyperliquid","aerodrome","binance"]},"private_key":{"type":"string","minLength":64,"description":"Wallet private key for wallet-based exchanges (Hyperliquid, Aerodrome)"},"wallet_address":{"type":"string","description":"Wallet address for wallet-based exchanges (Hyperliquid, Aerodrome)"},"api_key":{"type":"string","description":"API key for API-key exchanges (Binance)"},"api_secret":{"type":"string","description":"API secret for API-key exchanges (Binance)"}}},"examples":{"hyperliquid":{"summary":"Hyperliquid wallet credentials","value":{"exchange":"hyperliquid","wallet_address":"0x1234567890123456789012345678901234567890","private_key":"0xabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcd"}},"aerodrome":{"summary":"Aerodrome wallet credentials","value":{"exchange":"aerodrome","wallet_address":"0x1234567890123456789012345678901234567890","private_key":"0xabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcd"}},"binance":{"summary":"Binance API key credentials","value":{"exchange":"binance","api_key":"BINANCE_API_KEY","api_secret":"BINANCE_API_SECRET"}}}}}},"responses":{"200":{"description":"Credentials stored successfully","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"credentials_status":{"type":"string","example":"stored"},"exchange":{"type":"string"},"updated_at":{"type":"string","format":"date-time"}}}}}},"400":{"description":"Invalid request - missing required fields","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Deployment not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/deployment/{id}/exit":{"post":{"tags":["Deployment"],"summary":"Exit all positions","description":"Closes all open orders and closes all open positions using market orders for the deployment's exchange account. The deployment must be stopped before exiting positions.","security":[{"ApiKeyAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Deployment ID"}],"responses":{"200":{"description":"Positions exited successfully","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"status":{"type":"string"},"orders_cancelled":{"type":"number","description":"Number of orders cancelled"},"positions_closed":{"type":"number","description":"Number of positions closed"}}}}}},"400":{"description":"Invalid request - deployment must be stopped or credentials missing","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Deployment not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/deployment/{id}/logs":{"get":{"tags":["Deployment"],"summary":"Get deployment logs","description":"Retrieves logs from Cloud Logging for a specific deployment. Supports pagination with pageSize and pageToken query parameters.","security":[{"ApiKeyAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Deployment ID"},{"name":"pageSize","in":"query","schema":{"type":"number","default":100},"description":"Number of log entries to return"},{"name":"pageToken","in":"query","schema":{"type":"string"},"description":"Token for pagination"}],"responses":{"200":{"description":"Deployment logs","content":{"application/json":{"schema":{"type":"object","properties":{"deployment_id":{"type":"string"},"items":{"type":"array","items":{"type":"object","properties":{"timestamp":{"type":"string","description":"Log timestamp"},"message":{"type":"string","description":"Log message"},"severity":{"type":"string","description":"Log severity level"}}}},"nextCursor":{"type":"string","nullable":true}}}}}},"404":{"description":"Deployment not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v2/backtesting":{"get":{"tags":["BacktestingV2"],"summary":"List all backtests","description":"Retrieves a paginated list of all backtest runs. Each backtest represents a historical simulation of a strategy on a specific trading pair and time range.","parameters":[{"name":"status","in":"query","required":false,"schema":{"type":"string","enum":["pending","running","completed","failed"]},"description":"Filter by backtest status"},{"name":"limit","in":"query","required":false,"schema":{"type":"number","default":10},"description":"Number of results to return"},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"Pagination cursor from previous response"},{"name":"with_code","in":"query","required":false,"schema":{"type":"string","enum":["true","false"]},"description":"Include strategy code in response (default: true)"},{"name":"with_config","in":"query","required":false,"schema":{"type":"string","enum":["true","false"]},"description":"Include config in response (default: true)"}],"responses":{"200":{"description":"List of backtests with pagination","content":{"application/json":{"schema":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/Backtest"}},"nextCursor":{"type":"string","nullable":true}}}}}}}},"post":{"tags":["BacktestingV2"],"summary":"Create and start a new backtest","description":"Creates a new backtest run and immediately starts execution. The backtest simulates the strategy on historical data for the specified trading pair and time range. Returns immediately with the backtest ID and initial status.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["config","code","timerange"],"properties":{"config":{"type":"object","description":"Freqtrade configuration (exchange, stake_currency, etc.)"},"code":{"type":"string","description":"Strategy code/implementation (Python with freqtrade IStrategy)"},"timerange":{"type":"object","description":"Historical time range for the backtest","required":["start","end"],"properties":{"start":{"type":"string","description":"Start date","example":"2025-01-01"},"end":{"type":"string","description":"End date","example":"2025-12-31"}}}}}}}},"responses":{"201":{"description":"Backtest created successfully","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"status":{"type":"string","example":"pending"},"message":{"type":"string","description":"Instructions for starting the backtest"}}}}}},"400":{"description":"Invalid request - missing required fields","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v2/backtesting/{id}":{"get":{"tags":["BacktestingV2"],"summary":"Get backtest by ID","description":"Retrieves complete details of a specific backtest including current status and results (if completed).","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Backtest ID"}],"responses":{"200":{"description":"Backtest details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Backtest"}}}},"404":{"description":"Backtest not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"patch":{"tags":["BacktestingV2"],"summary":"Update a backtest","description":"Update fields on a backtest. Currently supports renaming.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Backtest ID"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"New name for the backtest (1-255 characters, trimmed)","example":"BTC 5m Trend Following"}}}}}},"responses":{"200":{"description":"Backtest updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Backtest"}}}},"400":{"description":"Invalid request - validation failed or no fields provided","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Backtest not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"tags":["BacktestingV2"],"summary":"Delete a backtest","description":"Deletes a backtest and cleans up its Kubernetes job if present. Completed backtests are soft deleted; pending, running, and failed backtests are hard deleted.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Backtest ID"}],"responses":{"200":{"description":"Backtest deleted successfully","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}}},"404":{"description":"Backtest not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v2/backtesting/{id}/status":{"get":{"tags":["BacktestingV2"],"summary":"Get backtest status","description":"Retrieves the current status of a backtest. Use this endpoint to poll for updates while a backtest is running.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Backtest ID"}],"responses":{"200":{"description":"Backtest status","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"status":{"type":"string","enum":["pending","running","completed","failed"]}}}}}},"404":{"description":"Backtest not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"put":{"tags":["BacktestingV2"],"summary":"Update backtest status","description":"Controls the execution of a backtest. Use \"start\" to begin a pending backtest, or \"stop\" to cancel a running or pending backtest. Stopping will terminate the Kubernetes pod and mark the backtest as cancelled.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Backtest ID"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["action"],"properties":{"action":{"type":"string","enum":["start","stop"],"description":"Action to perform: \"start\" begins a pending backtest, \"stop\" cancels a running/pending backtest"}}}}}},"responses":{"200":{"description":"Status updated successfully","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"status":{"type":"string"},"previous_status":{"type":"string"},"k8s_job_name":{"type":"string","description":"Kubernetes Job name"}}}}}},"400":{"description":"Invalid request - cannot perform action on current status","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Backtest not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v2/backtesting/{id}/logs":{"get":{"tags":["BacktestingV2"],"summary":"Get backtest logs","description":"Retrieves logs from Cloud Logging for a specific backtest job. Supports pagination with pageSize and pageToken query parameters.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Backtest ID"},{"name":"pageSize","in":"query","schema":{"type":"number","default":100},"description":"Number of log entries to return"},{"name":"pageToken","in":"query","schema":{"type":"string"},"description":"Token for pagination"}],"responses":{"200":{"description":"Backtest logs","content":{"application/json":{"schema":{"type":"object","properties":{"backtest_id":{"type":"string"},"items":{"type":"array","items":{"type":"object","properties":{"timestamp":{"type":"string","description":"Log timestamp"},"message":{"type":"string","description":"Log message"},"severity":{"type":"string","description":"Log severity level"}}}},"nextCursor":{"type":"string","nullable":true}}}}}},"404":{"description":"Backtest not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v2/backtesting-data/hyperliquid":{"get":{"tags":["BacktestingData"],"summary":"Check Hyperliquid backtesting data availability","description":"Checks if backtest data is available for a given trading pair and timeframe on Hyperliquid.","parameters":[{"name":"pair","in":"query","required":true,"schema":{"type":"string"},"description":"Trading pair (e.g., BTC/USDC:USDC)"},{"name":"timeframe","in":"query","required":false,"schema":{"type":"string","default":"5m"},"description":"Timeframe interval (e.g., 1m, 5m, 1h)"}],"responses":{"200":{"description":"Data availability information","content":{"application/json":{"schema":{"type":"object","properties":{"available":{"type":"boolean","description":"Whether data is available"},"pair":{"type":"string","description":"The trading pair"},"timeframe":{"type":"string","description":"The timeframe interval"},"from":{"type":"string","format":"date-time","description":"Start date of available data (present when available=true)"},"to":{"type":"string","format":"date-time","description":"End date of available data (present when available=true)"},"candles":{"type":"integer","description":"Number of candles available (present when available=true)"},"error":{"type":"string","description":"Error message explaining why data is not available (present when available=false)"}}}}}},"400":{"description":"Validation failed - missing required parameter","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal error - failed to check data availability","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v2/backtesting-data/aerodrome":{"get":{"tags":["BacktestingData"],"summary":"Check Aerodrome backtesting data availability","description":"Checks if backtest data is available for a given trading pair and timeframe on Aerodrome (Base DEX). Aerodrome fetches OHLCV live from Bitquery, so data is generally available even without pre-downloaded catalogs.","parameters":[{"name":"pair","in":"query","required":true,"schema":{"type":"string"},"description":"Trading pair (e.g., AERO/USDC)"},{"name":"timeframe","in":"query","required":false,"schema":{"type":"string","default":"5m"},"description":"Timeframe interval (e.g., 5m, 15m, 1h)"}],"responses":{"200":{"description":"Data availability information","content":{"application/json":{"schema":{"type":"object","properties":{"available":{"type":"boolean","description":"Whether data is available"},"pair":{"type":"string"},"timeframe":{"type":"string"},"from":{"type":"string","format":"date-time"},"to":{"type":"string","format":"date-time"},"candles":{"type":"integer"},"error":{"type":"string"}}}}}},"400":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v2/backtesting-data/binance":{"get":{"tags":["BacktestingData"],"summary":"Check Binance backtesting data availability","description":"Checks if backtest data is available for a given trading pair and timeframe on Binance.","parameters":[{"name":"pair","in":"query","required":true,"schema":{"type":"string"},"description":"Trading pair (e.g., BTC/USDT)"},{"name":"timeframe","in":"query","required":false,"schema":{"type":"string","default":"5m"},"description":"Timeframe interval (e.g., 1m, 5m, 1h)"}],"responses":{"200":{"description":"Data availability information","content":{"application/json":{"schema":{"type":"object","properties":{"available":{"type":"boolean","description":"Whether data is available"},"pair":{"type":"string","description":"The trading pair"},"timeframe":{"type":"string","description":"The timeframe interval"},"from":{"type":"string","format":"date-time","description":"Start date of available data (present when available=true)"},"to":{"type":"string","format":"date-time","description":"End date of available data (present when available=true)"},"candles":{"type":"integer","description":"Number of candles available (present when available=true)"},"error":{"type":"string","description":"Error message explaining why data is not available (present when available=false)"}}}}}},"400":{"description":"Validation failed - missing required parameter","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal error - failed to check data availability","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v2/account":{"get":{"tags":["AccountV2"],"summary":"List trading accounts","description":"Lists trading accounts linked to the authenticated user, ordered by account index.","security":[{"ApiKeyAuth":[]},{"BearerAuth":[]}],"responses":{"200":{"description":"Trading accounts","content":{"application/json":{"schema":{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"account_index":{"type":"number","description":"Trading account index"},"wallet_address":{"type":"string","nullable":true,"description":"Privy wallet address for the trading account"}}}}}}}}},"401":{"description":"Authentication required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Terminal database is not configured","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v2/account/deposit-link":{"get":{"tags":["AccountV2"],"summary":"Generate account deposit links","description":"Generates mobile wallet deep links for depositing native USDC on Arbitrum into one of the authenticated user trading account wallets. If wallet_address is omitted, the main trading account wallet is used.","security":[{"ApiKeyAuth":[]},{"BearerAuth":[]}],"parameters":[{"name":"chain","in":"query","required":false,"schema":{"type":"string","enum":["arbitrum"],"default":"arbitrum"},"description":"Deposit chain. Only Arbitrum is currently supported."},{"name":"wallet_address","in":"query","required":false,"schema":{"type":"string"},"description":"Destination trading account wallet. Must belong to the authenticated user. Defaults to the main trading account wallet."},{"name":"amount","in":"query","required":false,"schema":{"type":"string","default":"10"},"description":"USDC amount with up to 6 decimals."},{"name":"wallet","in":"query","required":false,"schema":{"type":"string","enum":["all","metamask","trust","coinbase","rainbow","okx","rabby","zerion","core","phantom","bitget","joyid"],"default":"all"},"description":"Wallet link format to return."}],"responses":{"200":{"description":"Deposit links","content":{"application/json":{"schema":{"type":"object","properties":{"chain":{"type":"string","example":"arbitrum"},"chain_id":{"type":"number","example":42161},"token":{"type":"object","properties":{"symbol":{"type":"string","example":"USDC"},"address":{"type":"string","example":"0xaf88d065e77c8cC2239327C5EDb3A432268e5831"},"decimals":{"type":"number","example":6}}},"amount":{"type":"string","example":"10"},"amount_atoms":{"type":"string","example":"10000000"},"wallet_address":{"type":"string","description":"Selected destination trading account wallet"},"selected_wallet":{"type":"string","enum":["all","metamask","trust","coinbase","rainbow","okx","rabby","zerion","core","phantom","bitget","joyid"]},"links":{"type":"object","additionalProperties":{"type":"string"},"properties":{"metamask":{"type":"string"},"trust":{"type":"string"},"coinbase":{"type":"string"},"rainbow":{"type":"string"},"okx":{"type":"string"},"rabby":{"type":"string"},"zerion":{"type":"string"},"core":{"type":"string"},"phantom":{"type":"string"},"bitget":{"type":"string"},"joyid":{"type":"string"},"eip681":{"type":"string"}}}}}}}},"400":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Authentication required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Trading account wallet not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Terminal database is not configured","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v2/account/status":{"get":{"tags":["AccountV2"],"summary":"Get account status","description":"Returns setup status for the authenticated user, including referral, builder fee, and Hyperliquid agent wallet readiness.","security":[{"ApiKeyAuth":[]},{"BearerAuth":[]}],"responses":{"200":{"description":"Account status","content":{"application/json":{"schema":{"type":"object","properties":{"accountTier":{"type":"string","enum":["free","pro"]},"referral":{"type":"object","properties":{"configured":{"type":"boolean"},"code":{"type":"string","nullable":true}}},"builder":{"type":"object","properties":{"configured":{"type":"boolean"},"address":{"type":"string"},"feePercent":{"type":"number"}}},"agentWallet":{"type":"object","properties":{"created":{"type":"boolean"},"address":{"type":"string"}}}}}}}},"400":{"description":"Agent wallet or builder setup is not ready","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Authentication required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"User wallet not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Terminal database is not configured","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v2/intelligence/scan":{"get":{"tags":["Intelligence"],"summary":"Get alpha scan","description":"Returns a filtered multi-bucket alpha scan from the agent server cache. Results can be narrowed by bucket, category, and top-N count.","security":[{"ApiKeyAuth":[]}],"parameters":[{"name":"bucket","in":"query","required":false,"schema":{"type":"string","enum":["all","squeeze","stealth","coiled","basis"],"default":"all"},"description":"Alpha bucket to return. Use all to include every bucket."},{"name":"category","in":"query","required":false,"schema":{"type":"string","enum":["alts","tradfi","both"],"default":"alts"},"description":"Market category to include."},{"name":"top_n","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":10,"default":5},"description":"Number of rows to return per bucket or TradFi group."}],"responses":{"200":{"description":"Alpha scan results","content":{"application/json":{"schema":{"type":"object","properties":{"computed_at":{"type":"string","format":"date-time"},"methodology":{"type":"object","additionalProperties":{"type":"string"}},"timeframes":{"type":"array","items":{"type":"string","enum":["15m","1h","4h","24h"]}},"alts":{"type":"object","properties":{"scanned":{"type":"number"},"buckets":{"type":"object","additionalProperties":{"type":"array","items":{"type":"object","properties":{"pair":{"type":"string"},"timeframe":{"type":"string"},"score":{"type":"number"},"snapshot":{"type":"object","additionalProperties":true},"best_fit":{"type":"object","additionalProperties":true}}}}}}},"tradfi":{"type":"object","properties":{"stocks":{"type":"array","items":{"type":"object","additionalProperties":true}},"indices":{"type":"array","items":{"type":"object","additionalProperties":true}},"commodities":{"type":"array","items":{"type":"object","additionalProperties":true}},"fx":{"type":"array","items":{"type":"object","additionalProperties":true}}}},"_note":{"type":"string"}}}}}},"400":{"description":"Invalid bucket or category","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Authentication required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Agent server alpha scan is unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v2/intelligence/setup/{pair}":{"get":{"tags":["Intelligence"],"summary":"Get pair setup card","description":"Returns a setup card for one scanned pair, including snapshot metrics, best fit, bucket scores, and presentation guidance.","security":[{"ApiKeyAuth":[]}],"parameters":[{"name":"pair","in":"path","required":true,"schema":{"type":"string"},"description":"Pair symbol to look up. Prefixes are normalized when matching scanned pairs."}],"responses":{"200":{"description":"Pair setup card or not-found result","content":{"application/json":{"schema":{"type":"object","properties":{"pair":{"type":"string"},"found":{"type":"boolean"},"computed_at":{"type":"string","format":"date-time"},"snapshot":{"type":"object","additionalProperties":true},"best_fit":{"type":"object","additionalProperties":true},"bucket_fits":{"type":"array","items":{"type":"object","properties":{"bucket":{"type":"string","enum":["squeeze","stealth","coiled","basis"]},"bucket_title":{"type":"string"},"best_timeframe":{"type":"string","enum":["15m","1h","4h","24h"]},"best_score":{"type":"number"},"score_by_timeframe":{"type":"object","additionalProperties":{"type":"number"}}}}},"_note":{"type":"string"}}}}}},"400":{"description":"Pair path parameter is missing","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Authentication required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Agent server alpha scan is unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v2/leaderboard-strategies":{"get":{"tags":["Leaderboard"],"summary":"List leaderboard strategies","description":"Returns live paper-trading leaderboard strategies in snake_case for frontend and paper deployment clients.","security":[],"responses":{"200":{"description":"Live leaderboard strategies","content":{"application/json":{"schema":{"type":"object","properties":{"strategies":{"type":"array","items":{"type":"object","properties":{"slug":{"type":"string"},"name":{"type":"string"},"prompt":{"type":"string"},"params":{"type":"object","properties":{"pair":{"type":"string"},"timeframe":{"type":"string"}}},"display_rank":{"type":"number"},"deployment_id":{"type":"string","nullable":true},"deployed_at":{"type":"string","nullable":true},"live_pnl_abs":{"type":"number","nullable":true},"live_pnl_pct":{"type":"number","nullable":true},"live_apr":{"type":"number","nullable":true},"pnl_24h_abs":{"type":"number","nullable":true},"pnl_24h_pct":{"type":"number","nullable":true},"account_value":{"type":"number","nullable":true},"snapshot_at":{"type":"string","nullable":true},"copy_count":{"type":"number"},"backtest_id":{"type":"string","nullable":true},"backtest":{"type":"object","nullable":true,"description":"Resolved backtest result structure from the linked backtest result URL when available.","properties":{"timerange":{"type":"object","properties":{"from":{"type":"string"},"to":{"type":"string"}}},"pnl_pct":{"type":"number"},"pnl_abs":{"type":"number"},"sharpe":{"type":"number"},"apr":{"type":"number","nullable":true},"max_drawdown":{"type":"number","nullable":true},"win_rate":{"type":"number","nullable":true},"profit_factor":{"type":"number","nullable":true},"total_trades":{"type":"number","nullable":true},"equity_curve":{"type":"array","items":{"type":"object","additionalProperties":true}},"actions":{"type":"array","items":{"type":"object","additionalProperties":true}}}}}}},"disclaimer":{"type":"string"}}}}}}}}},"/v2/copy-trading/traders":{"get":{"tags":["Copy Trading"],"summary":"List copy-trading traders","description":"Returns a paginated list of recently validated copy-trading candidates. Results include all trust tiers by default and can be filtered by tier.","security":[],"parameters":[{"name":"tier","in":"query","required":false,"schema":{"type":"string","enum":["green","yellow","red"]},"description":"Optional trust-tier filter"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":100,"default":20},"description":"Maximum number of traders to return. Values above 100 are capped."},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0},"description":"Zero-based pagination offset"}],"responses":{"200":{"description":"Copy-trading traders","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CopyTradingTraderList"}}}}}}},"/v2/copy-trading/traders/{wallet}":{"get":{"tags":["Copy Trading"],"summary":"Get copy-trading trader card","description":"Returns the full copy-trading card for one wallet, including behavioral profile, synthesized strategy, validation backtest, deployment template, and prompt seed.","security":[],"parameters":[{"name":"wallet","in":"path","required":true,"schema":{"type":"string"},"description":"Trader wallet address"}],"responses":{"200":{"description":"Copy-trading trader card","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CopyTradingTraderCard"}}}},"404":{"description":"Trader wallet was not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Copy-trading database is unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v2/paper-deployment":{"get":{"tags":["Paper Deployments"],"summary":"List paper deployments","description":"Lists credential-free dry-run deployments for the authenticated user.","parameters":[{"name":"status","in":"query","required":false,"schema":{"type":"string","enum":["pending","running","stopped"]},"description":"Filter by deployment status"},{"name":"limit","in":"query","required":false,"schema":{"type":"number","default":10},"description":"Number of results to return"},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"Pagination cursor from previous response"},{"name":"with_code","in":"query","required":false,"schema":{"type":"string","enum":["true","false"]},"description":"Include strategy code in response (default: true)"},{"name":"with_config","in":"query","required":false,"schema":{"type":"string","enum":["true","false"]},"description":"Include config in response (default: true)"}],"responses":{"200":{"description":"List of paper deployments with pagination","content":{"application/json":{"schema":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/Deployment"}},"nextCursor":{"type":"string","nullable":true}}}}}}}},"post":{"tags":["Paper Deployments"],"summary":"Create and start a paper deployment","description":"Creates and starts one credential-free Freqtrade dry-run deployment. Only one active dry-run deployment is allowed per user.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name","config","code"],"properties":{"name":{"type":"string","description":"Human-readable deployment name"},"config":{"type":"object","description":"Freqtrade configuration. The server forces dry_run true.","properties":{"dry_run_wallet":{"type":"object","additionalProperties":{"type":"string"},"example":{"USDC":"1000"}}}},"code":{"type":"string","description":"Strategy code/implementation"}}}}}},"responses":{"201":{"description":"Paper deployment started","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"status":{"type":"string","enum":["running"]},"execution_mode":{"type":"string","enum":["dry-run"]},"credentials_status":{"type":"string","enum":["missing"]},"k8s_deployment_name":{"type":"string"},"message":{"type":"string"}}}}}},"400":{"description":"Validation failed or active paper deployment exists","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Deployment creation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v2/paper-deployment/{id}":{"get":{"tags":["Paper Deployments"],"summary":"Get paper deployment","description":"Returns one dry-run deployment owned by the authenticated user.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Deployment ID"}],"responses":{"200":{"description":"Paper deployment","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Deployment"}}}},"404":{"description":"Paper deployment not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v2/paper-deployment/{id}/{paperDeploymentEndpoint}":{"get":{"tags":["Paper Deployments"],"summary":"Get paper deployment endpoint","description":"Proxies an allowlisted read-only paper deployment endpoint for a running dry-run bot. Query parameters are forwarded to Freqtrade.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Deployment ID"},{"name":"paperDeploymentEndpoint","in":"path","required":true,"schema":{"type":"string","enum":["profit","trades","status","count","entries","exits","performance","balance","daily","weekly","stats"]},"description":"Read-only paper deployment endpoint to proxy."}],"responses":{"200":{"description":"Raw paper deployment endpoint response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"description":"Raw response from the selected Freqtrade /api/v1 endpoint."}}}},"400":{"description":"Paper deployment is not running","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Paper deployment or endpoint not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Paper deployment endpoint returned an error or could not be reached","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Freqtrade REST API is not available yet","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v2/paper-deployment/{id}/status":{"put":{"tags":["Paper Deployments"],"summary":"Start or stop a paper deployment","description":"Starts or stops a dry-run deployment. Start is rejected when another dry-run deployment is active.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Deployment ID"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["action"],"properties":{"action":{"type":"string","enum":["start","stop"]}}}}}},"responses":{"200":{"description":"Paper deployment status updated","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Invalid status transition or active paper deployment exists","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Paper deployment not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v2/deployment":{"get":{"tags":["DeploymentV2"],"summary":"List all deployments","description":"Retrieves a paginated list of all live trading deployments. Each deployment represents a strategy running in a live trading environment.","parameters":[{"name":"status","in":"query","required":false,"schema":{"type":"string","enum":["pending","running","stopped"]},"description":"Filter by deployment status"},{"name":"credentials_status","in":"query","required":false,"schema":{"type":"string","enum":["stored","missing"]},"description":"Filter by credentials status"},{"name":"wallet_address","in":"query","required":false,"schema":{"type":"string"},"description":"Filter by wallet address"},{"name":"limit","in":"query","required":false,"schema":{"type":"number","default":10},"description":"Number of results to return"},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"Pagination cursor from previous response"},{"name":"with_code","in":"query","required":false,"schema":{"type":"string","enum":["true","false"]},"description":"Include strategy code in response (default: true)"},{"name":"with_config","in":"query","required":false,"schema":{"type":"string","enum":["true","false"]},"description":"Include config in response (default: true)"}],"responses":{"200":{"description":"List of deployments with pagination","content":{"application/json":{"schema":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/Deployment"}},"nextCursor":{"type":"string","nullable":true}}}}}}}},"post":{"tags":["DeploymentV2"],"summary":"Create a new deployment","description":"Creates a new live trading deployment. The deployment will be created in \"pending\" status and a Kubernetes deployment will be provisioned. Add exchange credentials before starting the deployment.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["config","code","name"],"properties":{"config":{"type":"object","description":"Freqtrade configuration"},"code":{"type":"string","description":"Strategy code/implementation"},"name":{"type":"string","description":"Human-readable name for this deployment","example":"Production BTC/USDT"}}}}}},"responses":{"201":{"description":"Deployment created successfully","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"config":{"type":"object"},"code":{"type":"string"},"name":{"type":"string"},"replicas":{"type":"number","example":1},"status":{"type":"string","example":"running"},"k8s_deployment_name":{"type":"string"},"created_at":{"type":"string","format":"date-time"}}}}}},"400":{"description":"Invalid request - missing required fields","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v2/deployment/{id}":{"get":{"tags":["DeploymentV2"],"summary":"Get deployment by ID","description":"Retrieves complete details of a specific deployment including status, replica count, and Kubernetes metadata.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Deployment ID"}],"responses":{"200":{"description":"Deployment details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Deployment"}}}},"404":{"description":"Deployment not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"patch":{"tags":["DeploymentV2"],"summary":"Update a deployment","description":"Update fields on a deployment. Currently supports renaming.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Deployment ID"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"New name for the deployment (1-255 characters, trimmed)","example":"BTC 5m Trend Following"}}}}}},"responses":{"200":{"description":"Deployment updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Deployment"}}}},"400":{"description":"Invalid request - validation failed or no fields provided","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Deployment not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"tags":["DeploymentV2"],"summary":"Delete a deployment","description":"Permanently deletes a deployment and removes the Kubernetes resources. Ensure the deployment is stopped before deletion.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Deployment ID"}],"responses":{"200":{"description":"Deployment deleted successfully","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}}},"404":{"description":"Deployment not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v2/deployment/{id}/status":{"get":{"tags":["DeploymentV2"],"summary":"Get deployment status","description":"Retrieves the current status of a deployment including live Kubernetes status, replica counts, and pod information. Use this to monitor deployment health.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Deployment ID"}],"responses":{"200":{"description":"Deployment status with live K8s data","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"status":{"type":"string","enum":["pending","running","stopped"]},"replicas":{"type":"number"},"available_replicas":{"type":"number"},"pods":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"status":{"type":"string"},"restarts":{"type":"number"}}}}}}}}},"404":{"description":"Deployment not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"put":{"tags":["DeploymentV2"],"summary":"Update deployment status","description":"Controls the execution of a live deployment. Use \"start\" to begin trading (scales Kubernetes replicas to 1), or \"stop\" to halt trading (scales to 0). The deployment must have exchange credentials configured before starting.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Deployment ID"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["action"],"properties":{"action":{"type":"string","enum":["start","stop"],"description":"Action to perform: \"start\" begins live trading, \"stop\" halts trading"}}}}}},"responses":{"200":{"description":"Status updated successfully","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"status":{"type":"string"},"previous_status":{"type":"string"}}}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Deployment not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v2/deployment/{id}/credentials":{"post":{"tags":["DeploymentV2"],"summary":"Add exchange credentials via Privy","description":"Add exchange credentials via Privy. In v2, private_key is not accepted - credentials are fetched from Privy. If wallet_address is omitted, uses the user's main trading wallet (first exportable wallet in their Privy account).","security":[{"ApiKeyAuth":[]},{"BearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Deployment ID"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["exchange"],"properties":{"exchange":{"type":"string","description":"Exchange name","enum":["hyperliquid","aerodrome","binance"]},"wallet_address":{"type":"string","description":"Wallet address for wallet-based exchanges. If omitted for Hyperliquid or Aerodrome, uses the user's main trading wallet from Privy."},"subaccount_address":{"type":"string","description":"Hyperliquid subaccount address (optional, only for Hyperliquid; must be a valid Ethereum address if provided)."},"api_key":{"type":"string","description":"API key for API-key exchanges (Binance)"},"api_secret":{"type":"string","description":"API secret for API-key exchanges (Binance)"}}},"examples":{"hyperliquidMainTradingWallet":{"summary":"Hyperliquid main trading wallet","value":{"exchange":"hyperliquid"}},"hyperliquidProvidedWallet":{"summary":"Hyperliquid provided wallet (must be in trading-accounts list)","value":{"exchange":"hyperliquid","wallet_address":"0x742d35Cc6634C0532925a3b844Bc454e4438f44e"}},"hyperliquidSubaccount":{"summary":"Hyperliquid subaccount","value":{"exchange":"hyperliquid","subaccount_address":"0x1111111111111111111111111111111111111111"}},"aerodrome":{"summary":"Aerodrome main trading wallet","value":{"exchange":"aerodrome"}},"binance":{"summary":"Binance API key credentials","value":{"exchange":"binance","api_key":"BINANCE_API_KEY","api_secret":"BINANCE_API_SECRET"}}}}}},"responses":{"200":{"description":"Credentials stored successfully","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"credentials_status":{"type":"string","example":"stored"},"exchange":{"type":"string"},"wallet_address":{"type":"string","description":"The wallet address used"},"wallet_source":{"type":"string","enum":["provided","main_trading_wallet"],"description":"Whether the wallet was provided in the request or auto-selected from Privy"},"subaccount_address":{"type":"string","nullable":true,"description":"Hyperliquid subaccount address if configured (Hyperliquid only)"},"updated_at":{"type":"string","format":"date-time"}}}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"invalid_request":{"summary":"Private key provided (not allowed in v2)","value":{"error":"invalid_request","message":"private_key is not accepted in v2 - credentials are fetched from Privy"}},"no_wallet_available":{"summary":"No wallet available","value":{"error":"no_wallet_available","message":"No exportable wallet found in your Privy account"}},"duplicate_wallet_address":{"summary":"Duplicate wallet address or subaccount","value":{"error":"duplicate_wallet_address","message":"This wallet address or subaccount is already used by another deployment"}},"invalid_wallet_address":{"summary":"Invalid wallet address","value":{"error":"invalid_wallet_address","message":"Invalid wallet address format"}},"invalid_subaccount_address":{"summary":"Invalid subaccount address","value":{"error":"invalid_subaccount_address","message":"Invalid Ethereum subaccount address format"}}}}}},"403":{"description":"Wallet not owned by user","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"wallet_not_owned":{"summary":"Wallet not owned","value":{"error":"wallet_not_owned","message":"The provided wallet address is not owned by your account"}},"subaccount_not_owned":{"summary":"Subaccount not owned","value":{"error":"subaccount_not_owned","message":"This subaccount does not belong to you"}}}}}},"404":{"description":"Deployment not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"get":{"tags":["DeploymentV2"],"summary":"Get credentials info","description":"Get credentials information for a deployment. Returns wallet address, source, and type. Does NOT return the private key.","security":[{"ApiKeyAuth":[]},{"BearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Deployment ID"}],"responses":{"200":{"description":"Credentials info","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"credentials_status":{"type":"string","enum":["stored","missing"]},"exchange":{"type":"string"},"wallet_address":{"type":"string","description":"The wallet address used"},"wallet_source":{"type":"string","enum":["provided","main_trading_wallet"],"description":"How the wallet was selected"},"wallet_type":{"type":"string","enum":["main_wallet","agent_wallet"],"description":"User-friendly wallet type"},"subaccount_address":{"type":"string","nullable":true,"description":"Hyperliquid subaccount address if configured (Hyperliquid only)"}}}}}},"404":{"description":"Deployment not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v2/deployment/{id}/exit":{"post":{"tags":["DeploymentV2"],"summary":"Exit all positions","description":"Closes all open orders and closes all open positions using market orders for the exchange account. For Hyperliquid deployments only (Aerodrome swaps are atomic with no open positions). Requires credentials_status to be stored on the deployment.","security":[{"ApiKeyAuth":[]},{"BearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Deployment ID"}],"responses":{"200":{"description":"Positions exited successfully","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"status":{"type":"string"},"orders_cancelled":{"type":"number","description":"Number of orders cancelled"},"positions_closed":{"type":"number","description":"Number of positions closed"}}}}}},"400":{"description":"Invalid request - deployment must be stopped or credentials missing","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Deployment not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v2/deployment/{id}/logs":{"get":{"tags":["DeploymentV2"],"summary":"Get deployment logs","description":"Retrieves logs from Cloud Logging for a specific deployment. Supports pagination with pageSize and pageToken query parameters.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Deployment ID"},{"name":"pageSize","in":"query","schema":{"type":"number","default":100},"description":"Number of log entries to return"},{"name":"pageToken","in":"query","schema":{"type":"string"},"description":"Token for pagination"}],"responses":{"200":{"description":"Deployment logs","content":{"application/json":{"schema":{"type":"object","properties":{"deployment_id":{"type":"string"},"items":{"type":"array","items":{"type":"object","properties":{"timestamp":{"type":"string","description":"Log timestamp"},"message":{"type":"string","description":"Log message"},"severity":{"type":"string","description":"Log severity level"}}}},"nextCursor":{"type":"string","nullable":true}}}}}},"404":{"description":"Deployment not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v2/portfolio/hyperliquid/deposit":{"post":{"tags":["PortfolioV2"],"summary":"Deposit Arbitrum USDC to Hyperliquid","description":"Transfers native USDC from the authenticated user's trading wallet on Arbitrum One to the Hyperliquid Bridge2 contract. Only native Arbitrum USDC is supported.","security":[{"ApiKeyAuth":[]},{"BearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["chain","asset_address","amount"],"properties":{"chain":{"type":"string","description":"Arbitrum One chain alias or chain ID. Supported values include arbitrum, arbitrum_one, arbitrum-one, and 42161.","example":"arbitrum"},"asset_address":{"type":"string","description":"Native USDC token address on Arbitrum One.","example":"0xaf88d065e77c8cC2239327C5EDb3A432268e5831"},"amount":{"type":"string","description":"USDC amount as a decimal string. Minimum deposit is 5 USDC and precision is limited to 6 decimals.","example":"5"},"from":{"type":"string","description":"Optional source wallet address. Must be one of the authenticated user's trading wallets. When omitted, the default main trading wallet is used.","example":"0x11223344556677889900aabbccddeeff11223344"}}}}}},"responses":{"200":{"description":"Deposit transaction submitted","content":{"application/json":{"schema":{"type":"object","properties":{"tx_hash":{"type":"string","description":"Arbitrum transaction hash"},"chain":{"type":"string","example":"arbitrum"},"asset_address":{"type":"string","example":"0xaf88d065e77c8cC2239327C5EDb3A432268e5831"},"amount":{"type":"string","example":"5"},"bridge_address":{"type":"string","example":"0x2df1c51e09aecf9cacb7bc98cb1742757f163df7"},"wallet_address":{"type":"string","description":"Source wallet address"}}}}}},"400":{"description":"Invalid request, unsupported chain/asset, no credentials, or insufficient USDC balance","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Server misconfigured","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Deposit transaction failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v2/portfolio/hyperliquid/exit":{"post":{"tags":["PortfolioV2"],"summary":"Close all positions and cancel orders","description":"Closes all open orders and closes all open positions using market orders for the Hyperliquid account. When a sub-account is specified, all funds are transferred back to the main account after closing.","security":[{"ApiKeyAuth":[]},{"BearerAuth":[]}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"subaccount_address":{"type":"string","description":"Sub-account address to close positions for. If omitted, closes the main account."}}}}}},"responses":{"200":{"description":"Positions closed and orders cancelled","content":{"application/json":{"schema":{"type":"object","properties":{"orders_cancelled":{"type":"number","description":"Number of orders cancelled"},"positions_closed":{"type":"number","description":"Number of positions closed"},"transferred_to_main":{"type":"number","description":"USDC transferred back to main account (only present when subAccountAddress is provided)"}}}}}},"400":{"description":"Invalid request or no credentials","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Hyperliquid error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v2/authorize-and-send/hyperliquid":{"post":{"tags":["HyperliquidProxy"],"summary":"Authorize and send Hyperliquid action","description":"Accepts a whitelisted Hyperliquid action, signs it with the authenticated user's main wallet private key, and forwards it to the Hyperliquid exchange API. Supported action types: createSubAccount, subAccountModify, subAccountTransfer, sendAsset, userSetAbstraction.","security":[{"ApiKeyAuth":[]},{"BearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["action"],"properties":{"action":{"type":"object","required":["type"],"properties":{"type":{"type":"string","enum":["createSubAccount","subAccountModify","subAccountTransfer","sendAsset","userSetAbstraction"],"description":"The Hyperliquid action type to execute"}},"description":"Action object. Additional parameters depend on the action type."}}},"examples":{"createSubAccount":{"summary":"Create a sub-account","value":{"action":{"type":"createSubAccount","name":"my-bot"}}},"subAccountModify":{"summary":"Rename a sub-account","value":{"action":{"type":"subAccountModify","subAccountUser":"0x...","name":"new-name"}}},"subAccountTransfer":{"summary":"Transfer to/from sub-account","value":{"action":{"type":"subAccountTransfer","subAccountUser":"0x...","isDeposit":true,"usd":1000000}}},"sendAsset":{"summary":"Send asset between accounts","value":{"action":{"type":"sendAsset","destination":"0x...","sourceDex":"spot","destinationDex":"spot","token":"USDC","amount":"100"}}},"userSetAbstraction":{"summary":"Set account abstraction mode","value":{"action":{"type":"userSetAbstraction","user":"0x...","abstraction":"unifiedAccount"}}}}}}},"responses":{"200":{"description":"Action executed successfully. Response body is the raw Hyperliquid API response.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","example":"ok"}}}}}},"400":{"description":"Invalid request - unknown action type, missing params, or no credentials","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"invalid_json":{"summary":"Invalid JSON body","value":{"error":"invalid_json","message":"Invalid JSON in request body"}},"validation_failed":{"summary":"Validation failed","value":{"error":"validation_failed","message":"Invalid request","details":[{"path":"action.type","message":"Invalid enum value"}]}},"no_credentials":{"summary":"No Hyperliquid wallet","value":{"error":"no_credentials","message":"No Hyperliquid wallet found for your account."}}}}}},"502":{"description":"Hyperliquid API error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":"hyperliquid_error","message":"Hyperliquid API request failed"}}}}}}},"/v2/deployment-history":{"get":{"tags":["DeploymentV2"],"summary":"List deployment history","description":"Retrieves a paginated list of deployment history records. Each record captures the trading session data (PnL, fills) from when a deployment was started until it was stopped or deleted. Filter by wallet_address or deployment_id.","parameters":[{"name":"wallet_address","in":"query","required":false,"schema":{"type":"string"},"description":"Filter by wallet or subaccount address"},{"name":"deployment_id","in":"query","required":false,"schema":{"type":"string"},"description":"Filter by deployment ID"}],"responses":{"200":{"description":"List of deployment history records with pagination","content":{"application/json":{"schema":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/DeploymentHistory"}},"next_cursor":{"type":"string","nullable":true}}}}}},"401":{"description":"Authentication required"},"503":{"description":"Deployment history is not available (database not configured)"}}}},"/v2/deployments/{id}/credentials":{"post":{"tags":["DeploymentV2"],"summary":"Add exchange credentials via Privy","description":"Add exchange credentials via Privy. In v2, private_key is not accepted - credentials are fetched from Privy. If wallet_address is omitted, uses the user's main trading wallet (first exportable wallet in their Privy account).","security":[{"ApiKeyAuth":[]},{"BearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Deployment ID"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["exchange"],"properties":{"exchange":{"type":"string","description":"Exchange name","enum":["hyperliquid","aerodrome","binance"]},"wallet_address":{"type":"string","description":"Wallet address for wallet-based exchanges. If omitted for Hyperliquid or Aerodrome, uses the user's main trading wallet from Privy."},"subaccount_address":{"type":"string","description":"Hyperliquid subaccount address (optional, only for Hyperliquid; must be a valid Ethereum address if provided)."},"api_key":{"type":"string","description":"API key for API-key exchanges (Binance)"},"api_secret":{"type":"string","description":"API secret for API-key exchanges (Binance)"}}},"examples":{"hyperliquidMainTradingWallet":{"summary":"Hyperliquid main trading wallet","value":{"exchange":"hyperliquid"}},"hyperliquidProvidedWallet":{"summary":"Hyperliquid provided wallet (must be in trading-accounts list)","value":{"exchange":"hyperliquid","wallet_address":"0x742d35Cc6634C0532925a3b844Bc454e4438f44e"}},"hyperliquidSubaccount":{"summary":"Hyperliquid subaccount","value":{"exchange":"hyperliquid","subaccount_address":"0x1111111111111111111111111111111111111111"}},"aerodrome":{"summary":"Aerodrome main trading wallet","value":{"exchange":"aerodrome"}},"binance":{"summary":"Binance API key credentials","value":{"exchange":"binance","api_key":"BINANCE_API_KEY","api_secret":"BINANCE_API_SECRET"}}}}}},"responses":{"200":{"description":"Credentials stored successfully","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"credentials_status":{"type":"string","example":"stored"},"exchange":{"type":"string"},"wallet_address":{"type":"string","description":"The wallet address used"},"wallet_source":{"type":"string","enum":["provided","main_trading_wallet"],"description":"Whether the wallet was provided in the request or auto-selected from Privy"},"subaccount_address":{"type":"string","nullable":true,"description":"Hyperliquid subaccount address if configured (Hyperliquid only)"},"updated_at":{"type":"string","format":"date-time"}}}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"invalid_request":{"summary":"Private key provided (not allowed in v2)","value":{"error":"invalid_request","message":"private_key is not accepted in v2 - credentials are fetched from Privy"}},"no_wallet_available":{"summary":"No wallet available","value":{"error":"no_wallet_available","message":"No exportable wallet found in your Privy account"}},"duplicate_wallet_address":{"summary":"Duplicate wallet address or subaccount","value":{"error":"duplicate_wallet_address","message":"This wallet address or subaccount is already used by another deployment"}},"invalid_wallet_address":{"summary":"Invalid wallet address","value":{"error":"invalid_wallet_address","message":"Invalid wallet address format"}},"invalid_subaccount_address":{"summary":"Invalid subaccount address","value":{"error":"invalid_subaccount_address","message":"Invalid Ethereum subaccount address format"}}}}}},"403":{"description":"Wallet not owned by user","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"wallet_not_owned":{"summary":"Wallet not owned","value":{"error":"wallet_not_owned","message":"The provided wallet address is not owned by your account"}},"subaccount_not_owned":{"summary":"Subaccount not owned","value":{"error":"subaccount_not_owned","message":"This subaccount does not belong to you"}}}}}},"404":{"description":"Deployment not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}}}