WATCHLIST.md — Módulo de watchlist
Mercados favoritos del usuario con umbral de alerta opcional. Cuando yesPrice >= alertThreshold, el job processAlerts crea una Alert y envía notificación por Telegram.
Todos los endpoints requieren Authorization: Bearer <token>.
Endpoints
POST /api/v1/watchlist
Añade un mercado a la watchlist del usuario.
Body
{
"marketId": "559677",
"alertThreshold": 0.75
}
| Campo | Tipo | Descripción |
|---|---|---|
marketId |
string | ID del mercado (debe existir en DB) |
alertThreshold |
float (0–1) | null | Precio YES que dispara la alerta; null para no alertar |
Respuesta 201
{
"ok": true,
"data": {
"id": 2,
"userId": 1,
"marketId": "559677",
"alertThreshold": 0.75,
"createdAt": "2026-05-16T09:21:41.606Z",
"market": {
"id": "559677",
"question": "Will Hillary Clinton win the 2028 Democratic presidential nomination?",
"yesPrice": 0.0075,
"noPrice": 0.9925,
"status": "active"
}
}
}
Respuesta 409 — mercado ya está en la watchlist del usuario:
{
"ok": false,
"error": { "code": "CONFLICT", "message": "Market already in watchlist" }
}
GET /api/v1/watchlist
Lista todos los mercados en la watchlist del usuario con datos de mercado embebidos.
Respuesta 200
{
"ok": true,
"data": [
{
"id": 2,
"userId": 1,
"marketId": "559677",
"alertThreshold": 0.001,
"createdAt": "2026-05-16T09:21:41.606Z",
"market": {
"id": "559677",
"question": "Will Hillary Clinton win the 2028 Democratic presidential nomination?",
"yesPrice": 0.0075,
"noPrice": 0.9925,
"status": "active"
}
}
]
}
DELETE /api/v1/watchlist/:marketId
Elimina un mercado de la watchlist del usuario.
Params
| Param | Tipo | Descripción |
|---|---|---|
marketId |
string | ID del mercado |
Respuesta 204 — sin body.
Respuesta 404
{
"ok": false,
"error": { "code": "NOT_FOUND", "message": "Watchlist entry not found" }
}
Lógica de alertas
El job processAlerts (cron * * * * *) evalúa cada entrada de watchlist con alertThreshold definido:
- Si
market.yesPrice >= alertThreshold→ creaAlert+ envía Telegram + emiteprice_alertpor socket. - Deduplicación: no se crea una segunda alerta si ya existe una para el mismo mercado en los últimos 5 min.
Para recibir alertas por Telegram, el usuario debe tener telegramChatId configurado en su perfil (campo opcional en User).
Ejemplos curl
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')
# Añadir a watchlist con umbral 75%
curl -s -X POST http://localhost:7860/api/v1/watchlist \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"marketId":"559677","alertThreshold":0.75}' | jq
# Listar watchlist
curl -s -H "Authorization: Bearer $TOKEN" http://localhost:7860/api/v1/watchlist | jq
# Eliminar de watchlist
curl -s -X DELETE -H "Authorization: Bearer $TOKEN" \
"http://localhost:7860/api/v1/watchlist/559677"
Códigos de error
| HTTP | Código | Cuándo |
|---|---|---|
400 |
VALIDATION_ERROR |
Body inválido (marketId vacío, threshold fuera de 0–1) |
401 |
UNAUTHORIZED |
Sin token o token inválido |
404 |
NOT_FOUND |
Mercado no existe en DB o entrada no encontrada al borrar |
409 |
CONFLICT |
Mercado ya en watchlist |
500 |
INTERNAL |
Error inesperado |