Releases: Gisus07/tasa-bcv-api
v1.0.0 — API completa: BCV + paralela + intervención
🎉 v1.0.0 — API completa y estable
Primera versión estable. La API cubre ahora las tres series de cambio de Venezuela.
Novedad: intervención cambiaria del BCV
Serie nueva e independiente — el tipo de cambio Bs./EUR que el BCV publica los días (≈3/semana) que interviene en el mercado.
GET /v1/intervention/latest— última intervención (date,intervention_number,rate).GET /v1/intervention/history?from&to— histórico (desde el 13 may 2019, máx 366 días).- Independiente de la tasa oficial USD/EUR; no se propaga (solo los días que efectivamente hubo).
- Captura automática cada mañana (7-9 AM lun-vie), guiada por la propagación de la tasa BCV como detector de feriados — sin calendario que mantener.
La API completa
- Tasas oficiales BCV USD/VES y EUR/VES — histórico desde 2016, propagación de findes/feriados, captura a las 23:00.
- Tasa paralela (Binance P2P, USDT/VES) — en vivo + histórico horario + velas diarias OHLC.
- Intervención cambiaria (Bs./EUR).
- Documentación bilingüe (
/docs,/docs/en), API keys gratuitas, rate limiting por tier.
Incluye la migración 0005; el histórico de intervención se siembra automáticamente en el primer arranque. 133 tests en verde.
v0.4.0 — Captura de tasas 23:00 + propagación anticipada
🛠️ Captura de tasas a las 23:00 con propagación anticipada
Arregla el bug por el que /v1/rates/latest se quedaba "pegado" en una fecha pasada durante fines de semana y feriados.
Cambios
- Daily a las 23:00 (lun-vie): a esa hora el BCV ya publicó la tasa del próximo día hábil, así que la propagación se hace hacia adelante y cubre sábado, domingo y feriados en una sola corrida (en vez de dejarlos vacíos hasta el siguiente día hábil).
/v1/rates/latestsiempre devuelvedate = hoy(marcado como propagado cuando aplica), aunque el daily no haya corrido todavía.
Validado contra Carnaval y Semana Santa 2026. No-breaking: el shape de las respuestas no cambia. typecheck + 122 tests en verde.
v0.3.1 — Tasa paralela en vivo
💵 /v1/parallel/latest ahora es en vivo
La tasa paralela (dólar Binance, USDT/VES) en /latest se consulta al momento desde Binance P2P, en lugar de devolver el último snapshot horario.
Cambios
/v1/parallel/latesten vivo: consulta Binance al vuelo con cache in-memory de 30s (Cache-Control: max-age=30). Si Binance no responde, cae al último snapshot almacenado — nunca se rompe.- README: nueva sección "Tasa paralela (dólar Binance)" con el modelo
buy/sell/average, los endpoints OHLC y el alcance del histórico (desde el lanzamiento). - El cron horario sigue alimentando
/historyy/daily(el histórico).
No-breaking: el shape de la respuesta es idéntico. 116 tests en verde.
v0.3.0 — Tasa paralela (Binance P2P, USDT/VES)
Primera fuente no-BCV: la tasa paralela USDT/VES (el "dólar Binance"). Minor y no-breaking — los endpoints del BCV quedan idénticos.
Nuevo
- Endpoints:
GET /v1/parallel/latest,/v1/parallel/history?from&to(horario, máx 31 días) y/v1/parallel/daily?from&to(velas OHLC, máx 365 días). - Fuente: Binance P2P (mediana del top-10 de ofertas) —
buy(comprar USDT) +sell(vender) +average. - Tracking: snapshot cada hora (mercado 24/7) + snapshot inicial al arrancar. No se propaga.
- Tabla
parallel_rates(migración0004); OpenAPI bilingüe ampliado (secciónparallel).
Calidad
pnpm typecheck limpio + 116 tests.
v0.2.1 — Hardening + fixes (propagación USD, /latest)
Release de mantenimiento desde v0.2.0: endurecimiento tras una auditoría completa + dos correcciones de datos.
🔒 Seguridad y robustez (auditoría A–E)
Rate-limit en el registro de keys, IP no spoofeable (TRUSTED_PROXY_HOPS), sin fugas de detalle en errores 5xx, timingSafeEqual para el admin token, allowlist de host del BCV, statement_timeout en el pool, graceful shutdown + handlers de proceso, /health/live, índices redundantes eliminados + FK en api_key_usage_daily, ventana de propagación adaptativa.
🐛 Correcciones de datos
- Propagación USD: el daily ahora re-lee el XLS de USD (captura publicaciones tardías) y
propagateGapsre-propaga filas obsoletas. NuevoPOST /v1/admin/reingestpara corrección manual. /v1/rates/latestdevuelve la tasa vigente hoy, no una futura que el BCV ya publicó para el próximo día hábil.
🧹 Calidad
93 → 108 tests, dependencias muertas eliminadas, versión sincronizada con package.json.
v0.2.0 — i18n, UI, API keys, admin y métricas
Consolidación grande sobre v0.1.0. La API ya no es solo "ofrece datos" — ahora tiene gestión de keys, métricas por usuario, documentación bilingüe y un security tab completamente limpio.
🟢 En producción
- API: https://tasa-bcv-api-production.up.railway.app
- Docs (auto-detect español/inglés): https://tasa-bcv-api-production.up.railway.app/docs
✨ Lo nuevo
Documentación bilingüe
/docs— español por defecto/docs/en— inglés- Auto-detect por
Accept-Language(si tu navegador prefiere inglés, redirige automáticamente) /openapi.json(ES) y/openapi-en.json(EN), este último traducido en runtime- Override manual con
?lang=eso?lang=en
API Keys (tier Free)
POST /v1/keys/register— auto-registro público, instantáneo (email + nombre + propósito opcional)GET /v1/keys/me— metadata de mi keyGET /v1/keys/me/usage?days=30— histograma diario de uso (ideal para dashboards)DELETE /v1/keys/me— auto-revoke- 300 req/min con key vs 30 req/min anonymous
Admin
GET /v1/admin/keys— listar todas las keys (activas + revocadas)POST /v1/admin/keys/{id}/revoke— soft-delete por idPOST /v1/admin/trigger-ingest— disparar ingest manual (ya existía)
Shapes JSON limpios
La respuesta default es ultra-plana:
{ "date": "2026-05-14", "usd": 510.7873, "eur": 598.12171255 }Cuando hay propagación, aparece propagated_currencies: ["USD", "EUR"]. Campos internos (source_file, fetched_at, currency_pair) ya no se exponen al consumidor.
Code samples embebidos
Cada endpoint trae snippets listos en curl, JavaScript (fetch), TypeScript, Python (requests), PHP (cURL), Go (net/http) — visibles como tabs en /docs.
UI de Scalar pulida
- Theme purple con tipografías Inter + JetBrains Mono
- Tags reorganizados (rates → keys → system → admin)
- Ejemplos múltiples por endpoint (día normal, fin de semana, propagación parcial, pre-redenominación)
- Server URL declarado en el spec (try-it desde docs funciona)
Errores unificados
Antes los errores de validación Zod devolvían un shape distinto a los AppError. Ahora todo usa el mismo envelope:
{
"error": "Entrada inválida",
"code": "VALIDATION_ERROR",
"details": { "issues": [{ "path": "date", "message": "...", "code": "custom" }] }
}🛡️ Seguridad
- 0 alertas abiertas en Security tab (code scanning, secret scanning, dependabot)
- CVE crítico de Drizzle (SQL injection en identifiers) parcheado: 0.36 → 0.45
- Headers HTTP endurecidos: HSTS 1 año + preload, CSP estricto, Permissions-Policy denegando 8 features
- Dependabot + GitHub Actions CodeQL + Secret Scanning + Push Protection: todo activado
- Branch protection en
maincon required status checks
🧪 Tests
- 93 tests pasando, 0 skipped (subimos de 71 + 8 skipped en v0.1.0)
- Tests de DB migrados de pg-mem a
@testcontainers/postgresqlcon Postgres real - Cada PR debe pasar el job
typecheck + tests + buildantes de mergear
📦 Datos
- Total filas en DB: ~6,000+ (rates reales + propagaciones)
- USD desde 2016-01-04 (2,500 registros reales)
- EUR desde 2020-03-27 (~1,400 registros reales)
🗺️ Próximos pasos (planeados)
- Dominio propio cuando haya presupuesto
- Tier Pro con monetización (Stripe/Plisio/PayPal, por decidir)
- Endpoint
/metricspara observabilidad - Más ejemplos de SDK en el README
📄 Licencia
No estamos afiliados al Banco Central de Venezuela.
v0.1.0 — First public release
🎉 Primera versión pública de tasa-bcv-api — la API REST pública y gratuita para el histórico oficial de tasas USD/VES y EUR/VES del Banco Central de Venezuela.
🟢 En producción
- API: https://tasa-bcv-api-production.up.railway.app
- Documentación interactiva (Scalar): https://tasa-bcv-api-production.up.railway.app/docs
- OpenAPI spec: https://tasa-bcv-api-production.up.railway.app/openapi.json
- Healthcheck: https://tasa-bcv-api-production.up.railway.app/health
📊 Datos disponibles
| Moneda | Histórico desde | Registros | Fuente |
|---|---|---|---|
| USD/VES | 2016-01-04 | 2500 días reales | 2_1_1_tdc.xlsx del BCV |
| EUR/VES | 2020-03-27 | 1419 días reales | 2_1_2*_otrasmonedas.xls del BCV |
Total cargado en la primera ingesta: 3913 filas reales + propagación a fines de semana y feriados para que toda fecha en el rango devuelva un valor.
⚙️ Funcionalidad
- 10 endpoints REST (
/v1/rates/*,/health,/docs,/openapi.json,/v1/admin/trigger-ingest). - Actualización diaria automática a las 00:00 Caracas (lun-vie) con retry a las 08:00 si la primera ingesta no captura la tasa del día.
- Propagación de fines de semana y feriados con flag
is_propagated: trueypropagated_fromapuntando al día origen. - Rate limit de 30 req/min por IP (X-Forwarded-For aware).
- OpenAPI 3.1 auto-generado desde los esquemas Zod de cada ruta.
- Validación robusta de fechas: 400 con códigos estables (
DATE_OUT_OF_RANGE,DATE_BEFORE_HISTORY,INVALID_RANGE,RANGE_TOO_LARGE,INVALID_DATE_FORMAT). - Endpoint admin protegido (Bearer token) para disparar ingest manualmente.
🛠️ Stack
TypeScript + Hono + Drizzle ORM + PostgreSQL 16, undici para HTTP (con SSL inválido tolerado), SheetJS para los XLS, cheerio para la homepage del BCV, node-cron para el scheduling, pino para logs estructurados. Deploy en Railway.
⚠️ Sobre la redenominación del bolívar
El 1 de octubre de 2021 el BCV redenominó el bolívar eliminando 6 ceros. La API devuelve el valor exacto que el BCV publicó en cada época, sin transformaciones:
- 2020-03-27: USD 73,830.16 / EUR 81,349.03 (Bs.S, antes de la reforma)
- 2026-05-14: USD 510.79 / EUR 598.12 (Bs.D, después de la reforma)
Para comparar entre escalas, divide los valores antiguos entre 1,000,000.
🤝 Cómo usarla
# Última tasa
curl https://tasa-bcv-api-production.up.railway.app/v1/rates/latest
# Fecha específica
curl https://tasa-bcv-api-production.up.railway.app/v1/rates/2026-05-14
# → USD 510.7873 / EUR 598.12171255
# Rango histórico
curl "https://tasa-bcv-api-production.up.railway.app/v1/rates/range?from=2026-05-01&to=2026-05-19¤cy=USD"
# Solo una moneda
curl https://tasa-bcv-api-production.up.railway.app/v1/rates/eur📜 Versión anterior
Este repo nació como un bot de Telegram en Python (@IntervencionBCVbot) que operó hasta agosto de 2025. El código del bot está preservado en el tag v0-legacy-python-bot, el branch legacy/python-bot y la carpeta legacy/python-bot/ en main.
🗺️ Próximos pasos
- API keys opcionales (más cuota por key registrada)
- Endpoint admin para disparar backfill (hoy solo trigger-ingest del daily)
- Migración de tests de DB a
testcontainers - Dominio propio cuando haya presupuesto
📄 Licencia
Distribuido bajo AGPL-3.0-or-later. Si despliegas una versión modificada como servicio público, debes publicar tus cambios.
No estamos afiliados al Banco Central de Venezuela. Las tasas son obtenidas de los datos oficiales que el BCV publica en su sitio web.
v0 (archived) — Telegram bot
📦 Snapshot archivado del bot de Telegram que precedió a esta API.
Esta release captura el código tal como existió justo antes del pivot hacia tasa-bcv-api. El bot operó en producción desde su creación como proyecto académico hasta agosto de 2025, cuando cumplió su propósito original y se dio de baja.
Qué hacía
- Notificaciones por Telegram cuando el BCV publicaba una nueva intervención cambiaria.
- Comandos
/tasa,/ultimopara consultas manuales. - Sistema de donaciones por Pago Móvil, Binance, PayPal y Wally.
Stack
Python 3.11 + python-telegram-bot + Firestore + Docker, scheduling con asyncio, scraping con requests + BeautifulSoup.
Dónde está
- En esta release: snapshot del último commit del bot (
2afc839). - En el branch
legacy/python-bot. - En la carpeta
legacy/python-bot/del branchmain, preservada para referencia cruzada durante el desarrollo de la API en TypeScript.
¿Por qué se archivó?
El bot llegaba a un público limitado (suscriptores de Telegram). Una API REST pública (v0.1.0+) sirve al mismo dolor pero a una audiencia mucho mayor: cualquier app, ERP, calculadora de remesas o e-commerce venezolano puede consumir las tasas oficiales del BCV.
No estamos afiliados al Banco Central de Venezuela.