{"openapi":"3.0.0","paths":{"/api/v1/health":{"get":{"operationId":"HealthController_check","parameters":[],"responses":{"200":{"description":""}},"summary":"Liveness check","tags":["Health"]}},"/api/v1/health/ready":{"get":{"operationId":"HealthController_ready","parameters":[],"responses":{"200":{"description":""}},"summary":"Readiness check — verifies dependencies","tags":["Health"]}},"/api/v1/customers":{"post":{"description":"Creates a new customer with either custodial or self-custodial account type","operationId":"CustomersController_createCustomer","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateCustomerDto"}}}},"responses":{"201":{"description":"Customer created successfully","content":{"application/json":{"schema":{"example":{"id":"550e8400-e29b-41d4-a716-446655440000","companyId":"550e8400-e29b-41d4-a716-446655440001","email":"john.doe@example.com","firstName":"John","lastName":"Doe","custodyType":"CUSTODIAL","kycStatus":"NOT_STARTED","status":"ACTIVE","createdAt":"2025-10-24T12:00:00.000Z"}}}}},"409":{"description":"Customer with this email already exists"}},"security":[{"bearer":[]}],"summary":"Create a new customer","tags":["Customers"]},"get":{"description":"Retrieve a paginated list of customers with optional filters","operationId":"CustomersController_listCustomers","parameters":[{"name":"companyId","required":false,"in":"query","description":"Filter by company ID","schema":{"type":"string"}},{"name":"searchTerm","required":false,"in":"query","description":"Search by name or email","schema":{"type":"string"}},{"name":"limit","required":false,"in":"query","description":"Items per page","schema":{"type":"number"}},{"name":"page","required":false,"in":"query","description":"Page number","schema":{"type":"number"}},{"name":"status","required":false,"in":"query","description":"Filter by customer status","schema":{"enum":["ACTIVE","INACTIVE","SUSPENDED","CLOSED"],"type":"string"}},{"name":"kycStatus","required":false,"in":"query","description":"Filter by KYC status","schema":{"enum":["NOT_STARTED","IN_PROGRESS","PENDING_REVIEW","APPROVED","REJECTED","EXPIRED"],"type":"string"}},{"name":"custodyType","required":false,"in":"query","description":"Filter by custody type","schema":{"enum":["CUSTODIAL","SELF_CUSTODIAL"],"type":"string"}}],"responses":{"200":{"description":"Customers retrieved successfully"}},"security":[{"bearer":[]}],"summary":"List customers with filtering and pagination","tags":["Customers"]}},"/api/v1/customers/stats":{"get":{"description":"Retrieve aggregated statistics about customers for a company","operationId":"CustomersController_getCustomerStats","parameters":[{"name":"companyId","required":true,"in":"query","description":"Company ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Customer statistics retrieved successfully","content":{"application/json":{"schema":{"example":{"totalCustomers":98,"byStatus":{"active":95,"inactive":2,"suspended":1,"closed":0},"byCustodyType":{"custodial":98,"selfCustodial":0},"byKycStatus":{"notStarted":98,"inProgress":0,"pendingReview":0,"approved":0,"rejected":0,"expired":0}}}}}}},"security":[{"bearer":[]}],"summary":"Get customer statistics","tags":["Customers"]}},"/api/v1/customers/top-holders":{"get":{"description":"Returns top N customers sorted by their total holdings USD value","operationId":"CustomersController_getTopHolders","parameters":[{"name":"companyId","required":true,"in":"query","description":"Company ID","schema":{"type":"string"}},{"name":"limit","required":false,"in":"query","description":"Number of top holders to return (default: 5)","schema":{"type":"number"}}],"responses":{"200":{"description":"Top holders retrieved successfully"}},"security":[{"bearer":[]}],"summary":"Get top holders by total holdings value","tags":["Customers"]}},"/api/v1/customers/{id}":{"get":{"operationId":"CustomersController_getCustomer","parameters":[{"name":"id","required":true,"in":"path","description":"Customer ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Customer retrieved successfully"},"404":{"description":"Customer not found"}},"security":[{"bearer":[]}],"summary":"Get customer by ID","tags":["Customers"]},"patch":{"operationId":"CustomersController_updateCustomer","parameters":[{"name":"id","required":true,"in":"path","description":"Customer ID","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateCustomerDto"}}}},"responses":{"200":{"description":"Customer updated successfully"},"404":{"description":"Customer not found"}},"security":[{"bearer":[]}],"summary":"Update customer profile","tags":["Customers"]}},"/api/v1/customers/{id}/upgrade-to-self-custodial":{"post":{"description":"Upgrades a custodial customer to self-custodial by assigning a smart wallet. Requires KYC approval.","operationId":"CustomersController_upgradeToSelfCustodial","parameters":[{"name":"id","required":true,"in":"path","description":"Customer ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Customer upgraded to self-custodial successfully"},"400":{"description":"Customer is already self-custodial or KYC not approved"},"404":{"description":"Customer not found"}},"security":[{"bearer":[]}],"summary":"Upgrade customer to self-custodial","tags":["Customers"]}},"/api/v1/customers/me/holdings":{"get":{"description":"Retrieve all token holdings for the authenticated user","operationId":"HoldingsController_getHoldings","parameters":[{"name":"limit","required":false,"in":"query","schema":{"type":"number"}},{"name":"page","required":false,"in":"query","schema":{"type":"number"}}],"responses":{"200":{"description":"Holdings retrieved successfully"}},"security":[{"bearer":[]}],"summary":"Get my holdings","tags":["Holdings"]}},"/api/v1/custodial/transactions":{"post":{"description":"Creates a new custodial transaction (deposit, withdrawal, purchase, etc.) for internal ledger tracking","operationId":"CustodialController_createTransaction","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateCustodialTransactionDto"}}}},"responses":{"201":{"description":"Transaction created successfully","content":{"application/json":{"schema":{"example":{"id":"550e8400-e29b-41d4-a716-446655440000","customerId":"550e8400-e29b-41d4-a716-446655440001","assetId":"550e8400-e29b-41d4-a716-446655440002","transactionType":"DEPOSIT","amount":"100.5","usdValue":500.25,"settlementStatus":"PENDING","createdAt":"2025-10-24T12:00:00.000Z"}}}}},"400":{"description":"Invalid transaction data"},"404":{"description":"Customer not found"}},"security":[{"bearer":[]}],"summary":"Create custodial transaction","tags":["Custodial"]}},"/api/v1/custodial/customers/{customerId}/transactions":{"get":{"description":"Retrieve transaction history for a specific customer","operationId":"CustodialController_getCustomerTransactions","parameters":[{"name":"customerId","required":true,"in":"path","description":"Customer ID","schema":{"type":"string"}},{"name":"limit","required":false,"in":"query","description":"Items per page","schema":{"type":"number"}},{"name":"page","required":false,"in":"query","description":"Page number","schema":{"type":"number"}}],"responses":{"200":{"description":"Transactions retrieved successfully","content":{"application/json":{"schema":{"example":{"data":[{"id":"550e8400-e29b-41d4-a716-446655440000","customerId":"550e8400-e29b-41d4-a716-446655440001","assetId":"550e8400-e29b-41d4-a716-446655440002","transactionType":"DEPOSIT","amount":"100.5","usdValue":500.25,"settlementStatus":"PENDING","createdAt":"2025-10-24T12:00:00.000Z"}],"pagination":{"total":1,"page":1,"limit":10,"totalPages":1}}}}}}},"security":[{"bearer":[]}],"summary":"Get customer custodial transactions","tags":["Custodial"]}},"/api/v1/customers/{customerId}/assets/nfts":{"get":{"description":"Retrieve all NFTs owned by a specific customer","operationId":"CustomerAssetsController_getCustomerNFTs","parameters":[{"name":"customerId","required":true,"in":"path","description":"Customer ID (Clerk user ID)","schema":{"type":"string"}},{"name":"offset","required":false,"in":"query","description":"Offset for pagination (default: 0)","schema":{"type":"number"}},{"name":"limit","required":false,"in":"query","description":"Items per page (default: 20)","schema":{"type":"number"}}],"responses":{"200":{"description":"NFTs retrieved successfully","content":{"application/json":{"schema":{"example":{"nfts":[{"id":"550e8400-e29b-41d4-a716-446655440000","companyId":"550e8400-e29b-41d4-a716-446655440001","name":"Rare Dragon NFT","imageUrl":"https://pxl8-app-cdn.nyc3.cdn.digitaloceanspaces.com/companies/123/nfts/dragon.png","status":"MINTED","ownerId":"user_2abc123def456","mintedAt":"2025-10-24T12:00:00.000Z"}],"total":5,"limit":20,"offset":0}}}}}},"security":[{"bearer":[]}],"summary":"Get customer NFTs","tags":["Customer Assets"]}},"/api/v1/customers/{customerId}/assets/tokens":{"get":{"description":"Retrieve all tokens owned by a specific customer","operationId":"CustomerAssetsController_getCustomerTokens","parameters":[{"name":"customerId","required":true,"in":"path","description":"Customer ID (Clerk user ID)","schema":{"type":"string"}},{"name":"offset","required":false,"in":"query","description":"Offset for pagination (default: 0)","schema":{"type":"number"}},{"name":"limit","required":false,"in":"query","description":"Items per page (default: 20)","schema":{"type":"number"}}],"responses":{"200":{"description":"Tokens retrieved successfully","content":{"application/json":{"schema":{"example":{"tokens":[{"id":"550e8400-e29b-41d4-a716-446655440000","companyId":"550e8400-e29b-41d4-a716-446655440001","tokenNumber":"TOKEN-001","status":"MINTED","ownerId":"user_2abc123def456","metadata":{"imageUrl":"https://pxl8-app-cdn.nyc3.cdn.digitaloceanspaces.com/companies/123/tokens/token-001.png"},"mintedAt":"2025-10-24T12:00:00.000Z"}],"total":3,"limit":20,"offset":0}}}}}},"security":[{"bearer":[]}],"summary":"Get customer tokens","tags":["Customer Assets"]}},"/api/v1/customers/{customerId}/assets/summary":{"get":{"description":"Retrieve summary counts of all assets (NFTs, tokens, holdings) for a customer","operationId":"CustomerAssetsController_getCustomerAssetsSummary","parameters":[{"name":"customerId","required":true,"in":"path","description":"Customer ID (Clerk user ID)","schema":{"type":"string"}}],"responses":{"200":{"description":"Assets summary retrieved successfully","content":{"application/json":{"schema":{"example":{"nftCount":5,"tokenCount":3,"customerId":"user_2abc123def456"}}}}}},"security":[{"bearer":[]}],"summary":"Get customer assets summary","tags":["Customer Assets"]}},"/api/v1/customers/me/portfolio/summary":{"get":{"description":"Retrieve aggregated portfolio metrics including total value, gain/loss, and asset allocation for the authenticated user","operationId":"PortfolioController_getPortfolioSummary","parameters":[],"responses":{"200":{"description":"Portfolio summary retrieved successfully","content":{"application/json":{"schema":{"example":{"totalValue":25500,"totalCostBasis":20000,"totalGainLoss":5500,"totalGainLossPercentage":27.5,"assetAllocation":[{"assetId":"550e8400-e29b-41d4-a716-446655440002","tokenSymbol":"PROP1","tokenName":"Property Token #1","value":15500,"percentage":60.78,"gainLoss":3500,"gainLossPercentage":29.17},{"assetId":"550e8400-e29b-41d4-a716-446655440003","tokenSymbol":"PROP2","tokenName":"Property Token #2","value":10000,"percentage":39.22,"gainLoss":2000,"gainLossPercentage":25}],"holdingsCount":2}}}}},"401":{"description":"Unauthorized - Invalid or missing authentication token"},"404":{"description":"Customer not found"}},"security":[{"bearer":[]}],"summary":"Get my portfolio summary","tags":["Portfolio"]}},"/api/v1/customers/me/portfolio/returns":{"get":{"description":"Calculate realized gains, unrealized gains, ROI, and portfolio performance metrics for the authenticated customer over a specified time period.","operationId":"PortfolioController_getPortfolioReturns","parameters":[{"name":"period","required":false,"in":"query","description":"Time period for returns calculation (default: 30d)","schema":{"enum":["7d","30d","90d","1y","all"],"type":"string"}}],"responses":{"200":{"description":"Portfolio returns retrieved successfully","schema":{"example":{"period":"30d","startDate":"2024-10-20T00:00:00.000Z","endDate":"2024-11-20T12:34:56.789Z","realizedGains":1500,"unrealizedGains":2500,"totalReturns":4000,"totalInvested":10000,"returnOnInvestment":40,"portfolioValueAtStart":10000,"portfolioValueAtEnd":14000,"changeInValue":4000,"changePercentage":40,"transactionsSummary":{"purchases":5,"sales":2,"deposits":3,"withdrawals":1}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PortfolioReturnsResponseDto"}}}},"400":{"description":"Bad Request - Invalid period parameter"},"401":{"description":"Unauthorized - Invalid or missing authentication token"}},"security":[{"bearer":[]}],"summary":"Get portfolio returns for a time period","tags":["Portfolio"]}},"/api/v1/customers/me/settings":{"get":{"description":"Returns the portfolio settings for the authenticated user. If settings do not exist, creates them with default values.","operationId":"CustomerSettingsController_getSettings","parameters":[],"responses":{"200":{"description":"Portfolio settings retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomerSettingsResponseDto"}}}},"404":{"description":"Customer not found"}},"security":[{"bearer":[]}],"summary":"Get current user portfolio settings","tags":["Customer Settings"]},"patch":{"description":"Updates the portfolio settings for the authenticated user. Only provided fields will be updated.","operationId":"CustomerSettingsController_updateSettings","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateCustomerSettingsDto"}}}},"responses":{"200":{"description":"Portfolio settings updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomerSettingsResponseDto"}}}},"400":{"description":"Invalid input data"},"404":{"description":"Customer not found"}},"security":[{"bearer":[]}],"summary":"Update current user portfolio settings","tags":["Customer Settings"]}},"/api/v1/customers/me/credits/balance":{"get":{"description":"Retrieve the current credits balance for the authenticated customer, including available, pending, and lifetime metrics","operationId":"CreditsController_getBalance","parameters":[],"responses":{"200":{"description":"Credits balance retrieved successfully","content":{"application/json":{"schema":{"example":{"id":"550e8400-e29b-41d4-a716-446655440000","customerId":"550e8400-e29b-41d4-a716-446655440001","availableBalance":250.5,"pendingBalance":50,"totalBalance":300.5,"lifetimeEarned":500.75,"lifetimeWithdrawn":250.25,"currency":"USD","createdAt":"2025-10-24T12:00:00.000Z","updatedAt":"2025-11-20T15:30:00.000Z"}}}}},"401":{"description":"Unauthorized"}},"security":[{"bearer":[]}],"summary":"Get customer credits balance","tags":["Credits"]}},"/api/v1/customers/me/credits/transactions":{"get":{"description":"Retrieve paginated list of all credits transactions (earnings and withdrawals) for the authenticated customer","operationId":"CreditsController_getTransactions","parameters":[{"name":"limit","required":false,"in":"query","description":"Number of results to return (default: 50)","schema":{"default":50,"example":50,"type":"number"}},{"name":"offset","required":false,"in":"query","description":"Number of results to skip (default: 0)","schema":{"default":0,"example":0,"type":"number"}},{"name":"type","required":false,"in":"query","description":"Filter by transaction type","schema":{"enum":["EARN_RESALE","EARN_DISTRIBUTION","EARN_REWARD","EARN_REFERRAL","WITHDRAW","ADJUSTMENT"],"type":"string"}}],"responses":{"200":{"description":"Transaction history retrieved successfully","content":{"application/json":{"schema":{"example":{"transactions":[{"id":"550e8400-e29b-41d4-a716-446655440000","customerId":"550e8400-e29b-41d4-a716-446655440001","transactionType":"EARN_RESALE","amount":50,"currency":"USD","balanceBefore":200,"balanceAfter":250,"status":"COMPLETED","description":"Marketplace resale proceeds for NFT #1234","createdAt":"2025-11-20T15:30:00.000Z"}],"total":25,"limit":50,"offset":0}}}}},"401":{"description":"Unauthorized"}},"security":[{"bearer":[]}],"summary":"Get credits transaction history","tags":["Credits"]}},"/api/v1/customers/me/credits/withdraw":{"post":{"description":"Request a withdrawal of available credits. Minimum withdrawal amount is $10. Withdrawals are processed asynchronously.","operationId":"CreditsController_withdraw","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WithdrawCreditsDto"}}}},"responses":{"201":{"description":"Withdrawal request created successfully","content":{"application/json":{"schema":{"example":{"id":"550e8400-e29b-41d4-a716-446655440000","customerId":"550e8400-e29b-41d4-a716-446655440001","transactionType":"WITHDRAW","amount":100,"currency":"USD","balanceBefore":250,"balanceAfter":150,"status":"PROCESSING","withdrawalMethod":"bank_transfer","description":"Withdrawal via bank_transfer","createdAt":"2025-11-20T15:30:00.000Z"}}}}},"400":{"description":"Bad request - Insufficient balance or invalid withdrawal details"},"401":{"description":"Unauthorized"}},"security":[{"bearer":[]}],"summary":"Withdraw credits to bank account or wallet","tags":["Credits"]}},"/api/v1/customers/me/credits/../coin":{"get":{"operationId":"CreditsController_getCoinBalance","parameters":[],"responses":{"200":{"description":""}},"security":[{"bearer":[]}],"summary":"Get PXL8 coin balance","tags":["Credits"]}},"/api/v1/customers/me/credits/../coin/transactions":{"get":{"operationId":"CreditsController_getCoinTransactions","parameters":[{"name":"limit","required":false,"in":"query","description":"Number of results to return","schema":{"default":50,"example":50,"type":"number"}},{"name":"offset","required":false,"in":"query","description":"Number of results to skip","schema":{"default":0,"example":0,"type":"number"}},{"name":"type","required":false,"in":"query","description":"Filter by transaction type","schema":{"example":"EARN_RESALE","type":"string","enum":["EARN_RESALE","EARN_DISTRIBUTION","EARN_REWARD","EARN_REFERRAL","WITHDRAW","ADJUSTMENT"]}}],"responses":{"200":{"description":""}},"security":[{"bearer":[]}],"summary":"Get PXL8 coin transaction history","tags":["Credits"]}}},"info":{"title":"PXL8 Customers API","description":"Customer Management API for Web3 RWA Platform - Supports both custodial and self-custodial customers","version":"1.0","contact":{}},"tags":[{"name":"Customers","description":"Customer profile management and custody operations"},{"name":"Holdings","description":"Customer asset holdings and portfolio tracking"},{"name":"Custodial","description":"Custodial transactions and internal ledger"}],"servers":[{"url":"https://api.pxl8.io","description":"Production API"},{"url":"http://localhost:3008","description":"Local Development"}],"components":{"securitySchemes":{"bearer":{"scheme":"bearer","bearerFormat":"JWT","type":"http"}},"schemas":{"CreateCustomerDto":{"type":"object","properties":{"companyId":{"type":"string","description":"Company ID","example":"550e8400-e29b-41d4-a716-446655440000"},"clerkUserId":{"type":"string","description":"Clerk User ID (for authentication integration)","example":"user_2NNEqL2nrIRdJ194ndJqAHwEfxC"},"email":{"type":"string","description":"Customer email address","example":"john.doe@example.com"},"firstName":{"type":"string","description":"Customer first name","example":"John"},"lastName":{"type":"string","description":"Customer last name","example":"Doe"},"phoneNumber":{"type":"string","description":"Customer phone number","example":"+1-555-123-4567"},"custodyType":{"type":"string","description":"Custody type for the customer","enum":["CUSTODIAL","SELF_CUSTODIAL"],"example":"CUSTODIAL"},"walletAddress":{"type":"string","description":"Wallet address (required for self-custodial customers)","example":"0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb"},"custodialAccountId":{"type":"string","description":"Custodial account ID (auto-generated if not provided for custodial customers)","example":"550e8400-e29b-41d4-a716-446655440001"},"metadata":{"type":"object","description":"Additional metadata","example":{"source":"web_signup","referrer":"organic"}}},"required":["companyId","email","custodyType"]},"UpdateCustomerDto":{"type":"object","properties":{"email":{"type":"string","description":"Customer email address","example":"john.doe@example.com"},"firstName":{"type":"string","description":"Customer first name","example":"John"},"lastName":{"type":"string","description":"Customer last name","example":"Doe"},"phoneNumber":{"type":"string","description":"Customer phone number","example":"+1-555-123-4567"},"metadata":{"type":"object","description":"Additional metadata","example":{"preferences":{"newsletter":true}}}}},"CreateCustodialTransactionDto":{"type":"object","properties":{"customerId":{"type":"string","description":"Customer ID","example":"550e8400-e29b-41d4-a716-446655440000"},"companyId":{"type":"string","description":"Company ID","example":"550e8400-e29b-41d4-a716-446655440001"},"assetId":{"type":"string","description":"Asset ID","example":"550e8400-e29b-41d4-a716-446655440002"},"transactionType":{"type":"string","description":"Transaction type","enum":["DEPOSIT","WITHDRAWAL","PURCHASE","SALE","TRANSFER_IN","TRANSFER_OUT","DISTRIBUTION","REWARD","FEE","ADJUSTMENT"],"example":"DEPOSIT"},"amount":{"type":"string","description":"Transaction amount (as string to support high precision)","example":"100.5"},"usdValue":{"type":"number","description":"USD value of the transaction","example":500.25},"referenceId":{"type":"string","description":"Reference ID (e.g., payment ID, order ID)","example":"payment_abc123"},"description":{"type":"string","description":"Transaction description","example":"Initial token purchase"},"metadata":{"type":"object","description":"Additional metadata","example":{"source":"payment_gateway","gateway":"stripe"}}},"required":["customerId","companyId","assetId","transactionType","amount"]},"PortfolioReturnsResponseDto":{"type":"object","properties":{"period":{"type":"string","description":"Time period for the returns calculation","example":"30d"},"startDate":{"format":"date-time","type":"string","description":"Start date of the period (UTC)","example":"2024-10-20T00:00:00.000Z"},"endDate":{"format":"date-time","type":"string","description":"End date of the period (UTC)","example":"2024-11-20T00:00:00.000Z"},"realizedGains":{"type":"number","description":"Realized gains from completed sales in the period (USD)","example":1500},"unrealizedGains":{"type":"number","description":"Unrealized gains from current holdings (USD)","example":2500},"totalReturns":{"type":"number","description":"Total returns (realized + unrealized) (USD)","example":4000},"totalInvested":{"type":"number","description":"Total amount invested (sum of cost basis) (USD)","example":10000},"returnOnInvestment":{"type":"number","description":"Return on investment as a percentage","example":40},"portfolioValueAtStart":{"type":"number","description":"Portfolio value at the start of the period (USD)","example":10000},"portfolioValueAtEnd":{"type":"number","description":"Portfolio value at the end of the period (current value) (USD)","example":14000},"changeInValue":{"type":"number","description":"Change in portfolio value during the period (USD)","example":4000},"changePercentage":{"type":"number","description":"Change in portfolio value as a percentage","example":40},"transactionsSummary":{"type":"object","description":"Summary of transaction counts during the period","example":{"purchases":5,"sales":2,"deposits":3,"withdrawals":1}}},"required":["period","startDate","endDate","realizedGains","unrealizedGains","totalReturns","totalInvested","returnOnInvestment","portfolioValueAtStart","portfolioValueAtEnd","changeInValue","changePercentage","transactionsSummary"]},"CustomerSettingsResponseDto":{"type":"object","properties":{"settingsId":{"type":"string","description":"Settings ID","example":"550e8400-e29b-41d4-a716-446655440000"},"customerId":{"type":"string","description":"Customer ID","example":"550e8400-e29b-41d4-a716-446655440001"},"displayCurrency":{"type":"string","description":"Display currency (3-letter ISO code)","example":"USD"},"returnCalculationMethod":{"type":"string","description":"Return calculation method","enum":["TIME_WEIGHTED","MONEY_WEIGHTED"],"example":"TIME_WEIGHTED"},"notificationsEnabled":{"type":"boolean","description":"Whether general notifications are enabled","example":true},"priceAlertsEnabled":{"type":"boolean","description":"Whether price alerts are enabled","example":false},"updatedAt":{"format":"date-time","type":"string","description":"Last updated timestamp","example":"2025-11-20T12:00:00.000Z"}},"required":["settingsId","customerId","displayCurrency","returnCalculationMethod","notificationsEnabled","priceAlertsEnabled","updatedAt"]},"UpdateCustomerSettingsDto":{"type":"object","properties":{"displayCurrency":{"type":"string","description":"Display currency (3-letter ISO code)","example":"USD"},"returnCalculationMethod":{"type":"string","description":"Return calculation method","enum":["TIME_WEIGHTED","MONEY_WEIGHTED"],"example":"TIME_WEIGHTED"},"notificationsEnabled":{"type":"boolean","description":"Enable/disable general notifications","example":true},"priceAlertsEnabled":{"type":"boolean","description":"Enable/disable price alerts","example":false}}},"BankTransferDetails":{"type":"object","properties":{"accountNumber":{"type":"string","description":"Bank account number","example":"1234567890"},"routingNumber":{"type":"string","description":"Bank routing number","example":"021000021"},"accountHolderName":{"type":"string","description":"Account holder name","example":"John Doe"}},"required":["accountNumber","routingNumber","accountHolderName"]},"PayPalDetails":{"type":"object","properties":{"paypalEmail":{"type":"string","description":"PayPal email address","example":"john.doe@example.com"}},"required":["paypalEmail"]},"CryptoWalletDetails":{"type":"object","properties":{"walletAddress":{"type":"string","description":"Cryptocurrency wallet address","example":"0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb"},"network":{"type":"string","description":"Blockchain network","example":"ethereum"}},"required":["walletAddress","network"]},"WithdrawCreditsDto":{"type":"object","properties":{"amount":{"type":"number","description":"Amount to withdraw in USD","example":100,"minimum":10},"method":{"type":"string","description":"Withdrawal method","enum":["bank_transfer","paypal","crypto_wallet"],"example":"bank_transfer"},"bankTransfer":{"description":"Bank transfer details (required if method is bank_transfer)","allOf":[{"$ref":"#/components/schemas/BankTransferDetails"}]},"paypal":{"description":"PayPal details (required if method is paypal)","allOf":[{"$ref":"#/components/schemas/PayPalDetails"}]},"cryptoWallet":{"description":"Crypto wallet details (required if method is crypto_wallet)","allOf":[{"$ref":"#/components/schemas/CryptoWalletDetails"}]}},"required":["amount","method"]}}}}