Changes include: - Updated architecture documentation - Enhanced module definitions (OQI-001 to OQI-008) - ML integration documentation updates - Trading strategies documentation - Orchestration and inventory updates - Docker configuration updates 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
21 KiB
| id | title | type | status | priority | epic | project | version | dates | tags | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| ET-MKT-002 | Especificacion de API - Marketplace | technical-spec | Draft | High | OQI-009 | trading-platform | 1.0.0 |
|
|
ET-MKT-002: Especificacion de API
Resumen
Este documento define los endpoints REST API para el modulo de Marketplace (OQI-009). Incluye endpoints para productos, compras, suscripciones, asesoria y visualizacion premium.
Base URL
/api/v1/marketplace
Autenticacion
Todos los endpoints requieren autenticacion via JWT Bearer token, excepto los marcados como publicos.
Authorization: Bearer <jwt_token>
Endpoints de Productos
GET /products
Lista productos del marketplace.
Query Parameters:
| Parametro | Tipo | Requerido | Descripcion |
|---|---|---|---|
| category | string | No | Filtrar por categoria (slug) |
| type | string | No | Filtrar por tipo de producto |
| search | string | No | Busqueda en nombre/descripcion |
| featured | boolean | No | Solo productos destacados |
| sort | string | No | Ordenamiento: price_asc, price_desc, rating, newest |
| page | number | No | Pagina (default: 1) |
| limit | number | No | Items por pagina (default: 12, max: 50) |
Response 200:
{
"data": [
{
"id": "550e8400-e29b-41d4-a716-446655440001",
"name": "Pro Signal Pack",
"slug": "pro-signal-pack",
"shortDescription": "200 senales ML de alta confianza",
"type": "signal_pack",
"price": 29.00,
"currency": "USD",
"billingType": "one_time",
"category": {
"id": "cat-001",
"name": "Senales",
"slug": "signals"
},
"isFeatured": true,
"metadata": {
"credits": 200,
"validityDays": 60,
"minConfidence": 80
}
}
],
"pagination": {
"page": 1,
"limit": 12,
"total": 7,
"totalPages": 1
}
}
GET /products/:id
Obtiene detalle de un producto.
Response 200:
{
"id": "550e8400-e29b-41d4-a716-446655440001",
"name": "Pro Signal Pack",
"slug": "pro-signal-pack",
"description": "Paquete de 200 senales ML de alta confianza...",
"shortDescription": "200 senales ML de alta confianza",
"type": "signal_pack",
"price": 29.00,
"currency": "USD",
"billingType": "one_time",
"subscriptionInterval": null,
"category": {
"id": "cat-001",
"name": "Senales",
"slug": "signals"
},
"isFeatured": true,
"isActive": true,
"metadata": {
"credits": 200,
"validityDays": 60,
"minConfidence": 80
},
"relatedProducts": [
{
"id": "550e8400-e29b-41d4-a716-446655440002",
"name": "Basic Signal Pack",
"price": 9.00
}
],
"createdAt": "2026-01-04T00:00:00Z"
}
GET /categories
Lista categorias de productos.
Response 200:
{
"data": [
{
"id": "cat-001",
"name": "Senales",
"slug": "signals",
"description": "Paquetes de senales ML premium",
"icon": "signal",
"productCount": 3
}
]
}
Endpoints de Compras
POST /purchases
Crea una nueva compra.
Request Body:
{
"productId": "550e8400-e29b-41d4-a716-446655440001",
"paymentMethodId": "pm_1234567890",
"quantity": 1,
"acceptedTerms": true
}
Response 201:
{
"id": "purchase-001",
"status": "completed",
"product": {
"id": "550e8400-e29b-41d4-a716-446655440001",
"name": "Pro Signal Pack"
},
"quantity": 1,
"unitPrice": 29.00,
"totalPrice": 29.00,
"currency": "USD",
"paymentId": "pi_abc123",
"completedAt": "2026-01-04T12:00:00Z",
"receipt": {
"url": "https://receipts.stripe.com/...",
"emailSent": true
},
"activation": {
"type": "signal_credits",
"creditsAdded": 200,
"newBalance": 215,
"expiresAt": "2026-03-04T12:00:00Z"
}
}
Response 402 (Pago Fallido):
{
"error": {
"code": "PAYMENT_FAILED",
"message": "El pago no pudo ser procesado",
"details": {
"declineCode": "insufficient_funds"
}
}
}
GET /purchases
Lista compras del usuario autenticado.
Query Parameters:
| Parametro | Tipo | Descripcion |
|---|---|---|
| status | string | Filtrar por estado |
| productType | string | Filtrar por tipo de producto |
| from | date | Fecha desde |
| to | date | Fecha hasta |
| page | number | Pagina |
| limit | number | Items por pagina |
Response 200:
{
"data": [
{
"id": "purchase-001",
"product": {
"id": "prod-001",
"name": "Pro Signal Pack",
"type": "signal_pack"
},
"totalPrice": 29.00,
"currency": "USD",
"status": "completed",
"completedAt": "2026-01-04T12:00:00Z"
}
],
"pagination": {
"page": 1,
"limit": 20,
"total": 5
}
}
GET /purchases/:id
Obtiene detalle de una compra.
Response 200:
{
"id": "purchase-001",
"product": {
"id": "prod-001",
"name": "Pro Signal Pack",
"type": "signal_pack",
"price": 29.00
},
"quantity": 1,
"unitPrice": 29.00,
"totalPrice": 29.00,
"currency": "USD",
"status": "completed",
"paymentMethod": "visa ****4242",
"completedAt": "2026-01-04T12:00:00Z",
"receipt": {
"url": "https://receipts.stripe.com/..."
}
}
Endpoints de Suscripciones
POST /subscriptions
Crea una nueva suscripcion.
Request Body:
{
"productId": "550e8400-e29b-41d4-a716-446655440003",
"paymentMethodId": "pm_1234567890",
"acceptedTerms": true
}
Response 201:
{
"id": "sub-001",
"status": "active",
"product": {
"id": "prod-003",
"name": "Unlimited Signals"
},
"price": 49.00,
"currency": "USD",
"interval": "monthly",
"currentPeriodStart": "2026-01-04T00:00:00Z",
"currentPeriodEnd": "2026-02-04T00:00:00Z",
"cancelAtPeriodEnd": false
}
GET /subscriptions
Lista suscripciones del usuario.
Response 200:
{
"data": [
{
"id": "sub-001",
"product": {
"id": "prod-003",
"name": "Unlimited Signals",
"type": "signal_pack"
},
"status": "active",
"price": 49.00,
"interval": "monthly",
"currentPeriodEnd": "2026-02-04T00:00:00Z",
"cancelAtPeriodEnd": false
}
]
}
DELETE /subscriptions/:id
Cancela una suscripcion.
Request Body:
{
"reason": "No longer needed",
"cancelImmediately": false
}
Response 200:
{
"id": "sub-001",
"status": "active",
"cancelAtPeriodEnd": true,
"canceledAt": "2026-01-04T12:00:00Z",
"accessEndsAt": "2026-02-04T00:00:00Z",
"message": "Tu suscripcion se cancelara al final del periodo actual"
}
Endpoints de Creditos de Senales
GET /credits
Obtiene creditos de senales del usuario.
Response 200:
{
"totalAvailable": 150,
"hasUnlimited": false,
"credits": [
{
"id": "credit-001",
"productName": "Pro Signal Pack",
"initialAmount": 200,
"remainingAmount": 150,
"expiresAt": "2026-03-04T12:00:00Z",
"isUnlimited": false
}
],
"usage": {
"today": 3,
"thisWeek": 15,
"thisMonth": 50
}
}
GET /credits/history
Historial de uso de creditos.
Response 200:
{
"data": [
{
"id": "delivery-001",
"signal": {
"id": "sig-001",
"symbol": "BTC/USDT",
"action": "BUY",
"confidence": 87.5
},
"deliveredAt": "2026-01-04T14:30:00Z",
"channel": "both"
}
],
"pagination": {
"page": 1,
"limit": 20,
"total": 50
}
}
Endpoints de Asesoria
GET /advisors
Lista asesores disponibles.
Query Parameters:
| Parametro | Tipo | Descripcion |
|---|---|---|
| specialty | string | Filtrar por especialidad |
| language | string | Filtrar por idioma |
| minRating | number | Rating minimo |
| sort | string | rating, price, experience |
| page | number | Pagina |
| limit | number | Items por pagina |
Response 200:
{
"data": [
{
"id": "advisor-001",
"displayName": "Maria Garcia, CFA",
"title": "Crypto Trading Expert",
"shortBio": "10 anos de experiencia en mercados crypto...",
"specialties": ["crypto", "defi", "technical_analysis"],
"experienceYears": 10,
"languages": ["es", "en"],
"rating": 4.9,
"reviewCount": 85,
"completedSessions": 120,
"priceFrom": 49.00,
"profileImageUrl": "https://...",
"nextAvailable": "2026-01-05T09:00:00Z"
}
],
"pagination": {
"page": 1,
"limit": 10,
"total": 5
}
}
GET /advisors/:id
Obtiene perfil completo de un asesor.
Response 200:
{
"id": "advisor-001",
"displayName": "Maria Garcia, CFA",
"title": "Crypto Trading Expert",
"bio": "Analista certificada CFA con 10 anos de experiencia...",
"shortBio": "10 anos de experiencia en mercados crypto...",
"specialties": ["crypto", "defi", "technical_analysis"],
"experienceYears": 10,
"languages": ["es", "en"],
"rating": 4.9,
"reviewCount": 85,
"completedSessions": 120,
"profileImageUrl": "https://...",
"isVerified": true,
"sessionOptions": [
{
"duration": 30,
"price": 49.00,
"currency": "USD",
"includes": ["video", "notes"]
},
{
"duration": 60,
"price": 89.00,
"currency": "USD",
"includes": ["video", "notes", "action_plan"]
},
{
"duration": 90,
"price": 119.00,
"currency": "USD",
"includes": ["video", "notes", "action_plan", "follow_up"]
}
],
"reviews": [
{
"id": "review-001",
"rating": 5,
"comment": "Excelente sesion, muy profesional",
"userName": "Juan P.",
"createdAt": "2026-01-03T00:00:00Z"
}
]
}
GET /advisors/:id/availability
Obtiene disponibilidad de un asesor.
Query Parameters:
| Parametro | Tipo | Descripcion |
|---|---|---|
| duration | number | Duracion de sesion en minutos |
| timezone | string | Zona horaria del usuario |
| from | date | Fecha desde |
| to | date | Fecha hasta |
Response 200:
{
"advisorId": "advisor-001",
"duration": 60,
"timezone": "America/Mexico_City",
"slots": [
{
"date": "2026-01-06",
"times": ["09:00", "10:00", "11:00", "14:00", "15:00"]
},
{
"date": "2026-01-07",
"times": ["09:00", "10:00", "14:00"]
}
]
}
POST /advisory-sessions
Agenda una sesion de asesoria.
Request Body:
{
"advisorId": "advisor-001",
"productId": "prod-advisory-60",
"scheduledAt": "2026-01-06T10:00:00-06:00",
"timezone": "America/Mexico_City",
"paymentMethodId": "pm_1234567890",
"notes": "Quiero discutir mi estrategia de DeFi"
}
Response 201:
{
"id": "session-001",
"advisor": {
"id": "advisor-001",
"displayName": "Maria Garcia, CFA"
},
"duration": 60,
"scheduledAt": "2026-01-06T16:00:00Z",
"scheduledAtLocal": "2026-01-06T10:00:00-06:00",
"timezone": "America/Mexico_City",
"status": "scheduled",
"price": 89.00,
"currency": "USD",
"calEventId": "cal-event-123",
"joinUrl": null,
"confirmationEmailSent": true
}
GET /advisory-sessions
Lista sesiones del usuario.
Query Parameters:
| Parametro | Tipo | Descripcion |
|---|---|---|
| status | string | scheduled, completed, cancelled |
| from | date | Fecha desde |
| to | date | Fecha hasta |
Response 200:
{
"data": [
{
"id": "session-001",
"advisor": {
"id": "advisor-001",
"displayName": "Maria Garcia, CFA",
"profileImageUrl": "https://..."
},
"duration": 60,
"scheduledAt": "2026-01-06T16:00:00Z",
"status": "scheduled",
"joinUrl": "https://daily.co/room-xyz",
"canReschedule": true,
"canCancel": true
}
]
}
GET /advisory-sessions/:id
Obtiene detalle de una sesion.
Response 200:
{
"id": "session-001",
"advisor": {
"id": "advisor-001",
"displayName": "Maria Garcia, CFA",
"profileImageUrl": "https://..."
},
"duration": 60,
"scheduledAt": "2026-01-06T16:00:00Z",
"endedAt": null,
"status": "scheduled",
"joinUrl": "https://daily.co/room-xyz",
"recordingUrl": null,
"notes": {
"summary": null,
"recommendations": [],
"resources": [],
"followUpActions": []
},
"review": null,
"canReschedule": true,
"canCancel": true,
"cancellationPolicy": {
"fullRefundBefore": "2026-01-05T16:00:00Z",
"partialRefundBefore": "2026-01-06T04:00:00Z"
}
}
PATCH /advisory-sessions/:id
Reagenda una sesion.
Request Body:
{
"scheduledAt": "2026-01-07T14:00:00-06:00",
"timezone": "America/Mexico_City"
}
Response 200:
{
"id": "session-001",
"scheduledAt": "2026-01-07T20:00:00Z",
"status": "scheduled",
"message": "Sesion reagendada exitosamente"
}
DELETE /advisory-sessions/:id
Cancela una sesion.
Request Body:
{
"reason": "Schedule conflict"
}
Response 200:
{
"id": "session-001",
"status": "cancelled",
"cancelledAt": "2026-01-04T12:00:00Z",
"refund": {
"amount": 89.00,
"percentage": 100,
"status": "processing"
}
}
POST /advisory-sessions/:id/notes
Asesor agrega notas a la sesion.
Request Body:
{
"summary": "Discutimos estrategias de DeFi y riesgos...",
"recommendations": [
"Diversificar en multiples protocolos",
"Implementar stop-loss automaticos"
],
"resources": [
{
"title": "Guia de DeFi Seguro",
"url": "https://..."
}
],
"followUpActions": [
"Revisar portfolio actual",
"Configurar alertas de precio"
]
}
Response 201:
{
"id": "notes-001",
"sessionId": "session-001",
"createdAt": "2026-01-06T18:00:00Z",
"notificationSent": true
}
POST /advisory-sessions/:id/reviews
Usuario deja review de la sesion.
Request Body:
{
"rating": 5,
"comment": "Excelente sesion, Maria es muy profesional y conocedora",
"isPublic": true
}
Response 201:
{
"id": "review-001",
"rating": 5,
"comment": "Excelente sesion...",
"isPublic": true,
"createdAt": "2026-01-06T19:00:00Z"
}
Endpoints de Visualizacion Premium
GET /visualization/subscription
Obtiene estado de suscripcion de visualizacion.
Response 200:
{
"isActive": true,
"subscription": {
"id": "vis-sub-001",
"startedAt": "2026-01-01T00:00:00Z",
"expiresAt": "2026-02-01T00:00:00Z",
"cancelAtPeriodEnd": false
},
"features": [
"ml_indicators",
"unlimited_backtest",
"unlimited_alerts",
"multi_chart_4"
],
"limits": {
"alerts": -1,
"layouts": -1,
"backtestDays": -1,
"charts": 4
}
}
POST /visualization/subscribe
Crea suscripcion de visualizacion premium.
Request Body:
{
"paymentMethodId": "pm_1234567890",
"acceptedTerms": true
}
Response 201:
{
"subscription": {
"id": "vis-sub-001",
"status": "active",
"startedAt": "2026-01-04T00:00:00Z",
"expiresAt": "2026-02-04T00:00:00Z"
},
"features": [
"ml_indicators",
"unlimited_backtest",
"unlimited_alerts",
"multi_chart_4"
],
"message": "Visualizacion Premium activada"
}
GET /visualization/indicators
Lista indicadores disponibles.
Response 200:
{
"basic": [
{
"id": "sma",
"name": "Simple Moving Average",
"type": "overlay",
"available": true
},
{
"id": "rsi",
"name": "Relative Strength Index",
"type": "panel",
"available": true
}
],
"premium": [
{
"id": "ml_range_predictor",
"name": "Range Predictor",
"type": "overlay",
"description": "Predice rangos de precio",
"available": true,
"requiresPremium": true
},
{
"id": "ml_amd_detector",
"name": "AMD Detector",
"type": "overlay",
"description": "Detecta patrones AMD",
"available": true,
"requiresPremium": true
}
]
}
GET /visualization/layouts
Lista layouts guardados del usuario.
Response 200:
{
"data": [
{
"id": "layout-001",
"name": "Mi Layout Principal",
"isDefault": true,
"chartCount": 4,
"createdAt": "2026-01-03T00:00:00Z"
}
],
"limits": {
"max": -1,
"used": 3
}
}
POST /visualization/layouts
Guarda un nuevo layout.
Request Body:
{
"name": "Crypto Watch",
"layoutConfig": {
"grid": "2x2",
"charts": [
{"position": 0, "symbol": "BTC/USDT", "timeframe": "4H"},
{"position": 1, "symbol": "ETH/USDT", "timeframe": "4H"},
{"position": 2, "symbol": "SOL/USDT", "timeframe": "4H"},
{"position": 3, "symbol": "AVAX/USDT", "timeframe": "4H"}
]
},
"indicators": [
{"chartIndex": 0, "indicators": ["ml_range_predictor", "sma"]},
{"chartIndex": 1, "indicators": ["ml_amd_detector"]}
],
"isDefault": false
}
Response 201:
{
"id": "layout-002",
"name": "Crypto Watch",
"isDefault": false,
"createdAt": "2026-01-04T12:00:00Z"
}
POST /visualization/alerts
Crea una alerta de indicador.
Request Body:
{
"indicatorId": "ml_amd_detector",
"symbol": "BTC/USDT",
"conditions": [
{
"field": "phase",
"operator": "equals",
"value": "distribution"
}
],
"notificationChannels": ["push", "email"],
"triggerOnce": false
}
Response 201:
{
"id": "alert-001",
"indicatorId": "ml_amd_detector",
"symbol": "BTC/USDT",
"isActive": true,
"createdAt": "2026-01-04T12:00:00Z"
}
POST /visualization/backtest
Ejecuta un backtest.
Request Body:
{
"symbol": "BTC/USDT",
"strategyConfig": {
"indicators": ["ml_amd_detector", "ml_signal_overlay"],
"entryConditions": [...],
"exitConditions": [...]
},
"periodStart": "2025-10-01",
"periodEnd": "2026-01-01",
"initialCapital": 10000
}
Response 200:
{
"id": "backtest-001",
"symbol": "BTC/USDT",
"periodStart": "2025-10-01",
"periodEnd": "2026-01-01",
"initialCapital": 10000.00,
"finalCapital": 12450.00,
"totalReturn": 0.245,
"totalTrades": 45,
"winningTrades": 30,
"losingTrades": 15,
"winRate": 66.67,
"profitFactor": 2.3,
"maxDrawdown": -8.5,
"sharpeRatio": 1.82,
"trades": [
{
"entryDate": "2025-10-05T14:00:00Z",
"exitDate": "2025-10-06T10:00:00Z",
"entryPrice": 42150.00,
"exitPrice": 43200.00,
"side": "long",
"pnl": 250.00,
"pnlPercent": 2.49
}
]
}
Webhooks
POST /webhooks/stripe
Procesa eventos de Stripe.
Headers:
Stripe-Signature: t=1234567890,v1=signature...
Eventos Soportados:
payment_intent.succeededpayment_intent.payment_failedcustomer.subscription.createdcustomer.subscription.updatedcustomer.subscription.deletedinvoice.paidinvoice.payment_failed
POST /webhooks/cal
Procesa eventos de Cal.com.
Eventos Soportados:
BOOKING_CREATEDBOOKING_CANCELLEDBOOKING_RESCHEDULEDMEETING_ENDED
Payload Ejemplo:
{
"triggerEvent": "BOOKING_CREATED",
"payload": {
"bookingId": 12345,
"uid": "booking-uid-123",
"startTime": "2026-01-06T16:00:00Z",
"endTime": "2026-01-06T17:00:00Z",
"attendees": [
{
"email": "user@example.com",
"name": "Juan Perez"
}
],
"metadata": {
"sessionId": "session-001"
}
}
}
POST /webhooks/daily
Procesa eventos de Daily.co.
Eventos Soportados:
meeting.startedmeeting.endedrecording.ready
Codigos de Error
| Codigo | HTTP Status | Descripcion |
|---|---|---|
| PRODUCT_NOT_FOUND | 404 | Producto no encontrado |
| PRODUCT_UNAVAILABLE | 400 | Producto no disponible |
| INSUFFICIENT_CREDITS | 400 | Creditos insuficientes |
| PAYMENT_FAILED | 402 | Pago fallido |
| SUBSCRIPTION_EXISTS | 409 | Ya existe suscripcion activa |
| ADVISOR_NOT_AVAILABLE | 400 | Asesor no disponible |
| SLOT_NOT_AVAILABLE | 409 | Horario no disponible |
| SESSION_NOT_CANCELLABLE | 400 | Sesion no puede cancelarse |
| PREMIUM_REQUIRED | 403 | Requiere suscripcion premium |
| LIMIT_EXCEEDED | 400 | Limite excedido |
Formato de Error:
{
"error": {
"code": "PAYMENT_FAILED",
"message": "El pago no pudo ser procesado",
"details": {
"declineCode": "insufficient_funds"
},
"timestamp": "2026-01-04T12:00:00Z",
"requestId": "req-abc123"
}
}
Rate Limiting
| Endpoint | Limite | Ventana |
|---|---|---|
| GET /products | 100 | 1 minuto |
| POST /purchases | 10 | 1 minuto |
| POST /subscriptions | 5 | 1 minuto |
| POST /advisory-sessions | 10 | 1 hora |
| POST /visualization/backtest | 20 | 1 hora |
Headers de Rate Limit:
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 95
X-RateLimit-Reset: 1704369600