# API-CONTRACTS-MASTER-MATRIX.md ## Matriz Maestra de Contratos API - Trading Platform Frontend **Proyecto:** trading-platform **Fecha:** 2026-01-25 **Total Endpoints:** 113 --- ## Tabla Maestra de Endpoints API ### OQI-001: Auth (15 endpoints) | # | Método | Endpoint | Componente Consumidor | Request Body | Response 200 | Estado | |---|--------|----------|----------------------|--------------|--------------|--------| | 1 | POST | `/auth/register` | Register.tsx | `{ email, password, name }` | `{ token, user }` | ✅ | | 2 | POST | `/auth/login` | Login.tsx | `{ email, password }` | `{ token, user, refreshToken }` | ✅ | | 3 | POST | `/auth/logout` | SecuritySettings | `{}` | `{ success: true }` | ✅ | | 4 | POST | `/auth/logout-all` | SecuritySettings | `{}` | `{ success: true }` | ✅ | | 5 | POST | `/auth/refresh` | AuthService (auto) | `{ refreshToken }` | `{ token }` | ❌ TODO | | 6 | POST | `/auth/forgot-password` | ForgotPassword | `{ email }` | `{ success: true }` | ✅ | | 7 | POST | `/auth/reset-password` | ResetPassword | `{ token, password }` | `{ success: true }` | ✅ | | 8 | POST | `/auth/verify-email` | VerifyEmail | `{ token }` | `{ success: true }` | ✅ | | 9 | POST | `/auth/phone/send-otp` | PhoneLoginForm | `{ phone }` | `{ success: true }` | ✅ | | 10 | POST | `/auth/phone/verify-otp` | PhoneLoginForm | `{ phone, code }` | `{ token, user }` | ✅ | | 11 | POST | `/auth/oauth/callback` | AuthCallback | `{ code, provider }` | `{ token, user }` | ✅ | | 12 | GET | `/auth/sessions` | SecuritySettings | - | `[ { id, device, ip, lastActive } ]` | ✅ | | 13 | DELETE | `/auth/sessions/:sessionId` | SessionsList | - | `{ success: true }` | ✅ | | 14 | POST | `/auth/2fa/enable` | SecuritySettings (UI falta) | `{ method: 'totp' }` | `{ qrCode, secret }` | ❌ TODO | | 15 | POST | `/auth/2fa/verify` | SecuritySettings (UI falta) | `{ code }` | `{ success: true }` | ❌ TODO | **Cobertura:** 87% (13/15) --- ### OQI-002: Educación (14 endpoints) | # | Método | Endpoint | Componente Consumidor | Request Body | Response 200 | Estado | |---|--------|----------|----------------------|--------------|--------------|--------| | 16 | GET | `/education/categories` | Courses (filtros) | - | `[ { id, name, slug } ]` | ✅ | | 17 | GET | `/education/courses` | Courses | `?category=&level=&search=&sort=&page=&limit=` | `{ courses: [], total, page }` | ✅ | | 18 | GET | `/education/courses/:slug` | CourseDetail | - | `{ id, title, modules: [...] }` | ✅ | | 19 | POST | `/education/courses/:courseId/enroll` | CourseDetail (botón) | `{}` | `{ enrollmentId }` | ✅ | | 20 | GET | `/education/lessons/:lessonId` | Lesson | - | `{ id, title, videoUrl, content }` | ✅ | | 21 | POST | `/education/lessons/:lessonId/progress` | VideoProgressPlayer | `{ progress: 0-100, timestamp }` | `{ success: true }` | ✅ | | 22 | POST | `/education/lessons/:lessonId/complete` | Lesson (auto) | `{}` | `{ xpGained, badge? }` | ✅ | | 23 | GET | `/education/quizzes/:quizId` | Quiz | - | `{ id, questions: [...] }` | ✅ | | 24 | POST | `/education/quizzes/:quizId/submit` | Quiz (submit) | `{ answers: [] }` | `{ score, passed, xpGained }` | ✅ | | 25 | GET | `/education/achievements` | MyLearning | - | `[ { id, title, icon, earnedAt } ]` | ✅ | | 26 | GET | `/education/leaderboard` | Leaderboard | `?period=all_time\|week\|month` | `[ { rank, userId, name, xp } ]` | ✅ | | 27 | GET | `/education/gamification/profile` | MyLearning (stats) | - | `{ xp, level, badges, streak }` | ✅ | | 28 | GET | `/education/enrollments` | MyLearning | - | `[ { courseId, progress, lastAccessed } ]` | ✅ | | 29 | POST | `/education/videos/upload` | Creator Dashboard (NO EXISTE) | `multipart/form-data (video)` | `{ videoId, processingStatus }` | ❌ FALTA | **Cobertura:** 93% (13/14) - Video upload bloqueante --- ### OQI-003: Trading (20 endpoints) | # | Método | Endpoint | Componente Consumidor | Request Body | Response 200 | Estado | |---|--------|----------|----------------------|--------------|--------------|--------| | 30 | GET | `/trading/market/klines/:symbol` | CandlestickChart | `?interval=1h&limit=500` | `[ [timestamp, open, high, low, close, volume] ]` | ✅ | | 31 | GET | `/trading/market/price/:symbol` | SymbolInfoPanel | - | `{ symbol, price, change24h }` | ✅ | | 32 | GET | `/trading/market/ticker/:symbol` | SymbolInfoPanel | - | `{ high, low, volume, ... }` | ✅ | | 33 | GET | `/trading/market/order-book/:symbol` | OrderBookPanel | `?limit=20` | `{ bids: [], asks: [] }` | ✅ | | 34 | GET | `/trading/indicators/sma/:symbol` | IndicatorConfigPanel | `?period=20&interval=1h` | `[ { timestamp, value } ]` | ⚠️ NO RENDERIZA | | 35 | GET | `/trading/indicators/ema/:symbol` | IndicatorConfigPanel | `?period=12&interval=1h` | `[ { timestamp, value } ]` | ⚠️ NO RENDERIZA | | 36 | GET | `/trading/indicators/rsi/:symbol` | IndicatorConfigPanel | `?period=14&interval=1h` | `[ { timestamp, value } ]` | ⚠️ NO RENDERIZA | | 37 | GET | `/trading/indicators/macd/:symbol` | IndicatorConfigPanel | `?interval=1h` | `[ { timestamp, macd, signal, histogram } ]` | ⚠️ NO RENDERIZA | | 38 | GET | `/trading/indicators/bollinger/:symbol` | IndicatorConfigPanel | `?period=20&stdDev=2&interval=1h` | `[ { timestamp, upper, middle, lower } ]` | ⚠️ NO RENDERIZA | | 39 | GET | `/trading/paper/account` | PaperTradingPanel | - | `{ balance, equity, margin, ... }` | ✅ | | 40 | GET | `/trading/paper/positions` | PositionsList | - | `[ { symbol, side, size, entryPrice, pnl } ]` | ✅ | | 41 | GET | `/trading/paper/orders` | TradesHistory | `?status=open\|closed` | `[ { id, symbol, side, type, status } ]` | ✅ | | 42 | POST | `/trading/paper/orders` | OrderForm | `{ symbol, side, type, quantity, price? }` | `{ orderId, status }` | ✅ | | 43 | DELETE | `/trading/paper/orders/:orderId` | TradesHistory (cancel) | - | `{ success: true }` | ✅ | | 44 | GET | `/trading/alerts` | AlertsPanel | - | `[ { id, symbol, condition, price } ]` | ✅ | | 45 | POST | `/trading/alerts` | AlertsPanel (crear) | `{ symbol, condition, price }` | `{ alertId }` | ✅ | | 46 | DELETE | `/trading/alerts/:alertId` | AlertsPanel (eliminar) | - | `{ success: true }` | ✅ | | 47 | POST | `/trading/drawings/save` | ChartDrawingToolsPanel | `{ symbol, interval, drawings: [] }` | `{ success: true }` | ❌ FALTA | | 48 | GET | `/trading/drawings/:symbol` | ChartDrawingToolsPanel | `?interval=1h` | `{ drawings: [] }` | ❌ FALTA | | 49 | WebSocket | `ws://localhost:3082/trading` | useTradingWebSocket | - | Real-time price updates | ❌ FALTA | **Cobertura:** 65% (13/20) - Indicadores renderizado, drawings persistencia, WebSocket faltan --- ### OQI-004: Inversión (10 endpoints) | # | Método | Endpoint | Componente Consumidor | Request Body | Response 200 | Estado | |---|--------|----------|----------------------|--------------|--------------|--------| | 50 | GET | `/investment/accounts/summary` | Investment (overview) | - | `{ totalValue, totalGain, accounts: [] }` | ✅ | | 51 | GET | `/investment/products` | Products | - | `[ { id, name, type, minInvestment, expectedReturn } ]` | ✅ | | 52 | GET | `/investment/products/:productId` | ProductDetail | - | `{ id, name, description, performance: [] }` | ✅ | | 53 | GET | `/investment/products/:productId/performance` | ProductDetail (chart) | `?period=1M\|3M\|1Y` | `[ { date, value } ]` | ✅ | | 54 | GET | `/investment/accounts/:accountId` | AccountDetail | - | `{ id, balance, product, createdAt }` | ✅ | | 55 | GET | `/investment/accounts/:accountId/transactions` | Transactions | `?type=&startDate=&endDate=` | `[ { id, type, amount, date } ]` | ✅ | | 56 | GET | `/investment/accounts/:accountId/withdrawals` | Withdrawals | - | `[ { id, amount, status, requestedAt } ]` | ✅ | | 57 | POST | `/investment/accounts/:accountId/deposits` | DepositForm | `{ amount, paymentMethodId }` | `{ depositId }` | ✅ | | 58 | POST | `/investment/accounts/:accountId/withdrawals` | WithdrawForm | `{ amount, bankAccountId }` | `{ withdrawalId }` | ✅ | | 59 | POST | `/investment/accounts` | CreateAccountForm (NO EXISTE) | `{ productId, initialAmount }` | `{ accountId }` | ❌ FALTA | **Cobertura:** 90% (9/10) - Creación cuentas bloqueante --- ### OQI-005: Pagos Stripe (24 endpoints) | # | Método | Endpoint | Componente Consumidor | Request Body | Response 200 | Estado | |---|--------|----------|----------------------|--------------|--------------|--------| | 60 | GET | `/payments/plans` | Pricing | - | `[ { id, name, price, features: [] } ]` | ✅ | | 61 | GET | `/payments/plans/:slug` | Pricing (detalle) | - | `{ id, name, price, features, stripePriceId }` | ✅ | | 62 | GET | `/payments/subscription` | Billing | - | `{ id, planId, status, currentPeriodEnd }` | ✅ | | 63 | POST | `/payments/subscription` | Pricing (subscribe) | `{ planId, paymentMethodId }` | `{ subscriptionId }` | ✅ | | 64 | POST | `/payments/subscription/change-plan` | SubscriptionUpgradeFlow | `{ newPlanId }` | `{ subscriptionId, proratedAmount }` | ✅ | | 65 | POST | `/payments/subscription/cancel` | Billing (cancel) | `{}` | `{ success: true }` | ✅ | | 66 | POST | `/payments/subscription/reactivate` | Billing (reactivate) | `{}` | `{ success: true }` | ✅ | | 67 | GET | `/payments/methods` | PaymentMethodsList | - | `[ { id, brand, last4, expiryMonth, expiryYear } ]` | ✅ | | 68 | POST | `/payments/methods` | PaymentMethodForm | `{ cardNumber, expMonth, expYear, cvc }` | `{ methodId }` | ⚠️ PCI-DSS RISK | | 69 | POST | `/payments/methods/default` | PaymentMethodsList | `{ methodId }` | `{ success: true }` | ✅ | | 70 | DELETE | `/payments/methods/:methodId` | PaymentMethodsList | - | `{ success: true }` | ✅ | | 71 | POST | `/payments/checkout` | Pricing (Hosted Checkout) | `{ planId, successUrl, cancelUrl }` | `{ sessionId, checkoutUrl }` | ✅ | | 72 | POST | `/payments/billing-portal` | Billing (Stripe Portal) | `{ returnUrl }` | `{ portalUrl }` | ✅ | | 73 | GET | `/payments/invoices` | InvoiceList | `?limit=10` | `[ { id, amount, status, date, pdfUrl } ]` | ✅ | | 74 | GET | `/payments/invoices/:invoiceId` | InvoiceDetail | - | `{ id, lineItems: [], total, pdfUrl }` | ✅ | | 75 | GET | `/payments/invoices/:invoiceId/pdf` | InvoiceDetail (download) | - | `PDF binary` | ✅ | | 76 | GET | `/payments/wallet` | WalletCard | - | `{ balance, available, pending }` | ✅ | | 77 | POST | `/payments/wallet/deposit` | WalletDepositModal | `{ amount, paymentMethodId }` | `{ transactionId }` | ✅ | | 78 | POST | `/payments/wallet/withdraw` | WalletWithdrawModal | `{ amount, bankAccountId }` | `{ withdrawalId }` | ✅ | | 79 | GET | `/payments/wallet/transactions` | TransactionHistory | `?type=&startDate=&endDate=&page=&limit=` | `[ { id, type, amount, status, date } ]` | ✅ | | 80 | POST | `/payments/coupons/validate` | CouponForm | `{ code }` | `{ valid: true, discount: 20 }` | ✅ | | 81 | POST | `/payments/refunds` | RefundModal (NO EXISTE) | `{ invoiceId, reason }` | `{ refundId }` | ❌ FALTA | | 82 | GET | `/payments/usage` | Billing (uso plan) | - | `{ limit, used, percentage }` | ✅ | | 83 | POST | `/payments/payment-intent` | PaymentMethodForm (Stripe.js) | `{ amount }` | `{ clientSecret }` | ❌ FALTA | **Cobertura:** 96% (23/24) - Payment Intent (PCI-DSS) crítico falta --- ### OQI-006: ML Signals (12 endpoints) | # | Método | Endpoint | Componente Consumidor | Request Body | Response 200 | Estado | |---|--------|----------|----------------------|--------------|--------------|--------| | 84 | GET | `/api/v1/signals/active` | MLDashboard | `?symbol=&status=active` | `[ { id, symbol, direction, entry, sl, tp, confidence } ]` | ✅ | | 85 | GET | `/api/v1/signals/latest/:symbol` | PredictionCard | - | `{ signal: {...}, validUntil }` | ✅ | | 86 | GET | `/api/v1/amd/detect/:symbol` | AMDPhaseIndicator | `?timeframe=1H` | `{ currentPhase, probabilities: {...}, keyLevels: [] }` | ✅ | | 87 | GET | `/api/v1/predict/range/:symbol` | RangePredictor | `?timeframe=1H` | `{ predictedHigh, predictedLow, confidence }` | ✅ | | 88 | POST | `/api/v1/signals/generate` | MLDashboard (refresh) | `{ symbol, timeframe }` | `{ signal: {...} }` | ✅ | | 89 | POST | `/api/ict/:symbol` | ICTAnalysisCard | `{ timeframe: '1H' }` | `{ orderBlocks: [], fvg: [], bias: 'bullish' }` | ✅ | | 90 | POST | `/api/ensemble/:symbol` | EnsembleSignalCard | `{ timeframe: '1H' }` | `{ strategies: [], aggregatedSignal: {...} }` | ✅ | | 91 | GET | `/api/ensemble/quick/:symbol` | EnsembleSignalCard (quick) | - | `{ signal: {...} }` | ✅ | | 92 | POST | `/api/scan` | MLDashboard (multi-symbol) | `{ symbols: [], timeframe }` | `[ { symbol, signal: {...} } ]` | ✅ | | 93 | GET | `/api/v1/backtest/results/:strategyId` | BacktestResultsVisualization | - | `{ trades: [], metrics: { winRate, profitFactor } }` | ✅ | | 94 | WebSocket | `ws://localhost:3083/signals` | useMLWebSocket | - | Real-time signal updates | ❌ FALTA | | 95 | POST | `/api/v1/signals/:signalId/export` | MLDashboard (export) | `{ format: 'csv' \| 'pdf' }` | `Blob (file download)` | ❌ FALTA | **Cobertura:** 83% (10/12) - WebSocket y exportación faltan --- ### OQI-007: LLM Agent (6 endpoints) | # | Método | Endpoint | Componente Consumidor | Request Body | Response 200 | Estado | |---|--------|----------|----------------------|--------------|--------------|--------| | 96 | POST | `/api/v1/llm/sessions` | Assistant (new chat) | `{ title? }` | `{ sessionId, title }` | ✅ | | 97 | GET | `/api/v1/llm/sessions` | ConversationHistory | - | `[ { id, title, createdAt, messageCount } ]` | ✅ | | 98 | GET | `/api/v1/llm/sessions/:sessionId` | Assistant (load) | - | `{ id, title, messages: [] }` | ✅ | | 99 | POST | `/api/v1/llm/sessions/:sessionId/chat` | ChatInput (send) | `{ content, role: 'user' }` | `{ id, role: 'assistant', content, toolCalls: [] }` | ✅ | | 100 | DELETE | `/api/v1/llm/sessions/:sessionId` | ConversationHistory (delete) | - | `{ success: true }` | ✅ | | 101 | GET | `/api/v1/llm/analyze/:symbol` | Assistant (quick analyze) | - | `{ analysis: '...' }` | ✅ | **Cobertura:** 100% (6/6) - Backend funcional, falta persistencia BD y streaming --- ### OQI-008: Portfolio (12 endpoints) | # | Método | Endpoint | Componente Consumidor | Request Body | Response 200 | Estado | |---|--------|----------|----------------------|--------------|--------------|--------| | 102 | GET | `/portfolio/portfolios` | PortfolioDashboard | - | `[ { id, name, totalValue, allocations: [] } ]` | ✅ | | 103 | GET | `/portfolio/portfolios/:portfolioId` | PortfolioDashboard (detalle) | - | `{ id, name, allocations: [], performance: [] }` | ✅ | | 104 | POST | `/portfolio/portfolios` | CreatePortfolio | `{ name, riskProfile, allocations: [] }` | `{ portfolioId }` | ✅ | | 105 | PUT | `/portfolio/portfolios/:portfolioId` | EditAllocations | `{ name?, allocations? }` | `{ success: true }` | ✅ | | 106 | DELETE | `/portfolio/portfolios/:portfolioId` | PortfolioDashboard (delete) | - | `{ success: true }` | ✅ | | 107 | GET | `/portfolio/portfolios/:portfolioId/performance` | PerformanceChart | `?period=1M\|3M\|1Y` | `[ { date, value } ]` | ✅ | | 108 | PUT | `/portfolio/portfolios/:portfolioId/allocations` | EditAllocations (save) | `{ allocations: [] }` | `{ success: true }` | ✅ | | 109 | GET | `/portfolio/goals` | PortfolioDashboard (goals) | - | `[ { id, name, targetAmount, deadline } ]` | ✅ | | 110 | POST | `/portfolio/goals` | CreateGoal | `{ name, targetAmount, deadline }` | `{ goalId }` | ✅ | | 111 | DELETE | `/portfolio/goals/:goalId` | PortfolioDashboard (delete goal) | - | `{ success: true }` | ✅ | | 112 | GET | `/portfolio/recommendations/rebalance/:portfolioId` | RebalanceCard | - | `{ recommended: [], changes: [] }` | ✅ | | 113 | POST | `/portfolio/optimize/:portfolioId` | OptimizeButton (NO EXISTE) | `{ method: 'markowitz', constraints: {} }` | `{ optimizedAllocations: [] }` | ❌ FALTA | **Cobertura:** 92% (11/12) - Markowitz optimization bloqueante --- ### OQI-009: MT4 Gateway (0 endpoints - TODO completo) | # | Método | Endpoint | Componente Consumidor | Request Body | Response 200 | Estado | |---|--------|----------|----------------------|--------------|--------------|--------| | - | - | TODOS FALTANTES | MT4 components (stubs) | - | - | ❌ 0% | **Cobertura:** 0% - Epic completo NO IMPLEMENTADO --- ## Resumen Global | Epic | Total Endpoints | Implementados | Faltantes | Cobertura | |------|----------------|---------------|-----------|-----------| | OQI-001 (Auth) | 15 | 13 | 2 | 87% | | OQI-002 (Educación) | 14 | 13 | 1 | 93% | | OQI-003 (Trading) | 20 | 13 | 7 | 65% | | OQI-004 (Inversión) | 10 | 9 | 1 | 90% | | OQI-005 (Pagos) | 24 | 23 | 1 | 96% | | OQI-006 (ML Signals) | 12 | 10 | 2 | 83% | | OQI-007 (LLM Agent) | 6 | 6 | 0 | 100% | | OQI-008 (Portfolio) | 12 | 11 | 1 | 92% | | OQI-009 (MT4) | 0 | 0 | 0+ | 0% | | **TOTAL** | **113** | **98** | **15** | **87%** | --- ## Endpoints Críticos Faltantes (Bloqueantes) | Epic | Endpoint | Criticidad | Impacto | |------|----------|------------|---------| | OQI-001 | POST /auth/refresh | P0 | Token refresh manual | | OQI-002 | POST /education/videos/upload | P0 | Video upload bloqueado | | OQI-003 | WebSocket trading | P0 | Real-time data (polling 30s) | | OQI-003 | POST /trading/drawings/save | P1 | Drawing tools orphaned | | OQI-004 | POST /investment/accounts | P0 | Creación cuentas bloqueada | | OQI-005 | POST /payments/payment-intent | P0 | PCI-DSS non-compliant | | OQI-006 | WebSocket signals | P1 | Polling 60s vs real-time | | OQI-008 | POST /portfolio/optimize | P0 | Markowitz optimization | | OQI-009 | ALL | P0 | Epic completo NO FUNCIONA | --- **Actualizado:** 2026-01-25 **Próxima actualización:** Después de implementar Fase 1