{"openapi":"3.0.0","paths":{"/health":{"get":{"operationId":"HealthController_check","parameters":[],"responses":{"200":{"description":""}},"summary":"Liveness probe — returns 200 if the API process is alive.","tags":["health"]}},"/v1/auth/register":{"post":{"operationId":"IdentityController_register","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RegisterDto"}}}},"responses":{"201":{"description":"Session cookie set; returns {user, tenant_id}."},"409":{"description":"Email already in use for this tenant."}},"summary":"Register a new user within a tenant.","tags":["identity"]}},"/v1/auth/login":{"post":{"operationId":"IdentityController_login","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoginDto"}}}},"responses":{"200":{"description":"Session cookie set; returns {user, tenant_id}."},"401":{"description":"Invalid credentials or TOTP."}},"summary":"Log in with email + password (+ TOTP if enrolled).","tags":["identity"]}},"/v1/auth/email/verify":{"post":{"operationId":"IdentityController_verifyEmail","parameters":[],"responses":{"200":{"description":""}},"summary":"Consume an email-verification token.","tags":["identity"]}},"/v1/auth/email/resend":{"post":{"operationId":"IdentityController_resendVerification","parameters":[],"responses":{"200":{"description":""}},"security":[{"session":[]}],"summary":"Resend the email-verification link to the current user.","tags":["identity"]}},"/v1/auth/password/forgot":{"post":{"operationId":"IdentityController_forgotPassword","parameters":[],"responses":{"200":{"description":""}},"summary":"Request a password-reset email. Always returns 200 to prevent enumeration.","tags":["identity"]}},"/v1/auth/password/reset":{"post":{"operationId":"IdentityController_resetPassword","parameters":[],"responses":{"200":{"description":""}},"summary":"Consume a password-reset token and set a new password.","tags":["identity"]}},"/v1/auth/logout":{"post":{"operationId":"IdentityController_logout","parameters":[],"responses":{"204":{"description":""}},"summary":"Log out and revoke the current session.","tags":["identity"]}},"/v1/auth/me":{"get":{"operationId":"IdentityController_me","parameters":[],"responses":{"200":{"description":""}},"security":[{"session":[]}],"summary":"Return the currently authenticated user + tenant.","tags":["identity"]}},"/v1/auth/sessions":{"get":{"operationId":"IdentityController_listSessions","parameters":[],"responses":{"200":{"description":""}},"security":[{"session":[]}],"summary":"List active sessions (devices) for the current user.","tags":["identity"]}},"/v1/auth/sessions/{id}":{"delete":{"operationId":"IdentityController_revokeSession","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"204":{"description":""}},"security":[{"session":[]}],"summary":"Revoke a specific session by id.","tags":["identity"]}},"/v1/auth/sessions/revoke-all":{"post":{"operationId":"IdentityController_revokeAll","parameters":[],"responses":{"200":{"description":""}},"security":[{"session":[]}],"summary":"Revoke all sessions except the current one (log out everywhere).","tags":["identity"]}},"/v1/auth/totp/enroll":{"post":{"operationId":"IdentityController_enrollTotp","parameters":[],"responses":{"201":{"description":""}},"security":[{"session":[]}],"summary":"Begin TOTP enrollment. Returns a provisioning URI for authenticator apps.","tags":["identity"]}},"/v1/auth/totp/verify":{"post":{"operationId":"IdentityController_verifyTotp","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnableTotpDto"}}}},"responses":{"204":{"description":""}},"security":[{"session":[]}],"summary":"Confirm TOTP enrollment by submitting a valid code.","tags":["identity"]}},"/v1/ai/health":{"get":{"operationId":"AiController_health","parameters":[],"responses":{"200":{"description":""}},"security":[{"session":[]}],"summary":"Liveness check for the local AI runtime.","tags":["ai"]}},"/v1/ai/kyc-summary":{"post":{"operationId":"AiController_kycSummary","parameters":[],"responses":{"200":{"description":""}},"security":[{"session":[]}],"summary":"AI-generated 2-sentence KYC reviewer summary from a doc analysis result.","tags":["ai"]}},"/v1/ai/classify-intent":{"post":{"operationId":"AiController_classifyIntent","parameters":[],"responses":{"200":{"description":""}},"security":[{"session":[]}],"summary":"Classify a support-ticket message into one of the 11 intent buckets.","tags":["ai"]}},"/v1/ai/draft-reply":{"post":{"operationId":"AiController_draftReply","parameters":[],"responses":{"200":{"description":""}},"security":[{"session":[]}],"summary":"Draft a polite operator reply to a support ticket.","tags":["ai"]}},"/v1/ai/fraud-explain":{"post":{"operationId":"AiController_fraudExplain","parameters":[],"responses":{"200":{"description":""}},"security":[{"session":[]}],"summary":"Explain why a deposit was flagged + recommend an action.","tags":["ai"]}},"/v1/ai/sales-coach":{"post":{"operationId":"AiController_salesCoach","parameters":[],"responses":{"200":{"description":""}},"security":[{"session":[]}],"summary":"Recommend the best next sales action for a trader.","tags":["ai"]}},"/v1/intelligence/leads/scored":{"get":{"operationId":"IntelligenceController_scoredLeads","parameters":[{"name":"limit","required":true,"in":"query","schema":{"type":"string"}},{"name":"tier","required":true,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"security":[{"session":[]}],"summary":"Top-N scored leads + traders ready to convert. Score 0-100.","tags":["intelligence"]}},"/v1/intelligence/leads/rescore":{"post":{"operationId":"IntelligenceController_rescoreLeads","parameters":[],"responses":{"200":{"description":""}},"security":[{"session":[]}],"summary":"Force re-score all traders for this tenant (normally runs nightly).","tags":["intelligence"]}},"/v1/intelligence/fraud/deposits":{"get":{"operationId":"IntelligenceController_fraudDeposits","parameters":[{"name":"threshold","required":true,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"security":[{"session":[]}],"summary":"High-fraud-score deposits for admin review.","tags":["intelligence"]}},"/v1/intelligence/fraud/rescan":{"post":{"operationId":"IntelligenceController_rescanFraud","parameters":[],"responses":{"200":{"description":""}},"security":[{"session":[]}],"summary":"Re-scan recent deposits for fraud anomalies (normally runs per-deposit).","tags":["intelligence"]}},"/v1/intelligence/churn/at-risk":{"get":{"operationId":"IntelligenceController_churnRisk","parameters":[],"responses":{"200":{"description":""}},"security":[{"session":[]}],"summary":"Traders predicted likely to churn (weighted signal model).","tags":["intelligence"]}},"/v1/intelligence/next-actions/{userId}":{"get":{"operationId":"IntelligenceController_nextActions","parameters":[{"name":"userId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"security":[{"session":[]}],"summary":"Best-next-action recommendations for a specific sales operator.","tags":["intelligence"]}},"/v1/intelligence/deposits/{id}/fraud-score":{"get":{"operationId":"IntelligenceController_depositFraud","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"security":[{"session":[]}],"summary":"Detailed fraud breakdown for one deposit.","tags":["intelligence"]}},"/v1/public/status":{"get":{"operationId":"EnterpriseController_publicStatus","parameters":[],"responses":{"200":{"description":""}},"summary":"Public status page data — latest incidents + component state.","tags":["enterprise"]}},"/v1/public/changelog":{"get":{"operationId":"EnterpriseController_publicChangelog","parameters":[],"responses":{"200":{"description":""}},"summary":"Public changelog — auto-generated from MetaModule + git tags.","tags":["enterprise"]}},"/v1/admin/status-incidents":{"post":{"operationId":"EnterpriseController_createIncident","parameters":[],"responses":{"201":{"description":""}},"security":[{"session":[]}],"tags":["enterprise"]}},"/v1/admin/status-incidents/{id}":{"patch":{"operationId":"EnterpriseController_updateIncident","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"security":[{"session":[]}],"tags":["enterprise"]}},"/v1/admin/siem/forwarders":{"get":{"operationId":"EnterpriseController_listForwarders","parameters":[],"responses":{"200":{"description":""}},"security":[{"session":[]}],"tags":["enterprise"]},"post":{"operationId":"EnterpriseController_createForwarder","parameters":[],"responses":{"201":{"description":""}},"security":[{"session":[]}],"tags":["enterprise"]}},"/v1/admin/siem/forwarders/{id}":{"delete":{"operationId":"EnterpriseController_deleteForwarder","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"security":[{"session":[]}],"tags":["enterprise"]}},"/v1/admin/siem/export-now":{"post":{"operationId":"EnterpriseController_exportSiemNow","parameters":[],"responses":{"201":{"description":""}},"security":[{"session":[]}],"summary":"Trigger SIEM export immediately (normally runs every 5 min from worker).","tags":["enterprise"]}},"/v1/admin/saved-views":{"get":{"operationId":"EnterpriseController_listViews","parameters":[{"name":"resource","required":true,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"security":[{"session":[]}],"tags":["enterprise"]},"post":{"operationId":"EnterpriseController_createView","parameters":[],"responses":{"201":{"description":""}},"security":[{"session":[]}],"tags":["enterprise"]}},"/v1/admin/saved-views/{id}":{"patch":{"operationId":"EnterpriseController_updateView","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"security":[{"session":[]}],"tags":["enterprise"]},"delete":{"operationId":"EnterpriseController_deleteView","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"security":[{"session":[]}],"tags":["enterprise"]}},"/v1/users/me/theme":{"get":{"operationId":"EnterpriseController_getTheme","parameters":[],"responses":{"200":{"description":""}},"security":[{"session":[]}],"tags":["enterprise"]},"patch":{"operationId":"EnterpriseController_setTheme","parameters":[],"responses":{"200":{"description":""}},"security":[{"session":[]}],"tags":["enterprise"]}},"/v1/admin/search":{"get":{"operationId":"EnterpriseController_globalSearch","parameters":[{"name":"q","required":true,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"security":[{"session":[]}],"summary":"Cmd-K global search across traders, deposits, withdrawals, tickets, leads, accounts.","tags":["enterprise"]}},"/v1/traders/me":{"get":{"operationId":"TradersController_me","parameters":[],"responses":{"200":{"description":""}},"security":[{"session":[]}],"summary":"Return the trader row linked to the current session user (portal).","tags":["traders"]}},"/v1/traders/me/accounts":{"get":{"operationId":"TradersController_myAccounts","parameters":[],"responses":{"200":{"description":""}},"security":[{"session":[]}],"tags":["traders"]}},"/v1/traders/me/export":{"get":{"operationId":"TradersController_myExport","parameters":[],"responses":{"200":{"description":""}},"security":[{"session":[]}],"tags":["traders"]}},"/v1/traders/me/referrals":{"get":{"operationId":"TradersController_myReferrals","parameters":[],"responses":{"200":{"description":""}},"security":[{"session":[]}],"tags":["traders"]}},"/v1/traders/me/notifications":{"get":{"operationId":"TradersController_myNotifications","parameters":[],"responses":{"200":{"description":""}},"security":[{"session":[]}],"tags":["traders"]}},"/v1/traders/me/accounts/{id}/auto-login":{"post":{"operationId":"TradersController_myAccountAutoLogin","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"security":[{"session":[]}],"tags":["traders"]}},"/v1/traders/me/transactions":{"get":{"operationId":"TradersController_myTransactions","parameters":[],"responses":{"200":{"description":""}},"security":[{"session":[]}],"tags":["traders"]}},"/v1/traders/me/positions":{"get":{"operationId":"TradersController_myPositions","parameters":[],"responses":{"200":{"description":""}},"security":[{"session":[]}],"tags":["traders"]}},"/v1/traders":{"get":{"operationId":"TradersController_list","parameters":[],"responses":{"200":{"description":""}},"security":[{"session":[]}],"summary":"List traders for the current tenant (cursor-paginated).","tags":["traders"]},"post":{"operationId":"TradersController_create","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateTraderDto"}}}},"responses":{"201":{"description":""},"409":{"description":"Email already in use for this tenant."}},"security":[{"session":[]}],"summary":"Create a new trader in the current tenant.","tags":["traders"]}},"/v1/traders/me/accept-terms":{"post":{"operationId":"TradersController_acceptTerms","parameters":[],"responses":{"200":{"description":""}},"security":[{"session":[]}],"summary":"Trader confirms they have read the current terms/privacy policy (portal).","tags":["traders"]}},"/v1/traders/{id}":{"get":{"operationId":"TradersController_get","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""},"404":{"description":""}},"security":[{"session":[]}],"summary":"Get a trader by id.","tags":["traders"]},"patch":{"operationId":"TradersController_update","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateTraderDto"}}}},"responses":{"200":{"description":""}},"security":[{"session":[]}],"summary":"Update trader fields (partial).","tags":["traders"]},"delete":{"operationId":"TradersController_remove","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"204":{"description":""}},"security":[{"session":[]}],"summary":"Soft-delete a trader.","tags":["traders"]}},"/v1/traders/{id}/segments":{"patch":{"operationId":"TradersController_patchSegments","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SegmentsPatchDto"}}}},"responses":{"200":{"description":""}},"security":[{"session":[]}],"summary":"Add / remove segment tags on a trader.","tags":["traders"]}},"/v1/traders/me/profile":{"patch":{"operationId":"TradersExtController_editProfile","parameters":[],"responses":{"200":{"description":""}},"security":[{"session":[]}],"summary":"Trader self-service profile edit (P3). Limited fields + re-trigger KYC on sensitive change.","tags":["traders"]}},"/v1/traders/me/withdrawal-allowlist":{"get":{"operationId":"TradersExtController_getAllowlist","parameters":[],"responses":{"200":{"description":""}},"security":[{"session":[]}],"summary":"Trader crypto withdrawal address allowlist (P6).","tags":["traders"]},"post":{"operationId":"TradersExtController_addAllowlistAddress","parameters":[],"responses":{"200":{"description":""}},"security":[{"session":[]}],"summary":"Append an address to the allowlist (P6). Locks for 24h then becomes active.","tags":["traders"]}},"/v1/traders/me/timeline":{"get":{"operationId":"TradersExtController_timeline","parameters":[],"responses":{"200":{"description":""}},"security":[{"session":[]}],"summary":"Trader activity timeline: deposits + kyc + tickets + logins merged (P2).","tags":["traders"]}},"/v1/kyc/uploads":{"post":{"operationId":"KycController_requestUpload","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestKycUploadDto"}}}},"responses":{"201":{"description":""}},"security":[{"session":[]}],"summary":"Request a presigned upload URL for a KYC document.","tags":["kyc"]}},"/v1/kyc/uploads/confirm":{"post":{"operationId":"KycController_confirmUpload","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConfirmKycUploadDto"}}}},"responses":{"200":{"description":""}},"security":[{"session":[]}],"summary":"Mark a KYC document as uploaded and enqueue it for analysis.","tags":["kyc"]}},"/v1/kyc/traders/{traderId}":{"get":{"operationId":"KycController_summary","parameters":[{"name":"traderId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"security":[{"session":[]}],"summary":"KYC summary: status + documents (with presigned preview URLs + analysis) + sanctions hits.","tags":["kyc"]}},"/v1/kyc/pending":{"get":{"operationId":"KycController_pending","parameters":[{"name":"limit","required":true,"in":"query","schema":{"type":"string"}},{"name":"cursor","required":true,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"security":[{"session":[]}],"summary":"List traders waiting for KYC review.","tags":["kyc"]}},"/v1/kyc/submit":{"post":{"operationId":"KycController_submit","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubmitKycDto"}}}},"responses":{"200":{"description":""}},"security":[{"session":[]}],"summary":"Submit a trader for KYC review. Also triggers sanctions screening.","tags":["kyc"]}},"/v1/kyc/approve":{"post":{"operationId":"KycController_approve","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApproveKycDto"}}}},"responses":{"200":{"description":""}},"security":[{"session":[]}],"summary":"Approve a trader KYC.","tags":["kyc"]}},"/v1/kyc/reject":{"post":{"operationId":"KycController_reject","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RejectKycDto"}}}},"responses":{"200":{"description":""}},"security":[{"session":[]}],"summary":"Reject a trader KYC with a reason.","tags":["kyc"]}},"/v1/kyc/request-more-info":{"post":{"operationId":"KycController_requestMoreInfo","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestMoreInfoKycDto"}}}},"responses":{"200":{"description":""}},"security":[{"session":[]}],"summary":"Ask the trader for extra documents; moves KYC back to in_progress.","tags":["kyc"]}},"/v1/kyc/sanctions/{hitId}/review":{"post":{"operationId":"KycController_reviewSanctions","parameters":[{"name":"hitId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"security":[{"session":[]}],"summary":"Mark a sanctions hit as cleared (false positive) or confirmed (true match).","tags":["kyc"]}},"/v1/kyc/webhooks/sumsub":{"post":{"operationId":"SumsubController_handle","parameters":[],"responses":{"204":{"description":""}},"summary":"Sumsub event webhook (HMAC-verified when SUMSUB_WEBHOOK_SECRET set).","tags":["kyc"]}},"/v1/kyc/documents/{id}/liveness":{"post":{"operationId":"KycLivenessController_setLiveness","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"security":[{"session":[]}],"summary":"K5: Submit liveness-check score (client-side blink/head-turn detection result).","tags":["kyc"]}},"/v1/accounts":{"get":{"operationId":"AccountsController_list","parameters":[],"responses":{"200":{"description":""}},"security":[{"session":[]}],"summary":"List trading accounts (cursor-paginated).","tags":["accounts"]},"post":{"operationId":"AccountsController_create","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateAccountDto"}}}},"responses":{"201":{"description":""}},"security":[{"session":[]}],"summary":"Create / link a trading account for a trader.","tags":["accounts"]}},"/v1/accounts/{id}":{"get":{"operationId":"AccountsController_get","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"security":[{"session":[]}],"tags":["accounts"]},"patch":{"operationId":"AccountsController_update","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateAccountDto"}}}},"responses":{"200":{"description":""}},"security":[{"session":[]}],"tags":["accounts"]},"delete":{"operationId":"AccountsController_remove","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"204":{"description":""}},"security":[{"session":[]}],"tags":["accounts"]}},"/v1/transactions":{"get":{"operationId":"TransactionsController_list","parameters":[],"responses":{"200":{"description":""}},"security":[{"session":[]}],"summary":"List transactions with filters (cursor-paginated).","tags":["transactions"]},"post":{"operationId":"TransactionsController_create","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateTransactionDto"}}}},"responses":{"201":{"description":""}},"security":[{"session":[]}],"summary":"Record a transaction.","tags":["transactions"]}},"/v1/transactions/export.csv":{"get":{"operationId":"TransactionsController_exportCsv","parameters":[],"responses":{"200":{"description":""}},"security":[{"session":[]}],"summary":"Export filtered transactions as CSV (max 10k rows).","tags":["transactions"]}},"/v1/communications/templates":{"get":{"operationId":"CommunicationsController_listTemplates","parameters":[],"responses":{"200":{"description":""}},"security":[{"session":[]}],"summary":"List communication templates.","tags":["communications"]},"post":{"operationId":"CommunicationsController_createTemplate","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateTemplateDto"}}}},"responses":{"201":{"description":""}},"security":[{"session":[]}],"tags":["communications"]}},"/v1/communications/templates/{id}":{"patch":{"operationId":"CommunicationsController_updateTemplate","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateTemplateDto"}}}},"responses":{"200":{"description":""}},"security":[{"session":[]}],"tags":["communications"]},"get":{"operationId":"CommunicationsController_getTemplate","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"security":[{"session":[]}],"tags":["communications"]}},"/v1/communications/send":{"post":{"operationId":"CommunicationsController_send","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendMessageDto"}}}},"responses":{"202":{"description":""}},"security":[{"session":[]}],"summary":"Queue a message to send (template or ad-hoc).","tags":["communications"]}},"/v1/communications/sends":{"get":{"operationId":"CommunicationsController_listSends","parameters":[],"responses":{"200":{"description":""}},"security":[{"session":[]}],"tags":["communications"]}},"/v1/communications/dispatch-queued":{"post":{"operationId":"CommunicationsController_dispatchQueued","parameters":[],"responses":{"200":{"description":""}},"security":[{"session":[]}],"summary":"Admin-only: force-dispatch every queued CommunicationSend for the current tenant. Useful after swapping MAIL_HOST / RESEND_API_KEY / TWILIO_* credentials.","tags":["communications"]}},"/v1/affiliates":{"get":{"operationId":"AffiliatesController_list","parameters":[],"responses":{"200":{"description":""}},"security":[{"session":[]}],"tags":["affiliates"]},"post":{"operationId":"AffiliatesController_create","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateAffiliateDto"}}}},"responses":{"201":{"description":""}},"security":[{"session":[]}],"tags":["affiliates"]}},"/v1/affiliates/tree/{rootId}":{"get":{"operationId":"AffiliatesController_tree","parameters":[{"name":"rootId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"security":[{"session":[]}],"summary":"Return the subtree rooted at rootId (ULID).","tags":["affiliates"]}},"/v1/affiliates/rules":{"get":{"operationId":"AffiliatesController_listRules","parameters":[],"responses":{"200":{"description":""}},"security":[{"session":[]}],"tags":["affiliates"]},"post":{"operationId":"AffiliatesController_createRule","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateRebateRuleDto"}}}},"responses":{"201":{"description":""}},"security":[{"session":[]}],"tags":["affiliates"]}},"/v1/affiliates/commissions":{"get":{"operationId":"AffiliatesController_listCommissions","parameters":[],"responses":{"200":{"description":""}},"security":[{"session":[]}],"tags":["affiliates"]}},"/v1/affiliates/tree":{"get":{"operationId":"AffiliatesExtController_tree","parameters":[],"responses":{"200":{"description":""}},"security":[{"session":[]}],"summary":"Sub-affiliate tree from the current session user's primary affiliate (I2).","tags":["affiliates"]}},"/v1/affiliates/commissions/by-symbol":{"get":{"operationId":"AffiliatesExtController_commissionsBySymbol","parameters":[],"responses":{"200":{"description":""}},"security":[{"session":[]}],"summary":"Commission breakdown by symbol (I5) — derived from source trades metadata.","tags":["affiliates"]}},"/v1/affiliates/funnel":{"get":{"operationId":"AffiliatesExtController_funnel","parameters":[],"responses":{"200":{"description":""}},"security":[{"session":[]}],"summary":"Registration → KYC → first-deposit funnel over last 90 days (I6/R1).","tags":["affiliates"]}},"/v1/affiliates/payouts":{"post":{"operationId":"AffiliatesExtController_requestPayout","parameters":[],"responses":{"201":{"description":""}},"security":[{"session":[]}],"summary":"IB requests a commission payout (I3).","tags":["affiliates"]},"get":{"operationId":"AffiliatesExtController_listPayouts","parameters":[{"name":"status","required":true,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"security":[{"session":[]}],"summary":"List payout requests for this tenant (I3).","tags":["affiliates"]}},"/v1/affiliates/payouts/{id}/approve":{"post":{"operationId":"AffiliatesExtController_approvePayout","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"security":[{"session":[]}],"tags":["affiliates"]}},"/v1/affiliates/payouts/{id}/paid":{"post":{"operationId":"AffiliatesExtController_markPaid","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"security":[{"session":[]}],"tags":["affiliates"]}},"/v1/affiliates/clicks/track":{"post":{"operationId":"AffiliatesExtController_trackClick","parameters":[],"responses":{"204":{"description":""}},"security":[{"session":[]}],"summary":"Affiliate click-tracking pixel (I7). Public endpoint, no auth.","tags":["affiliates"]}},"/v1/payments/methods":{"get":{"operationId":"PaymentsController_listMethods","parameters":[{"name":"traderId","required":true,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"security":[{"session":[]}],"tags":["payments"]},"post":{"operationId":"PaymentsController_createMethod","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatePaymentMethodDto"}}}},"responses":{"201":{"description":""}},"security":[{"session":[]}],"tags":["payments"]}},"/v1/payments/deposits":{"get":{"operationId":"PaymentsController_listDeposits","parameters":[],"responses":{"200":{"description":""}},"security":[{"session":[]}],"tags":["payments"]},"post":{"operationId":"PaymentsController_createDeposit","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateDepositDto"}}}},"responses":{"201":{"description":""}},"security":[{"session":[]}],"tags":["payments"]}},"/v1/payments/deposits/approve":{"post":{"operationId":"PaymentsController_approveDeposit","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApprovePaymentDto"}}}},"responses":{"200":{"description":""}},"security":[{"session":[]}],"summary":"Approve a deposit awaiting review.","tags":["payments"]}},"/v1/payments/deposits/bulk-approve":{"post":{"operationId":"PaymentsController_bulkApproveDeposits","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkApprovePaymentsDto"}}}},"responses":{"200":{"description":""}},"security":[{"session":[]}],"summary":"Approve up to 50 deposits in one call.","tags":["payments"]}},"/v1/payments/deposits/reject":{"post":{"operationId":"PaymentsController_rejectDeposit","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RejectPaymentDto"}}}},"responses":{"200":{"description":""}},"security":[{"session":[]}],"tags":["payments"]}},"/v1/payments/deposits/settle":{"post":{"operationId":"PaymentsController_settleDeposit","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SettlePaymentDto"}}}},"responses":{"200":{"description":""}},"security":[{"session":[]}],"summary":"Manually settle an approved deposit with optional fee/net/settle-date/proof.","tags":["payments"]}},"/v1/payments/deposits/reconcile":{"post":{"operationId":"PaymentsController_reconcileDeposit","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReconcilePaymentDto"}}}},"responses":{"200":{"description":""}},"security":[{"session":[]}],"summary":"Flag a deposit as reconciled / un-reconciled against external statements.","tags":["payments"]}},"/v1/payments/deposits/reverse":{"post":{"operationId":"PaymentsController_reverseDeposit","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReversePaymentDto"}}}},"responses":{"200":{"description":""}},"security":[{"session":[]}],"summary":"Reverse a settled deposit (chargeback, NSF wire, fraud). Flips commissions to reversed.","tags":["payments"]}},"/v1/payments/withdrawals":{"get":{"operationId":"PaymentsController_listWithdrawals","parameters":[],"responses":{"200":{"description":""}},"security":[{"session":[]}],"tags":["payments"]},"post":{"operationId":"PaymentsController_createWithdrawal","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateWithdrawalDto"}}}},"responses":{"201":{"description":""}},"security":[{"session":[]}],"tags":["payments"]}},"/v1/payments/withdrawals/approve":{"post":{"operationId":"PaymentsController_approveWithdrawal","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApprovePaymentDto"}}}},"responses":{"200":{"description":""}},"security":[{"session":[]}],"tags":["payments"]}},"/v1/payments/withdrawals/bulk-approve":{"post":{"operationId":"PaymentsController_bulkApproveWithdrawals","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkApprovePaymentsDto"}}}},"responses":{"200":{"description":""}},"security":[{"session":[]}],"summary":"Approve up to 50 withdrawals in one call.","tags":["payments"]}},"/v1/payments/withdrawals/reject":{"post":{"operationId":"PaymentsController_rejectWithdrawal","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RejectPaymentDto"}}}},"responses":{"200":{"description":""}},"security":[{"session":[]}],"tags":["payments"]}},"/v1/payments/withdrawals/settle":{"post":{"operationId":"PaymentsController_settleWithdrawal","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SettlePaymentDto"}}}},"responses":{"200":{"description":""}},"security":[{"session":[]}],"summary":"Mark an approved withdrawal as settled with optional settle-date / proof.","tags":["payments"]}},"/v1/payments/withdrawals/reconcile":{"post":{"operationId":"PaymentsController_reconcileWithdrawal","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReconcilePaymentDto"}}}},"responses":{"200":{"description":""}},"security":[{"session":[]}],"summary":"Flag a withdrawal as reconciled / un-reconciled against external statements.","tags":["payments"]}},"/v1/payments/deposits/export.csv":{"get":{"operationId":"PaymentsController_exportDeposits","parameters":[],"responses":{"200":{"description":""}},"security":[{"session":[]}],"summary":"Export deposits to CSV (filters match GET /deposits). Max 10,000 rows.","tags":["payments"]}},"/v1/payments/withdrawals/export.csv":{"get":{"operationId":"PaymentsController_exportWithdrawals","parameters":[],"responses":{"200":{"description":""}},"security":[{"session":[]}],"summary":"Export withdrawals to CSV (filters match GET /withdrawals). Max 10,000 rows.","tags":["payments"]}},"/v1/payments/reconciliation":{"get":{"operationId":"PaymentsController_reconciliation","parameters":[{"name":"from","required":true,"in":"query","schema":{"type":"string"}},{"name":"to","required":true,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"security":[{"session":[]}],"tags":["payments"]}},"/v1/payments/webhooks/stripe":{"post":{"operationId":"StripeWebhookController_handle","parameters":[],"responses":{"204":{"description":""}},"summary":"Stripe webhook receiver (signature-verified).","tags":["payments"]}},"/v1/payments/deposits/{id}/invoice.pdf":{"get":{"operationId":"InvoicePdfController_invoicePdf","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"security":[{"session":[]}],"summary":"M5: Invoice PDF for a settled deposit. Uses pdfkit for tables + branding.","tags":["payments"]}},"/v1/payments/traders/{traderId}/statement.pdf":{"get":{"operationId":"InvoicePdfController_statementPdf","parameters":[{"name":"traderId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"security":[{"session":[]}],"summary":"P4: Monthly statement PDF for a trader. Multi-table pdfkit layout.","tags":["payments"]}},"/v1/auth/passkeys":{"get":{"operationId":"WebauthnController_list","parameters":[],"responses":{"200":{"description":""}},"security":[{"session":[]}],"tags":["webauthn"]}},"/v1/auth/passkeys/register/start":{"post":{"operationId":"WebauthnController_registerStart","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StartRegDto"}}}},"responses":{"200":{"description":""}},"security":[{"session":[]}],"tags":["webauthn"]}},"/v1/auth/passkeys/register/finish":{"post":{"operationId":"WebauthnController_registerFinish","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FinishRegDto"}}}},"responses":{"200":{"description":""}},"security":[{"session":[]}],"tags":["webauthn"]}},"/v1/auth/passkeys/authenticate/start":{"post":{"operationId":"WebauthnController_authStart","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StartAuthDto"}}}},"responses":{"200":{"description":""}},"summary":"Begin passkey login — returns the challenge options the browser passes to navigator.credentials.get().","tags":["webauthn"]}},"/v1/auth/passkeys/authenticate/finish":{"post":{"operationId":"WebauthnController_authFinish","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FinishAuthDto"}}}},"responses":{"200":{"description":""}},"summary":"Complete passkey login — verifies the assertion + mints a session cookie identical to /auth/login.","tags":["webauthn"]}},"/v1/auth/passkeys/{id}":{"delete":{"operationId":"WebauthnController_revoke","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"204":{"description":""}},"security":[{"session":[]}],"tags":["webauthn"]}},"/v1/webhooks/subscriptions":{"get":{"operationId":"WebhooksController_listSubs","parameters":[],"responses":{"200":{"description":""}},"security":[{"session":[]}],"tags":["webhooks"]},"post":{"operationId":"WebhooksController_createSub","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateSubscriptionDto"}}}},"responses":{"201":{"description":""}},"security":[{"session":[]}],"tags":["webhooks"]}},"/v1/webhooks/subscriptions/{id}":{"delete":{"operationId":"WebhooksController_deleteSub","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"204":{"description":""}},"security":[{"session":[]}],"tags":["webhooks"]}},"/v1/webhooks/subscriptions/{id}/test":{"post":{"operationId":"WebhooksController_testSub","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"security":[{"session":[]}],"tags":["webhooks"]}},"/v1/webhooks/deliveries/{id}/retry":{"post":{"operationId":"WebhooksController_retryDelivery","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"security":[{"session":[]}],"tags":["webhooks"]}},"/v1/webhooks/deliveries":{"get":{"operationId":"WebhooksController_listDeliveries","parameters":[{"name":"subscriptionId","required":true,"in":"query","schema":{"type":"string"}},{"name":"limit","required":true,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"security":[{"session":[]}],"tags":["webhooks"]}},"/v1/sales/leads":{"get":{"operationId":"SalesController_listLeads","parameters":[],"responses":{"200":{"description":""}},"security":[{"session":[]}],"tags":["sales"]},"post":{"operationId":"SalesController_createLead","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateLeadDto"}}}},"responses":{"201":{"description":""}},"security":[{"session":[]}],"tags":["sales"]}},"/v1/sales/leads/{id}":{"get":{"operationId":"SalesController_getLead","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"security":[{"session":[]}],"tags":["sales"]},"patch":{"operationId":"SalesController_updateLead","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateLeadDto"}}}},"responses":{"200":{"description":""}},"security":[{"session":[]}],"tags":["sales"]}},"/v1/sales/leads/{id}/convert":{"post":{"operationId":"SalesController_convert","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"security":[{"session":[]}],"summary":"Convert a lead to a trader.","tags":["sales"]}},"/v1/sales/pipelines":{"get":{"operationId":"SalesController_listPipelines","parameters":[],"responses":{"200":{"description":""}},"security":[{"session":[]}],"tags":["sales"]},"post":{"operationId":"SalesController_createPipeline","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatePipelineDto"}}}},"responses":{"201":{"description":""}},"security":[{"session":[]}],"tags":["sales"]}},"/v1/sales/activities":{"get":{"operationId":"SalesController_listActivities","parameters":[{"name":"leadId","required":true,"in":"query","schema":{"type":"string"}},{"name":"traderId","required":true,"in":"query","schema":{"type":"string"}},{"name":"limit","required":true,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"security":[{"session":[]}],"tags":["sales"]},"post":{"operationId":"SalesController_createActivity","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateActivityDto"}}}},"responses":{"201":{"description":""}},"security":[{"session":[]}],"tags":["sales"]}},"/v1/integrations/configs":{"get":{"operationId":"IntegrationsController_listConfigs","parameters":[],"responses":{"200":{"description":""}},"security":[{"session":[]}],"tags":["integrations"]},"post":{"operationId":"IntegrationsController_upsert","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpsertConfigDto"}}}},"responses":{"200":{"description":""}},"security":[{"session":[]}],"summary":"Create or update the (tenant, platform) connector config.","tags":["integrations"]}},"/v1/integrations/configs/{platform}/test":{"post":{"operationId":"IntegrationsController_test","parameters":[{"name":"platform","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"security":[{"session":[]}],"tags":["integrations"]}},"/v1/integrations/sync":{"post":{"operationId":"IntegrationsController_sync","parameters":[],"responses":{"200":{"description":""}},"security":[{"session":[]}],"summary":"Pull positions from every active connector for this tenant.","tags":["integrations"]}},"/v1/integrations/positions":{"get":{"operationId":"IntegrationsController_listPositions","parameters":[{"name":"accountId","required":true,"in":"query","schema":{"type":"string"}},{"name":"open","required":true,"in":"query","schema":{"type":"string"}},{"name":"limit","required":true,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"security":[{"session":[]}],"tags":["integrations"]}},"/v1/reporting/overview":{"get":{"operationId":"ReportingController_overview","parameters":[],"responses":{"200":{"description":""}},"security":[{"session":[]}],"summary":"KPI overview for the admin dashboard.","tags":["reporting"]}},"/v1/reporting/activity-by-day":{"get":{"operationId":"ReportingController_activityByDay","parameters":[{"name":"days","required":true,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"security":[{"session":[]}],"tags":["reporting"]}},"/v1/reporting/saved":{"get":{"operationId":"ReportingController_listSaved","parameters":[],"responses":{"200":{"description":""}},"security":[{"session":[]}],"tags":["reporting"]},"post":{"operationId":"ReportingController_createSaved","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SavedReportDto"}}}},"responses":{"201":{"description":""}},"security":[{"session":[]}],"tags":["reporting"]}},"/v1/reporting/saved/{id}/run":{"get":{"operationId":"ReportingController_runSaved","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"security":[{"session":[]}],"tags":["reporting"]}},"/v1/reporting/saved/{id}":{"delete":{"operationId":"ReportingController_removeSaved","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"204":{"description":""}},"security":[{"session":[]}],"tags":["reporting"]}},"/v1/workflows":{"get":{"operationId":"WorkflowsController_list","parameters":[],"responses":{"200":{"description":""}},"security":[{"session":[]}],"tags":["workflows"]},"post":{"operationId":"WorkflowsController_create","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateWorkflowDto"}}}},"responses":{"201":{"description":""}},"security":[{"session":[]}],"tags":["workflows"]}},"/v1/workflows/{id}/runs":{"get":{"operationId":"WorkflowsController_listRuns","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"security":[{"session":[]}],"tags":["workflows"]}},"/v1/workflows/{id}":{"delete":{"operationId":"WorkflowsController_remove","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"204":{"description":""}},"security":[{"session":[]}],"tags":["workflows"]}},"/v1/campaigns":{"get":{"operationId":"CampaignsController_list","parameters":[],"responses":{"200":{"description":""}},"security":[{"session":[]}],"tags":["campaigns"]},"post":{"operationId":"CampaignsController_create","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateCampaignDto"}}}},"responses":{"201":{"description":""}},"security":[{"session":[]}],"tags":["campaigns"]}},"/v1/campaigns/{id}":{"patch":{"operationId":"CampaignsController_update","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateCampaignDto"}}}},"responses":{"200":{"description":""}},"security":[{"session":[]}],"tags":["campaigns"]},"delete":{"operationId":"CampaignsController_remove","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"204":{"description":""}},"security":[{"session":[]}],"tags":["campaigns"]}},"/v1/campaigns/{id}/steps":{"get":{"operationId":"CampaignsController_listSteps","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"security":[{"session":[]}],"tags":["campaigns"]},"post":{"operationId":"CampaignsController_addStep","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddStepDto"}}}},"responses":{"201":{"description":""}},"security":[{"session":[]}],"tags":["campaigns"]},"put":{"operationId":"CampaignsController_replaceSteps","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"security":[{"session":[]}],"tags":["campaigns"]}},"/v1/campaigns/{id}/steps/{stepId}":{"delete":{"operationId":"CampaignsController_removeStep","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"stepId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"204":{"description":""}},"security":[{"session":[]}],"tags":["campaigns"]}},"/v1/campaigns/{id}/enrollments":{"get":{"operationId":"CampaignsController_listEnrollments","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"security":[{"session":[]}],"tags":["campaigns"]}},"/v1/risk-rules":{"get":{"operationId":"RiskController_list","parameters":[],"responses":{"200":{"description":""}},"security":[{"session":[]}],"tags":["risk-rules"]},"post":{"operationId":"RiskController_create","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateRiskRuleDto"}}}},"responses":{"201":{"description":""}},"security":[{"session":[]}],"tags":["risk-rules"]}},"/v1/risk-rules/stats":{"get":{"operationId":"RiskController_stats","parameters":[],"responses":{"200":{"description":""}},"security":[{"session":[]}],"summary":"Routing breakdown across the tenants trading accounts (after the most recent classify run).","tags":["risk-rules"]}},"/v1/risk-rules/{id}":{"patch":{"operationId":"RiskController_update","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateRiskRuleDto"}}}},"responses":{"200":{"description":""}},"security":[{"session":[]}],"tags":["risk-rules"]},"delete":{"operationId":"RiskController_remove","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"204":{"description":""}},"security":[{"session":[]}],"tags":["risk-rules"]}},"/v1/risk-rules/{id}/dry-run":{"post":{"operationId":"RiskController_dryRun","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DryRunDto"}}}},"responses":{"200":{"description":""}},"security":[{"session":[]}],"summary":"Dry-run a rule against a hypothetical context — returns whether it would fire and which routing it would emit.","tags":["risk-rules"]}},"/v1/risk-rules/classify-accounts":{"post":{"operationId":"RiskController_classifyAccounts","parameters":[],"responses":{"200":{"description":""}},"security":[{"session":[]}],"summary":"Re-evaluate every active trading account and persist the routing decision.","tags":["risk-rules"]}},"/v1/users/{id}/impersonate":{"post":{"operationId":"UsersController_impersonate","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"security":[{"session":[]}],"tags":["admin"]}},"/v1/users":{"get":{"operationId":"UsersController_list","parameters":[],"responses":{"200":{"description":""}},"security":[{"session":[]}],"tags":["admin"]}},"/v1/users/invite":{"post":{"operationId":"UsersController_invite","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InviteUserDto"}}}},"responses":{"201":{"description":""}},"security":[{"session":[]}],"tags":["admin"]}},"/v1/users/{id}/roles":{"patch":{"operationId":"UsersController_updateRoles","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateRolesDto"}}}},"responses":{"200":{"description":""}},"security":[{"session":[]}],"tags":["admin"]}},"/v1/users/{id}":{"delete":{"operationId":"UsersController_remove","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"204":{"description":""}},"security":[{"session":[]}],"tags":["admin"]}},"/v1/audit":{"get":{"operationId":"AuditController_list","parameters":[{"name":"resource","required":true,"in":"query","schema":{"type":"string"}},{"name":"action","required":true,"in":"query","schema":{"type":"string"}},{"name":"userId","required":true,"in":"query","schema":{"type":"string"}},{"name":"from","required":true,"in":"query","schema":{"type":"string"}},{"name":"to","required":true,"in":"query","schema":{"type":"string"}},{"name":"limit","required":true,"in":"query","schema":{"type":"string"}},{"name":"cursor","required":true,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"security":[{"session":[]}],"tags":["admin"]}},"/v1/audit/facets":{"get":{"operationId":"AuditController_facets","parameters":[],"responses":{"200":{"description":""}},"security":[{"session":[]}],"tags":["admin"]}},"/v1/audit/export.csv":{"get":{"operationId":"AuditController_exportCsv","parameters":[{"name":"resource","required":true,"in":"query","schema":{"type":"string"}},{"name":"action","required":true,"in":"query","schema":{"type":"string"}},{"name":"userId","required":true,"in":"query","schema":{"type":"string"}},{"name":"from","required":true,"in":"query","schema":{"type":"string"}},{"name":"to","required":true,"in":"query","schema":{"type":"string"}},{"name":"days","required":true,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"security":[{"session":[]}],"tags":["admin"]}},"/v1/admin/notifications/summary":{"get":{"operationId":"NotificationsController_summary","parameters":[],"responses":{"200":{"description":""}},"security":[{"session":[]}],"summary":"Action queues summary for the topbar bell + sidebar badges (pending KYC, open sanctions, deposits/withdrawals awaiting approval, open tickets).","tags":["admin"]}},"/v1/tenants/current":{"get":{"operationId":"TenantController_current","parameters":[],"responses":{"200":{"description":""}},"security":[{"session":[]}],"tags":["admin"]},"patch":{"operationId":"TenantController_update","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateTenantDto"}}}},"responses":{"200":{"description":""}},"security":[{"session":[]}],"tags":["admin"]}},"/v1/tenants/current/logo-upload":{"post":{"operationId":"TenantController_logoUpload","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LogoUploadDto"}}}},"responses":{"201":{"description":""}},"security":[{"session":[]}],"tags":["admin"]}},"/v1/tenants/current/logo-confirm":{"post":{"operationId":"TenantController_logoConfirm","parameters":[],"responses":{"201":{"description":""}},"security":[{"session":[]}],"tags":["admin"]}},"/v1/admin/traders/bulk-edit":{"post":{"operationId":"AdminExtController_bulkEditTraders","parameters":[],"responses":{"200":{"description":""}},"security":[{"session":[]}],"summary":"Bulk-edit traders (A3). Apply segment/assignment/risk changes to up to 500 ids.","tags":["admin"]}},"/v1/admin/activity":{"get":{"operationId":"AdminExtController_activity","parameters":[{"name":"days","required":true,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"security":[{"session":[]}],"summary":"Admin activity dashboard (A7): per-user action counts last 7 days.","tags":["admin"]}},"/v1/admin/position-heatmap":{"get":{"operationId":"AdminExtController_heatmap","parameters":[],"responses":{"200":{"description":""}},"security":[{"session":[]}],"summary":"Position heatmap (A12) — aggregated open volume per symbol across all traders.","tags":["admin"]}},"/v1/admin/sla/overdue":{"get":{"operationId":"AdminExtController_slaOverdue","parameters":[],"responses":{"200":{"description":""}},"security":[{"session":[]}],"summary":"Support tickets past their SLA deadline (A11).","tags":["admin"]}},"/v1/admin/reporting/cohorts":{"get":{"operationId":"AdminExtController_cohorts","parameters":[],"responses":{"200":{"description":""}},"security":[{"session":[]}],"summary":"Registration-month cohort analysis (R2): retention via first-deposit.","tags":["admin"]}},"/v1/admin/reporting/revenue-breakdown":{"get":{"operationId":"AdminExtController_revenueBreakdown","parameters":[{"name":"days","required":true,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"security":[{"session":[]}],"summary":"Commission revenue split by source type (R6).","tags":["admin"]}},"/v1/admin/traders/merge":{"post":{"operationId":"AdminExtV2Controller_mergeTraders","parameters":[],"responses":{"200":{"description":""}},"security":[{"session":[]}],"summary":"A2: merge duplicate traders. Moves accounts/deposits/withdrawals/tickets from secondary into primary, soft-deletes secondary.","tags":["admin"]}},"/v1/admin/impersonate/start":{"post":{"operationId":"AdminExtV2Controller_startImpersonation","parameters":[],"responses":{"200":{"description":""}},"security":[{"session":[]}],"summary":"A4: owner starts a \"view as trader\" session. Returns a short-lived token scoped to the target trader.","tags":["admin"]}},"/v1/admin/impersonate/{id}/end":{"post":{"operationId":"AdminExtV2Controller_endImpersonation","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"security":[{"session":[]}],"tags":["admin"]}},"/v1/admin/traders/{id}/pii-export":{"get":{"operationId":"AdminExtV2Controller_piiExport","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"security":[{"session":[]}],"summary":"G2: owner-initiated PII bundle export for a trader (GDPR Article 15).","tags":["admin"]}},"/v1/admin/reports/sql":{"post":{"operationId":"AdminExtV2Controller_sqlSandbox","parameters":[],"responses":{"200":{"description":""}},"security":[{"session":[]}],"summary":"R4: read-only SQL sandbox (owner-only). Wrapped in a Postgres READ ONLY transaction with 30s statement_timeout so even comment-smuggled writes are rejected at the DB layer. Results capped at 10k rows; query also passes a coarse keyword guard for clearer errors before the DB sees it.","tags":["admin"]}},"/v1/admin/fx-rates":{"get":{"operationId":"AdminExtV2Controller_fxRates","parameters":[],"responses":{"200":{"description":""}},"security":[{"session":[]}],"summary":"M1: current FX rates cached in fx_rates table.","tags":["admin"]},"post":{"operationId":"AdminExtV2Controller_setFxRate","parameters":[],"responses":{"201":{"description":""}},"security":[{"session":[]}],"summary":"M1: set/overwrite an FX rate (admin manual input).","tags":["admin"]}},"/v1/admin/deposits/{id}/partial-settle":{"post":{"operationId":"AdminExtV2Controller_partialSettle","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"security":[{"session":[]}],"summary":"M3: settle a deposit for a smaller amount (bank wire came in short). Writes a partial-settlement note into provider_payload.","tags":["admin"]}},"/v1/admin/tax-report":{"get":{"operationId":"AdminExtV2Controller_taxReport","parameters":[{"name":"year","required":true,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"security":[{"session":[]}],"summary":"M6: tax report stub — aggregate deposits/withdrawals per trader over a window for 1099/DAC7-style exports.","tags":["admin"]}},"/v1/billing/plans":{"get":{"operationId":"BillingController_plans","parameters":[],"responses":{"200":{"description":""}},"summary":"Public list of self-serve subscription plans.","tags":["billing"]}},"/v1/billing/current":{"get":{"operationId":"BillingController_current","parameters":[],"responses":{"200":{"description":""}},"security":[{"session":[]}],"tags":["billing"]}},"/v1/billing/checkout":{"post":{"operationId":"BillingController_checkout","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckoutDto"}}}},"responses":{"200":{"description":""}},"security":[{"session":[]}],"summary":"Create a Stripe Checkout session for the chosen plan.","tags":["billing"]}},"/v1/billing/portal":{"post":{"operationId":"BillingController_portal","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PortalDto"}}}},"responses":{"200":{"description":""}},"security":[{"session":[]}],"summary":"Open the Stripe billing portal for self-serve plan + invoice management.","tags":["billing"]}},"/v1/billing/webhook":{"post":{"operationId":"BillingWebhookController_handle","parameters":[],"responses":{"204":{"description":""}},"summary":"Stripe Billing webhook receiver (signature-verified). Handles subscription + invoice events.","tags":["billing"]}},"/v1/dashboards":{"get":{"operationId":"DashboardsController_list","parameters":[],"responses":{"200":{"description":""}},"security":[{"session":[]}],"tags":["dashboards"]},"post":{"operationId":"DashboardsController_create","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateDashboardDto"}}}},"responses":{"201":{"description":""}},"security":[{"session":[]}],"tags":["dashboards"]}},"/v1/dashboards/{id}":{"get":{"operationId":"DashboardsController_get","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"security":[{"session":[]}],"tags":["dashboards"]},"patch":{"operationId":"DashboardsController_update","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateDashboardDto"}}}},"responses":{"200":{"description":""}},"security":[{"session":[]}],"tags":["dashboards"]},"delete":{"operationId":"DashboardsController_remove","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"204":{"description":""}},"security":[{"session":[]}],"tags":["dashboards"]}},"/v1/api-keys":{"get":{"operationId":"ApiKeysController_list","parameters":[],"responses":{"200":{"description":""}},"security":[{"session":[]}],"tags":["api-keys"]},"post":{"operationId":"ApiKeysController_create","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateApiKeyDto"}}}},"responses":{"201":{"description":""}},"security":[{"session":[]}],"tags":["api-keys"]}},"/v1/api-keys/{id}/rotate":{"post":{"operationId":"ApiKeysController_rotate","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"security":[{"session":[]}],"tags":["api-keys"]}},"/v1/api-keys/{id}/revoke":{"post":{"operationId":"ApiKeysController_revoke","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"201":{"description":""}},"security":[{"session":[]}],"tags":["api-keys"]}},"/v1/api-keys/{id}":{"delete":{"operationId":"ApiKeysController_remove","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"204":{"description":""}},"security":[{"session":[]}],"tags":["api-keys"]}},"/v1/support/tickets":{"get":{"operationId":"SupportController_listTickets","parameters":[{"name":"status","required":true,"in":"query","schema":{"type":"string"}},{"name":"mine","required":true,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"security":[{"session":[]}],"tags":["support"]},"post":{"operationId":"SupportController_create","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateTicketDto"}}}},"responses":{"201":{"description":""}},"security":[{"session":[]}],"tags":["support"]}},"/v1/support/tickets/{id}":{"get":{"operationId":"SupportController_getTicket","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"security":[{"session":[]}],"tags":["support"]},"patch":{"operationId":"SupportController_update","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateTicketDto"}}}},"responses":{"200":{"description":""}},"security":[{"session":[]}],"tags":["support"]}},"/v1/support/tickets/{id}/reply":{"post":{"operationId":"SupportController_reply","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReplyDto"}}}},"responses":{"201":{"description":""}},"security":[{"session":[]}],"tags":["support"]}},"/v1/search":{"get":{"operationId":"SearchController_search","parameters":[{"name":"q","required":true,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"security":[{"session":[]}],"tags":["search"]}},"/v1/_meta/version":{"get":{"operationId":"MetaController_getVersion","parameters":[],"responses":{"200":{"description":""}},"summary":"Return the frozen public-API contract version + last changelog entry.","tags":["meta"]}},"/v1/_meta/changelog":{"get":{"operationId":"MetaController_getChangelog","parameters":[],"responses":{"200":{"description":""}},"summary":"Full /v1 contract changelog (newest first).","tags":["meta"]}},"/v1/docs/examples":{"get":{"operationId":"DocsController_list","parameters":[{"name":"tag","required":true,"in":"query","schema":{"type":"string"}},{"name":"lang","required":true,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"Auto-generated curl/JS/Python/PHP/Go snippets per /v1 endpoint.","tags":["docs"]}},"/v1/docs/examples/{operationId}":{"get":{"operationId":"DocsController_one","parameters":[{"name":"operationId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"tags":["docs"]}}},"info":{"title":"LumireCRM API","description":"REST API for LumireCRM — brokers, prop firms, and trading-platform back-office.","version":"1.0.0","contact":{}},"tags":[],"servers":[{"url":"http://localhost:4000","description":"Current environment"}],"components":{"securitySchemes":{"session":{"scheme":"bearer","bearerFormat":"session","type":"http"},"api-key":{"type":"apiKey","in":"header","name":"X-API-Key"}},"schemas":{"RegisterDto":{"type":"object","properties":{"email":{"type":"string","format":"email","maxLength":255},"password":{"type":"string","minLength":12,"maxLength":128},"displayName":{"type":"string","minLength":1,"maxLength":255},"tenantSlug":{"type":"string","minLength":1,"maxLength":64},"tenantName":{"type":"string","minLength":1,"maxLength":120}},"required":["email","password"]},"LoginDto":{"type":"object","properties":{"email":{"type":"string","format":"email"},"password":{"type":"string","minLength":1},"totpCode":{"type":"string"},"tenantSlug":{"type":"string","minLength":1,"maxLength":64}},"required":["email","password"]},"EnableTotpDto":{"type":"object","properties":{"code":{"type":"string"}},"required":["code"]},"CreateTraderDto":{"type":"object","properties":{"email":{"type":"string","format":"email","maxLength":255},"phone":{"type":"string","maxLength":32,"nullable":true},"firstName":{"type":"string","minLength":1,"maxLength":128,"nullable":true},"lastName":{"type":"string","minLength":1,"maxLength":128,"nullable":true},"country":{"type":"string","nullable":true},"dateOfBirth":{"type":"string","nullable":true},"segments":{"type":"array","maxItems":32,"items":{"type":"string","minLength":1,"maxLength":64}},"source":{"type":"string","maxLength":64,"nullable":true},"assignedToId":{"type":"string","pattern":"^[0-9A-HJKMNP-TV-Z]{26}$","nullable":true},"metadata":{"type":"object","additionalProperties":{}}},"required":["email","phone","firstName","lastName","country","dateOfBirth","source","assignedToId"]},"UpdateTraderDto":{"type":"object","properties":{"email":{"type":"string","format":"email","maxLength":255},"phone":{"type":"string","maxLength":32,"nullable":true},"firstName":{"type":"string","minLength":1,"maxLength":128,"nullable":true},"lastName":{"type":"string","minLength":1,"maxLength":128,"nullable":true},"country":{"type":"string","nullable":true},"dateOfBirth":{"type":"string","nullable":true},"segments":{"type":"array","maxItems":32,"items":{"type":"string","minLength":1,"maxLength":64}},"source":{"type":"string","maxLength":64,"nullable":true},"assignedToId":{"type":"string","pattern":"^[0-9A-HJKMNP-TV-Z]{26}$","nullable":true},"metadata":{"type":"object","additionalProperties":{}},"kycStatus":{"type":"string","enum":["not_started","in_progress","pending_review","approved","rejected"]}}},"SegmentsPatchDto":{"type":"object","properties":{"add":{"type":"array","items":{"type":"string","minLength":1,"maxLength":64}},"remove":{"type":"array","items":{"type":"string","minLength":1,"maxLength":64}}}},"RequestKycUploadDto":{"type":"object","properties":{"traderId":{"type":"string","pattern":"^[0-9A-HJKMNP-TV-Z]{26}$"},"kind":{"type":"string","enum":["passport","id_front","id_back","proof_of_address","selfie","other"]},"contentType":{"type":"string","pattern":"^[a-z]+\\/[a-z0-9.\\-+]+$","maxLength":127},"fileSize":{"type":"integer","minimum":0,"exclusiveMinimum":true,"maximum":20971520,"exclusiveMaximum":false}},"required":["traderId","kind","contentType","fileSize"]},"ConfirmKycUploadDto":{"type":"object","properties":{"documentId":{"type":"string","pattern":"^[0-9A-HJKMNP-TV-Z]{26}$"}},"required":["documentId"]},"SubmitKycDto":{"type":"object","properties":{"traderId":{"type":"string","pattern":"^[0-9A-HJKMNP-TV-Z]{26}$"}},"required":["traderId"]},"ApproveKycDto":{"type":"object","properties":{"traderId":{"type":"string","pattern":"^[0-9A-HJKMNP-TV-Z]{26}$"},"notes":{"type":"string","maxLength":500}},"required":["traderId"]},"RejectKycDto":{"type":"object","properties":{"traderId":{"type":"string","pattern":"^[0-9A-HJKMNP-TV-Z]{26}$"},"reason":{"type":"string","minLength":5,"maxLength":500}},"required":["traderId","reason"]},"RequestMoreInfoKycDto":{"type":"object","properties":{"traderId":{"type":"string","pattern":"^[0-9A-HJKMNP-TV-Z]{26}$"},"notes":{"type":"string","minLength":5,"maxLength":500}},"required":["traderId","notes"]},"CreateAccountDto":{"type":"object","properties":{"traderId":{"type":"string","pattern":"^[0-9A-HJKMNP-TV-Z]{26}$"},"platform":{"type":"string","enum":["mt5","mt4","ctrader","lumireone","manual"]},"externalId":{"type":"string","maxLength":128,"nullable":true},"accountNumber":{"type":"string","minLength":1,"maxLength":64},"currency":{"type":"string"},"balance":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$"},"equity":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$"},"leverage":{"type":"integer","minimum":0,"exclusiveMinimum":true,"maximum":2000,"exclusiveMaximum":false},"isDemo":{"type":"boolean"},"metadata":{"type":"object","additionalProperties":{}}},"required":["traderId","platform","externalId","accountNumber","currency"]},"UpdateAccountDto":{"type":"object","properties":{"traderId":{"type":"string","pattern":"^[0-9A-HJKMNP-TV-Z]{26}$"},"platform":{"type":"string","enum":["mt5","mt4","ctrader","lumireone","manual"]},"externalId":{"type":"string","maxLength":128,"nullable":true},"accountNumber":{"type":"string","minLength":1,"maxLength":64},"currency":{"type":"string"},"balance":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$"},"equity":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$"},"leverage":{"type":"integer","minimum":0,"exclusiveMinimum":true,"maximum":2000,"exclusiveMaximum":false},"isDemo":{"type":"boolean"},"metadata":{"type":"object","additionalProperties":{}},"status":{"type":"string","enum":["active","suspended","closed"]}}},"CreateTransactionDto":{"type":"object","properties":{"traderId":{"type":"string","pattern":"^[0-9A-HJKMNP-TV-Z]{26}$","nullable":true},"accountId":{"type":"string","pattern":"^[0-9A-HJKMNP-TV-Z]{26}$","nullable":true},"kind":{"type":"string","enum":["deposit","withdrawal","trade","commission","rebate","fee","adjustment"]},"status":{"type":"string","enum":["pending","completed","failed","reversed"]},"amount":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$"},"currency":{"type":"string"},"reference":{"type":"string","maxLength":128,"nullable":true},"description":{"type":"string","maxLength":500,"nullable":true},"externalId":{"type":"string","maxLength":128,"nullable":true},"occurredAt":{"type":"string","format":"date-time"},"metadata":{"type":"object","additionalProperties":{}}},"required":["traderId","accountId","kind","amount","currency","reference","description","externalId"]},"CreateTemplateDto":{"type":"object","properties":{"slug":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[a-z0-9][a-z0-9-_]*$"},"channel":{"type":"string","enum":["email","sms","whatsapp"]},"subject":{"type":"string","maxLength":255,"nullable":true},"body":{"type":"string","minLength":1,"maxLength":50000},"variables":{"type":"array","items":{"type":"string","minLength":1,"maxLength":64}},"isActive":{"type":"boolean"}},"required":["slug","channel","subject","body"]},"UpdateTemplateDto":{"type":"object","properties":{"slug":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[a-z0-9][a-z0-9-_]*$"},"channel":{"type":"string","enum":["email","sms","whatsapp"]},"subject":{"type":"string","maxLength":255,"nullable":true},"body":{"type":"string","minLength":1,"maxLength":50000},"variables":{"type":"array","items":{"type":"string","minLength":1,"maxLength":64}},"isActive":{"type":"boolean"}}},"SendMessageDto":{"type":"object","properties":{"traderId":{"type":"string","pattern":"^[0-9A-HJKMNP-TV-Z]{26}$"},"templateSlug":{"type":"string","minLength":1,"maxLength":64},"channel":{"type":"string","enum":["email","sms","whatsapp"]},"to":{"type":"string","minLength":1,"maxLength":255},"subject":{"type":"string","maxLength":255},"body":{"type":"string","minLength":1,"maxLength":50000},"variables":{"type":"object","additionalProperties":{"type":"string"}}},"required":["channel","to"]},"CreateAffiliateDto":{"type":"object","properties":{"traderId":{"type":"string","pattern":"^[0-9A-HJKMNP-TV-Z]{26}$"},"code":{"type":"string","minLength":3,"maxLength":32,"pattern":"^[A-Z0-9_-]+$"},"parentId":{"type":"string","pattern":"^[0-9A-HJKMNP-TV-Z]{26}$"}},"required":["traderId","code"]},"CreateRebateRuleDto":{"type":"object","properties":{"affiliateId":{"type":"string","pattern":"^[0-9A-HJKMNP-TV-Z]{26}$"},"kind":{"type":"string","enum":["per_deposit","per_lot","per_volume"]},"depth":{"type":"integer","minimum":1,"exclusiveMinimum":false,"maximum":10,"exclusiveMaximum":false},"amount":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$"},"percent":{"type":"boolean"},"currency":{"type":"string"},"isActive":{"type":"boolean"}},"required":["kind","amount"]},"CreatePaymentMethodDto":{"type":"object","properties":{"traderId":{"type":"string","pattern":"^[0-9A-HJKMNP-TV-Z]{26}$"},"kind":{"type":"string","enum":["card","bank_transfer","crypto_wallet","crypto_processor","manual"]},"label":{"type":"string","minLength":1,"maxLength":128},"externalRef":{"type":"string","maxLength":255},"currency":{"type":"string"},"network":{"type":"string","maxLength":32},"metadata":{"type":"object","additionalProperties":{}},"isDefault":{"type":"boolean"}},"required":["traderId","kind","label"]},"CreateDepositDto":{"type":"object","properties":{"traderId":{"type":"string","pattern":"^[0-9A-HJKMNP-TV-Z]{26}$"},"accountId":{"type":"string","pattern":"^[0-9A-HJKMNP-TV-Z]{26}$"},"paymentMethodId":{"type":"string","pattern":"^[0-9A-HJKMNP-TV-Z]{26}$"},"kind":{"type":"string","enum":["card","bank_transfer","crypto_wallet","crypto_processor","manual"]},"amount":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$"},"currency":{"type":"string"},"externalId":{"type":"string","maxLength":255},"metadata":{"type":"object","additionalProperties":{}}},"required":["traderId","kind","amount","currency"]},"ApprovePaymentDto":{"type":"object","properties":{"id":{"type":"string","pattern":"^[0-9A-HJKMNP-TV-Z]{26}$"},"notes":{"type":"string","maxLength":500}},"required":["id"]},"BulkApprovePaymentsDto":{"type":"object","properties":{"ids":{"type":"array","minItems":1,"maxItems":50,"items":{"type":"string","pattern":"^[0-9A-HJKMNP-TV-Z]{26}$"}},"notes":{"type":"string","maxLength":500}},"required":["ids"]},"RejectPaymentDto":{"type":"object","properties":{"id":{"type":"string","pattern":"^[0-9A-HJKMNP-TV-Z]{26}$"},"reason":{"type":"string","minLength":5,"maxLength":500}},"required":["id","reason"]},"SettlePaymentDto":{"type":"object","properties":{"id":{"type":"string","pattern":"^[0-9A-HJKMNP-TV-Z]{26}$"},"feeAmount":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$"},"netAmount":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$"},"settledAt":{"type":"string","format":"date-time"},"externalId":{"type":"string","maxLength":255},"proofUrl":{"type":"string","format":"uri","maxLength":512},"notes":{"type":"string","maxLength":500}},"required":["id"]},"ReconcilePaymentDto":{"type":"object","properties":{"id":{"type":"string","pattern":"^[0-9A-HJKMNP-TV-Z]{26}$"},"reconciled":{"type":"boolean"},"notes":{"type":"string","maxLength":500}},"required":["id","reconciled"]},"ReversePaymentDto":{"type":"object","properties":{"id":{"type":"string","pattern":"^[0-9A-HJKMNP-TV-Z]{26}$"},"reason":{"type":"string","minLength":5,"maxLength":500}},"required":["id","reason"]},"CreateWithdrawalDto":{"type":"object","properties":{"traderId":{"type":"string","pattern":"^[0-9A-HJKMNP-TV-Z]{26}$"},"accountId":{"type":"string","pattern":"^[0-9A-HJKMNP-TV-Z]{26}$"},"paymentMethodId":{"type":"string","pattern":"^[0-9A-HJKMNP-TV-Z]{26}$"},"kind":{"type":"string","enum":["card","bank_transfer","crypto_wallet","crypto_processor","manual"]},"amount":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$"},"currency":{"type":"string"},"destinationRef":{"type":"string","maxLength":255},"metadata":{"type":"object","additionalProperties":{}}},"required":["traderId","kind","amount","currency"]},"StartRegDto":{"type":"object","properties":{"label":{"type":"string","minLength":1,"maxLength":128}},"required":["label"]},"FinishRegDto":{"type":"object","properties":{"label":{"type":"string","minLength":1,"maxLength":128},"response":{"type":"object","additionalProperties":{}}},"required":["label","response"]},"StartAuthDto":{"type":"object","properties":{"email":{"type":"string","format":"email"}},"required":["email"]},"FinishAuthDto":{"type":"object","properties":{"response":{"type":"object","additionalProperties":{}}},"required":["response"]},"CreateSubscriptionDto":{"type":"object","properties":{"url":{"type":"string","format":"uri","maxLength":1024},"events":{"type":"array","minItems":1,"maxItems":32,"items":{"type":"string","minLength":1,"maxLength":64}}},"required":["url","events"]},"CreateLeadDto":{"type":"object","properties":{"email":{"type":"string","format":"email","maxLength":255},"phone":{"type":"string","maxLength":32},"firstName":{"type":"string","maxLength":128},"lastName":{"type":"string","maxLength":128},"country":{"type":"string"},"source":{"type":"string","maxLength":64},"assignedToId":{"type":"string","pattern":"^[0-9A-HJKMNP-TV-Z]{26}$"},"score":{"type":"integer","minimum":0,"exclusiveMinimum":false,"maximum":100,"exclusiveMaximum":false},"metadata":{"type":"object","additionalProperties":{}}},"required":["email"]},"UpdateLeadDto":{"type":"object","properties":{"email":{"type":"string","format":"email","maxLength":255},"phone":{"type":"string","maxLength":32},"firstName":{"type":"string","maxLength":128},"lastName":{"type":"string","maxLength":128},"country":{"type":"string"},"source":{"type":"string","maxLength":64},"assignedToId":{"type":"string","pattern":"^[0-9A-HJKMNP-TV-Z]{26}$"},"score":{"type":"integer","minimum":0,"exclusiveMinimum":false,"maximum":100,"exclusiveMaximum":false},"metadata":{"type":"object","additionalProperties":{}},"status":{"type":"string","enum":["new","contacted","qualified","converted","lost","disqualified"]},"pipelineStageId":{"type":"string","pattern":"^[0-9A-HJKMNP-TV-Z]{26}$"}}},"CreatePipelineDto":{"type":"object","properties":{"slug":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[a-z0-9][a-z0-9-_]*$"},"name":{"type":"string","minLength":1,"maxLength":128},"isDefault":{"type":"boolean"},"stages":{"type":"array","minItems":1,"maxItems":20,"items":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":64},"position":{"type":"integer","minimum":0,"exclusiveMinimum":false,"maximum":20,"exclusiveMaximum":false},"probability":{"type":"integer","minimum":0,"exclusiveMinimum":false,"maximum":100,"exclusiveMaximum":false}},"required":["name","position"]}}},"required":["slug","name","stages"]},"CreateActivityDto":{"type":"object","properties":{"leadId":{"type":"string","pattern":"^[0-9A-HJKMNP-TV-Z]{26}$"},"traderId":{"type":"string","pattern":"^[0-9A-HJKMNP-TV-Z]{26}$"},"kind":{"type":"string","enum":["note","call","email","sms","whatsapp","meeting"]},"subject":{"type":"string","maxLength":255},"body":{"type":"string","maxLength":10000},"occurredAt":{"type":"string","format":"date-time"}},"required":["kind"]},"UpsertConfigDto":{"type":"object","properties":{"platform":{"type":"string","enum":["mt5","mt4","ctrader","lumireone","manual"]},"label":{"type":"string","minLength":1,"maxLength":128},"endpoint":{"type":"string","maxLength":512},"credentials":{"type":"object","additionalProperties":{}},"isActive":{"type":"boolean"}},"required":["platform","label"]},"SavedReportDto":{"type":"object","properties":{"slug":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[a-z0-9-]+$"},"name":{"type":"string","minLength":1,"maxLength":255},"kind":{"type":"string","enum":["deposits","withdrawals","traders","leads","commissions"]},"query":{"type":"object","additionalProperties":{},"default":{}},"schedule":{"type":"string","maxLength":64,"nullable":true}},"required":["slug","name","kind"]},"CreateWorkflowDto":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":255},"triggerType":{"type":"string","minLength":1,"maxLength":64},"condition":{"type":"object","additionalProperties":{}},"actions":{"type":"array","items":{"type":"object","additionalProperties":{}}},"isActive":{"type":"boolean"}},"required":["name","triggerType"]},"CreateCampaignDto":{"type":"object","properties":{"slug":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[a-z0-9-]+$"},"name":{"type":"string","minLength":1,"maxLength":255},"enrollmentRule":{"type":"object","additionalProperties":{}},"steps":{"type":"array","items":{"type":"object","properties":{"position":{"type":"integer","minimum":0,"exclusiveMinimum":false},"kind":{"type":"string","enum":["email","sms","whatsapp","delay","tag"]},"delayHours":{"type":"integer","minimum":0,"exclusiveMinimum":false,"maximum":8760,"exclusiveMaximum":false,"default":0},"payload":{"type":"object","additionalProperties":{},"default":{}}},"required":["position","kind"]},"default":[]}},"required":["slug","name"]},"UpdateCampaignDto":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":255},"status":{"type":"string","enum":["draft","active","paused","archived"]},"enrollmentRule":{"type":"object","additionalProperties":{}}}},"AddStepDto":{"type":"object","properties":{"position":{"type":"integer","minimum":0,"exclusiveMinimum":false},"kind":{"type":"string","enum":["email","sms","whatsapp","delay","tag"]},"delayHours":{"type":"integer","minimum":0,"exclusiveMinimum":false,"maximum":8760,"exclusiveMaximum":false,"default":0},"payload":{"type":"object","additionalProperties":{},"default":{}}},"required":["position","kind"]},"CreateRiskRuleDto":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":128},"match":{"type":"object","additionalProperties":{},"default":{}},"routing":{"type":"string","minLength":1,"maxLength":16},"priority":{"type":"integer","minimum":0,"exclusiveMinimum":false,"maximum":1000,"exclusiveMaximum":false,"default":0},"isActive":{"type":"boolean","default":true}},"required":["name","routing"]},"UpdateRiskRuleDto":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":128},"match":{"type":"object","additionalProperties":{},"default":{}},"routing":{"type":"string","minLength":1,"maxLength":16},"priority":{"type":"integer","minimum":0,"exclusiveMinimum":false,"maximum":1000,"exclusiveMaximum":false,"default":0},"isActive":{"type":"boolean","default":true}}},"DryRunDto":{"type":"object","properties":{"trader_country":{"type":"string"},"account_balance":{"type":"number"},"account_leverage":{"type":"number"},"deposit_total_lifetime":{"type":"number"},"position_volume":{"type":"number"},"position_symbol":{"type":"string"},"position_profit":{"type":"number"},"is_demo":{"type":"boolean"}}},"InviteUserDto":{"type":"object","properties":{"email":{"type":"string","format":"email","maxLength":255},"displayName":{"type":"string","minLength":1,"maxLength":255},"roles":{"type":"array","maxItems":8,"items":{"type":"string","minLength":1,"maxLength":32},"default":[]},"password":{"type":"string","minLength":12,"maxLength":256},"sendInviteLink":{"type":"boolean","default":true}},"required":["email"]},"UpdateRolesDto":{"type":"object","properties":{"roles":{"type":"array","maxItems":8,"items":{"type":"string","minLength":1,"maxLength":32}}},"required":["roles"]},"UpdateTenantDto":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":255},"branding":{"type":"object","additionalProperties":{}},"featureFlags":{"type":"object","additionalProperties":{}}}},"LogoUploadDto":{"type":"object","properties":{"contentType":{"type":"string","pattern":"^image\\/[a-z0-9.+-]+$","maxLength":127},"fileSize":{"type":"integer","minimum":0,"exclusiveMinimum":true,"maximum":5242880,"exclusiveMaximum":false}},"required":["contentType","fileSize"]},"CheckoutDto":{"type":"object","properties":{"plan":{"type":"string","minLength":1,"maxLength":64},"return_url":{"type":"string","format":"uri","maxLength":1024}},"required":["plan","return_url"]},"PortalDto":{"type":"object","properties":{"return_url":{"type":"string","format":"uri","maxLength":1024}},"required":["return_url"]},"CreateDashboardDto":{"type":"object","properties":{"slug":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[a-z0-9-]+$"},"name":{"type":"string","minLength":1,"maxLength":255},"widgets":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string","enum":["kpi","saved_report","activity_feed"]},"title":{"type":"string","minLength":1,"maxLength":128},"colSpan":{"type":"integer","minimum":1,"exclusiveMinimum":false,"maximum":12,"exclusiveMaximum":false,"default":4},"savedReportId":{"type":"string","minLength":1},"kpiKind":{"type":"string","enum":["traders","active_leads","kyc_pending","deposits_7d","withdrawals_7d","open_positions","commissions_30d"]}},"required":["type","title"]},"default":[]},"userId":{"type":"string","minLength":1}},"required":["slug","name"]},"UpdateDashboardDto":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":255},"widgets":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string","enum":["kpi","saved_report","activity_feed"]},"title":{"type":"string","minLength":1,"maxLength":128},"colSpan":{"type":"integer","minimum":1,"exclusiveMinimum":false,"maximum":12,"exclusiveMaximum":false,"default":4},"savedReportId":{"type":"string","minLength":1},"kpiKind":{"type":"string","enum":["traders","active_leads","kyc_pending","deposits_7d","withdrawals_7d","open_positions","commissions_30d"]}},"required":["type","title"]}}}},"CreateApiKeyDto":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":128},"scopes":{"type":"array","maxItems":32,"items":{"type":"string","minLength":1,"maxLength":64},"default":[]},"expiresAt":{"type":"string","format":"date-time"}},"required":["name"]},"CreateTicketDto":{"type":"object","properties":{"subject":{"type":"string","minLength":3,"maxLength":255},"body":{"type":"string","minLength":1,"maxLength":10000},"priority":{"type":"string","enum":["low","normal","high","urgent"],"default":"normal"},"traderId":{"type":"string"}},"required":["subject","body"]},"ReplyDto":{"type":"object","properties":{"body":{"type":"string","minLength":1,"maxLength":10000}},"required":["body"]},"UpdateTicketDto":{"type":"object","properties":{"status":{"type":"string","enum":["open","pending_trader","pending_operator","resolved","closed"]},"priority":{"type":"string","enum":["low","normal","high","urgent"]},"assignedToId":{"type":"string","nullable":true}}}}}}