File size: 4,356 Bytes
71b8eb2 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 | # API.md — Referencia general PolySignal Backend
Base URL (dev): `http://localhost:7860`
Base URL (prod, HF Spaces): misma URL que el frontend (mismo origen).
---
## Arranque rápido
```bash
cd backend/
npm install
npm run db:migrate # solo primera vez
npm run db:seed # crea usuarios de prueba
npm run dev # http://localhost:7860
```
Usuarios de prueba: `admin@polysignal.test / Admin123!` y `user@polysignal.test / User123!`
---
## Autenticación
El API usa JWT Bearer. Para obtener un token:
```bash
TOKEN=$(curl -s -X POST http://localhost:7860/api/v1/auth/login \
-H 'Content-Type: application/json' \
-d '{"email":"admin@polysignal.test","password":"Admin123!"}' | jq -r '.data.token')
```
Enviarlo en cada request protegido:
```
Authorization: Bearer <token>
```
---
## Endpoints
### Públicos (sin auth)
| Método | Ruta | Descripción | Doc |
|---|---|---|---|
| `GET` | `/api/v1/health` | Sanity check | [AUTH.md](AUTH.md) |
| `POST` | `/api/v1/auth/login` | Login → JWT | [AUTH.md](AUTH.md) |
| `GET` | `/api/v1/markets` | Lista mercados paginada | [MARKETS.md](MARKETS.md) |
| `GET` | `/api/v1/markets/:id` | Detalle de mercado | [MARKETS.md](MARKETS.md) |
| `GET` | `/api/v1/markets/:id/signal` | Señal AI del mercado | [SIGNALS.md](SIGNALS.md) |
### Protegidos (requieren `Authorization: Bearer <token>`)
| Método | Ruta | Descripción | Doc |
|---|---|---|---|
| `GET` | `/api/v1/auth/me` | Perfil del usuario | [AUTH.md](AUTH.md) |
| `POST` | `/api/v1/positions` | Abrir posición | [POSITIONS.md](POSITIONS.md) |
| `GET` | `/api/v1/positions` | Listar posiciones | [POSITIONS.md](POSITIONS.md) |
| `DELETE` | `/api/v1/positions/:id` | Cerrar posición | [POSITIONS.md](POSITIONS.md) |
| `POST` | `/api/v1/watchlist` | Añadir a watchlist | [WATCHLIST.md](WATCHLIST.md) |
| `GET` | `/api/v1/watchlist` | Listar watchlist | [WATCHLIST.md](WATCHLIST.md) |
| `DELETE` | `/api/v1/watchlist/:marketId` | Eliminar de watchlist | [WATCHLIST.md](WATCHLIST.md) |
| `GET` | `/api/v1/alerts` | Historial de alertas | [ALERTS.md](ALERTS.md) |
---
## Contrato de respuesta
Todas las respuestas siguen el mismo envelope:
```json
// éxito
{ "ok": true, "data": <payload>, "meta": { ...opcional } }
// error
{ "ok": false, "error": { "code": "ERROR_CODE", "message": "...", "details": [...] } }
```
Códigos HTTP: `200` lectura · `201` creación · `204` borrado · `400` validación · `401` no autenticado · `404` no encontrado · `409` conflicto · `429` rate limit · `500` server error.
---
## Rate limiting
- **Global:** 200 req / 15 min / IP
- **`POST /auth/login`:** 5 intentos / 15 min / IP
Headers de respuesta: `RateLimit-Limit`, `RateLimit-Remaining`, `RateLimit-Reset`.
---
## WebSocket (Socket.io)
Conectar al mismo host que el backend:
```js
import { io } from 'socket.io-client';
const socket = io('http://localhost:7860');
```
| Evento | Frecuencia | Descripción | Doc |
|---|---|---|---|
| `market_update` | cada 30s | Precio actualizado de un mercado | [MARKETS.md](MARKETS.md) |
| `ai_signal` | cada 5 min | Nueva señal AI generada | [SIGNALS.md](SIGNALS.md) |
| `price_alert` | cuando se dispara | Alerta de precio threshold | [ALERTS.md](ALERTS.md) |
---
## Importar en Insomnia / Postman
Ver [`insomnia-collection.json`](insomnia-collection.json) — export v4 listo para importar en Insomnia.
Pasos:
1. Abrir Insomnia → Import → File
2. Seleccionar `backend/docs/insomnia-collection.json`
3. Configurar variable de entorno `base_url = http://localhost:7860`
4. Ejecutar `POST /auth/login` y copiar el token a la variable `token`
---
## Variables de entorno completas
Ver [`backend/.env.example`](../.env.example) para la plantilla completa.
| Variable | Obligatoria | Descripción |
|---|---|---|
| `PORT` | Sí | Puerto del servidor (7860 para HF Spaces) |
| `DATABASE_URL` | Sí | Path SQLite: `file:./polysignal.db` |
| `JWT_SECRET` | Sí | Mínimo 32 chars |
| `JWT_EXPIRES_IN` | No | Default `1h` |
| `BCRYPT_ROUNDS` | No | Default `10` |
| `CORS_ORIGIN` | No | Default `http://localhost:5173` |
| `LOG_LEVEL` | No | Default `info` |
| `HF_TOKEN` | No | HuggingFace (señales AI reales) |
| `OPENROUTER_API_KEY` | No | Fallback LLM |
| `FINNHUB_API_KEY` | No | Noticias para señales |
| `TELEGRAM_BOT_TOKEN` | No | Alertas Telegram |
|