ValorGrid expone una API HTTP local para que el frontend gestione cartera, histórico, importaciones, backups y exportaciones.
Por defecto el servidor escucha en:
http://127.0.0.1:1325
Si VALORGRID_AUTH_PASSWORD está configurado, toda la API queda protegida con Basic Auth monousuario. El usuario por defecto es valorgrid y puede cambiarse con VALORGRID_AUTH_USER.
GET /api/version
GET /api/extensions
GET /api/health
GET /api/state
GET /api/diagnostics/performance
GET /api/version: devuelve la versión definida enpackage.jsony la edición (communityoprofessional).GET /api/extensions: devuelve un manifiesto público de extensiones activas. En Community devuelve una lista vacía; en ediciones profesionales puede incluir módulos web y estilos cargables sin exponer contratos privados.GET /api/health: devuelve estado local, ruta de base de datos activa, versiones internas y último build histórico.GET /api/state: devuelve el estado completo de la aplicación: instrumentos, grupos, movimientos, planes automáticos y ruta de base de datos activa.GET /api/diagnostics/performance: devuelve métricas de rendimiento, tamaños de caché e invalidaciones pendientes.
GET /api/preferences/ui
PUT /api/preferences/ui
GET /api/preferences/ui: en Community devuelve un objeto de preferencias vacío yeditable: false. Las preferencias visuales avanzadas no forman parte del contrato público Community.PUT /api/preferences/ui: en Community devuelve403con mensajeFeature available in Professional Edition. Las ediciones profesionales pueden registrar una implementación privada mediante extensión para aceptar payloads parciales con preferencias visuales avanzadas sin publicar ese contrato interno en el repositorio Community.
GET /api/instruments
POST /api/instruments
DELETE /api/instruments
POST /api/instruments/preview-delete
PUT /api/instruments/:symbol
DELETE /api/instruments/:symbol
GET /api/instrument-groups
POST /api/instrument-groups
PUT /api/instrument-groups/settings
DELETE /api/instrument-groups
PUT /api/instrument-groups/:id
DELETE /api/instrument-groups/:id
GET /api/instrument-identifiers
POST /api/instrument-identifiers
DELETE /api/instrument-identifiers/:id
PUT /api/instruments/brand-palette
GET /api/liquidity
POST /api/liquidity/accounts
PUT /api/liquidity/accounts/:symbol
DELETE /api/liquidity/accounts/:symbol
-
POST /api/instruments/preview-delete: devuelve estado de posición y dependencias antes de eliminar; es una previsualización y no bloquea por sí misma. -
El bloqueo real por posición o automatizaciones activas se aplica al ejecutar
DELETE /api/instruments/:symboloDELETE /api/instruments. -
PUT /api/instruments/brand-palette: activa o desactiva la paleta corporativa automática. Cuerpo:{ "enabled": boolean }. Si se activa, guarda snapshot de colores actuales, aplica colores corporativos a grupos e instrumentos y actualiza transacciones. Si se desactiva, restaura los colores del snapshot. Respuesta incluyebrandPaletteEnabled,snapshotCreated,snapshotReused,updatedGroups,updatedInstruments,updatedTransactions,restoredGroups,restoredInstruments,snapshotCleared. -
GET /api/instrumentsyGET /api/instrument-groupsincluyenbrandPaletteEnableden la respuesta. -
GET /api/liquidity: devuelve el grupo técnico de liquidez, cuentas activas y total EUR actual. -
POST /api/liquidity/accounts: crea una cuenta de liquidez con{ name, cashBalance, currency, color }. No crea movimientos. -
PUT /api/liquidity/accounts/:symbol: actualiza nombre, saldo actual, divisa, color y visibilidad en dashboard. -
DELETE /api/liquidity/accounts/:symbol: desactiva la cuenta de liquidez y pone su saldo a cero. -
instrumentsalmacena valores visibles de cartera. -
instrument_groupsorganiza visibilidad por dashboard, revisión YTD y desglose. -
instrument_identifiersguarda identificadores confirmados por el usuario, como ISIN o alias de broker, para futuras importaciones. -
PUT /api/instrument-groups/settings: activa o desactiva el uso de grupos. Request body:{ "enabled": boolean }(requerido, debe ser booleano). Al activar, los instrumentos activos sin grupo se asignan automáticamente a "grupo-cero". Response 200:{ groupsEnabled, createdDefaultGroup, assignedInstrumentCount, defaultGroup }. Response 400:{ error: "enabled must be a boolean" }.
GET /api/onboarding/status
POST /api/onboarding/wizard/preview
POST /api/onboarding/wizard/commit
El wizard permite crear grupo, instrumento, primera compra opcional y plan automático opcional de forma atómica. La respuesta GET /api/onboarding/status incluye groupsEnabled (boolean) que indica si los grupos de instrumentos están habilitados.
GET /api/transactions
POST /api/transactions
POST /api/transactions/preview
DELETE /api/transactions/:id
DELETE /api/transactions (bulk)
Los movimientos son la verdad contable principal. Una compra o venta puede incluir:
- fecha de operación,
- fecha de mercado,
- ticker,
- tipo (
addoremove), - cantidad (
shares, visible como acciones o unidades según el tipo de instrumento), - valor bruto EUR,
- precio,
- divisa,
- FX a EUR,
- comisión,
- cash-flow firmado,
- origen.
entryMode es opcional para compatibilidad. Si se envía, acepta tres modos:
market_eur(euros): se calcula la cantidad coneuros / priceEurusando precio de mercado/cache. Si se envía explícitamente, solo es válido para compras.manual_total_eur(shares+euros): registra una ejecución liquidada en euros. No consulta mercado; guardaprice = euros / shares,currency = EURyfxToEur = 1.manual_unit_price(shares+unitPrice): registra un precio unitario manual.priceCurrencypermite indicar la divisa de ejecución; si falta, se usa la divisa del instrumento. Si la divisa no es EUR,fxToEures obligatorio cuandoentryMode = manual_unit_price.
Sin entryMode, se mantiene la inferencia histórica:
euros: se calcula la cantidad con precio de mercado/cache.shares: se calculavalueEur = shares * priceEurusando precio de mercado/cache.shares+unitPrice: usa precio manual y conserva la resolución previa de FX.
Reglas de validación:
- En
market_eur, se exigeeurosy no se permiteshares. - En ventas nuevas, la UI usa
manual_total_eur: cantidad vendida + importe bruto de venta en EUR + comisión EUR. La API rechaza ventas explícitas conentryMode = market_eur. - En
manual_total_eur, se exigeneurosyshares, y no se permiteunitPrice. - En
manual_unit_price,unitPricerequiereshares > 0y no se permite coneuros. - Sin
entryMode,eurosysharessiguen siendo XOR (no se permiten ambos), salvoshares + unitPrice. unitPricerequiereshares > 0y no se permite coneuros.unitPricerequiere un instrumento existente.- Para instrumentos no EUR con precio manual legacy, se puede enviar
fxToEurmanual. Si no se envia, la API exige FX de mercado disponible para la fecha; no usa FX antiguo automáticamente en escrituras. type = dividendno se acepta en estos endpoints. Los dividendos solo se crean desde eventos de Yahoo Finance revisados o auto-confirmados por/api/dividends/*.
GET /api/dividends/summary
GET /api/dividends/drafts
POST /api/dividends/scan
PATCH /api/dividends/drafts/:id
POST /api/dividends/drafts/:id/confirm
POST /api/dividends/drafts/:id/ignore
PUT /api/dividends/settings/:symbol
GET /api/dividends/summary: devuelve contadores de borradores pendientes, total pendiente, dividendos confirmados, simbolos con auto-inclusion y ultimo scan.GET /api/dividends/drafts: devuelve borradoresdraftdetectados desde Yahoo Finance.POST /api/dividends/scan: lanza una busqueda de dividendos. El frontend la usa automáticamente al arrancar; no hay boton manual público en Community.PATCH /api/dividends/drafts/:id: actualiza importe por accion, acciones con derecho y total EUR efectivo.POST /api/dividends/drafts/:id/confirm: crea un movimiento realtransactions.type = dividenddesde el borrador.POST /api/dividends/drafts/:id/ignore: descarta el borrador sin crear movimiento.PUT /api/dividends/settings/:symbol: activa/desactivaautoIncludepara proximos dividendos del instrumento.
Reglas:
- Solo se escanean instrumentos
stockyetf. - El primer dividendo de un instrumento queda como borrador porque
autoIncludeempieza desactivado. - Si
autoIncludeesta activo, los siguientes dividendos se confirman automáticamente salvo que Yahoo informe split/dividend split. - Los split/dividend split solo se informan; no se procesan en esta versión.
- No se pueden crear dividendos manuales sin evento Yahoo.
GET /api/auto-plans
PUT /api/auto-plans
POST /api/auto-plans/preview
Los planes soportan frecuencia diaria, semanal, bisemanal y mensual. Cada plan tiene fecha de inicio y respeta skips si una operación automática se elimina manualmente.
GET /api/portfolio/summary
GET /api/portfolio/performance
GET /api/portfolio/returns
GET /api/portfolio/monthly?year=2026
GET /api/portfolio/history?range=ytd&granularity=auto
GET /api/portfolio/history?range=1y
GET /api/portfolio/history?range=2y&granularity=weekly
GET /api/portfolio/history?range=5y&granularity=weekly
GET /api/portfolio/history?range=all&granularity=weekly
summary: distribución actual, grupos e instrumentos. Respuesta incluyegroupsEnabled(boolean) que indica si los grupos de instrumentos están habilitados.performance: aportado, retirado, comisiones, plusvalía y rentabilidad simple.returns: en Community devuelve403con mensajeFeature available in Professional Edition. Las ediciones profesionales pueden registrar una implementación privada para rentabilidad por instrumento o grupo sin publicar ese contrato interno en el repositorio Community.monthly: revisión YTD por meses y grupos. La respuesta devuelvemonths(array con insight por mes:month,label,total,transactions,cells) ysummary(métricas agregadas:currentValue,netContributed,resultYtd,valueStart,contributions,withdrawals,dividends,dividendCount,commissions,completedMonths,latestMonth,activeGroups) como contratos canónicos.history: serie histórica materializada diaria/semanal y eventos. Aceptagranularity(auto|daily|weekly, defaultauto).- Semántica de fórmulas y signos:
docs/FINANCIAL_SEMANTICS.md.
Las vistas de cartera son tolerantes a fallos del proveedor de mercado: summary incluye marketDataStatus (ok, stale o missing) y las posiciones pueden incluir dataQuality, priceSource, priceAgeDays y valuationAvailable.
GET /api/quote?symbol=TICKER&date=2026-05-03
GET /api/market-data/sources
GET /api/market-data/alpha-vantage/status
POST /api/market-data/alpha-vantage/key
DELETE /api/market-data/alpha-vantage/key
GET /api/quote devuelve precio cacheado o consultado al proveedor de mercado. La selección de proveedor es automática según el tipo de instrumento:
- ETF, Stock, Crypto: Yahoo Finance
- Commodity: Alpha Vantage (requiere clave API configurada)
Si el instrumento tiene fuentes configuradas, se consultan por prioridad. Yahoo es el respaldo por defecto si la fuente primaria no responde.
Si el proveedor no responde y existe un precio local anterior, la respuesta puede ser 200 con stale: true, dataQuality: "stale", fallbackReason y priceAgeDays. Si no hay dato local, devuelve un error accionable.
GET /api/market-data/sources lista proveedores disponibles y su estado local.
GET /api/market-data/alpha-vantage/status devuelve el estado de la configuración de Alpha Vantage:
{
"configured": false,
"mode": "desktop",
"source": null,
"canSaveKey": true,
"hint": "Abre https://www.alphavantage.co/support/#api-key para obtener tu clave gratuita"
}configured:truesi hay clave configurada,falsesi no.mode:"desktop"si se ejecuta como app de escritorio Electron,"server"en modo Node puro.source:"local"si se guardó desde el asistente,"env"si se configuró por variable de entorno,nullsi no hay clave.canSaveKey:truesi la API puede guardar una clave local en caliente. Esfalsecuando la clave está gestionada por variable de entorno.hint: mensaje accionable para el usuario según el modo.
POST /api/market-data/alpha-vantage/key guarda una nueva clave de Alpha Vantage desde el asistente local. Funciona en desktop y en Docker/CasaOS cuando la clave no está gestionada por variable de entorno. Validación:
- El campo
apiKeydebe tener 16 caracteres alfanuméricos mayúsculas. - Se valida con una llamada real a
GOLD_SILVER_SPOTantes de guardar. - Si la clave es inválida o el límite diario está activo, devuelve
400con mensaje explicativo. - Si
VALORGRID_ALPHA_VANTAGE_API_KEYestá configurada por entorno, devuelve400e indica que la clave se cambie en la configuración del contenedor o proceso.
Respuesta:
{
"message": "Clave de Alpha Vantage guardada correctamente"
}DELETE /api/market-data/alpha-vantage/key elimina la clave guardada localmente. Si la clave viene de variable de entorno, devuelve 400.
- App de escritorio: la clave se guarda en
secrets.jsonjunto al directorio de backups dentro de la carpeta privada de Electron (app.getPath('userData')). ValorGrid nunca la expone por API ni la envía a servidores externos (salvo a la API oficial de Alpha Vantage para consultar precios). - Docker/CasaOS: si no se configura variable de entorno, la misma vista de configuración permite pegar la clave y guardarla en el volumen persistente de datos (
/data/secrets.json) sin reiniciar el contenedor. - Servidor/dev avanzado:
VALORGRID_ALPHA_VANTAGE_API_KEYtiene prioridad sobre la clave local persistida.ALPHA_VANTAGE_API_KEYsigue aceptada por compatibilidad.
GET /api/backups
POST /api/backups
GET /api/backups/:file
DELETE /api/backups/:file
Los backups se guardan en local/valorgrid/backups/ y no deben versionarse.
GET /api/backups— lista todos los backups disponibles.POST /api/backups— crea un nuevo backup de la base de datos activa.GET /api/backups/:file— descarga un backup específico.DELETE /api/backups/:file— elimina un backup específico.- Las operaciones de riesgo (bulk delete transactions, replace auto-plans, delete instruments, delete groups, import commit, import rollback) pueden devolver un campo
backupcon el backup automático creado antes de la operación.
GET /api/export/transactions.xlsx
GET /api/export/transactions.xlsx?symbol=AAPL
GET /api/export/transactions.xlsx?origin=manual&type=add
GET /api/export/transactions.xlsx?from=2026-01-01&to=2026-12-31
Exporta el ledger de movimientos como Excel importable por ValorGrid. El libro contiene una sola hoja Movimientos, sin instrucciones ni ejemplos, con los encabezados oficiales de la plantilla de importación: Tipo, Fecha, Ticker, Yahoo, Acciones, Precio, Divisa, FX a EUR, Valor EUR, Comision EUR y Referencia.
Sin parámetros, exporta todos los movimientos. Parámetros opcionales de filtro:
| Parámetro | Descripción | Ejemplo |
|---|---|---|
symbol |
Filtra por símbolo (case-insensitive, parcial) | symbol=AAPL |
origin |
Filtra por origen: manual, auto, import |
origin=auto |
type |
Filtra por tipo: add, remove, dividend |
type=add |
from |
Fecha mínima (YYYY-MM-DD) |
from=2026-01-01 |
to |
Fecha máxima (YYYY-MM-DD) |
to=2026-06-30 |
Los parámetros se combinan con AND. Una consulta inválida devuelve 400 con mensaje de error.
Las compras se exportan como compra con cantidad positiva, las ventas como venta con cantidad negativa y los dividendos como dividendo con acciones informativas. En el Excel esa cantidad usa el encabezado Acciones por compatibilidad. Referencia usa externalId si existe o el id interno si no existe.
GET /api/import/sources
GET /api/import/template.xlsx
POST /api/import/preview
POST /api/import/commit
GET /api/import/batches
GET /api/import/batches/:id
POST /api/import/batches/:id/rollback
GET /api/import/rollback-log
POST /api/import/ticker-suggestions
GET /api/import/sources — devuelve la lista de fuentes de importación disponibles con su estado de disponibilidad según la edición activa (community o professional).
Respuesta:
{
"sources": [
{
"key": "valorgrid-xlsx",
"label": "Plantilla Excel de ValorGrid",
"edition": "community",
"available": true
},
{
"key": "<fuente-profesional>",
"label": "<Fuente profesional>",
"edition": "professional",
"available": false,
"comingSoon": true
}
]
}available: true— la fuente puede usarse para importar.available: false— la fuente pertenece a otra edición y no está habilitada.comingSoon: true— la fuente está en desarrollo y no está disponible en ninguna edición.
valorgrid-xlsx (plantilla Excel de ValorGrid — recomendado, siempre disponible)
Las fuentes de ediciones profesionales pueden aparecer en el catálogo con edition: "professional" y available: false cuando no están habilitadas. Su configuración, contratos de adaptación y detalles operativos se documentan solo en materiales privados de ValorGrid Pro/Enterprise. Cuando una edición privada está cargada mediante el host de extensiones, sus fuentes pueden aparecer como available: true sin que Community publique el adaptador ni su contrato interno.
GET /api/import/template.xlsx — descarga la plantilla Excel oficial de ValorGrid con tres hojas:
Movimientos(primera hoja, importable): encabezadosTipo,Fecha,Ticker,Acciones,Precio,Divisa,FX a EUR,Valor EUR,Comision EUR,Referencia.Instrucciones: guía de uso.Ejemplos: datos de ejemplo.
La respuesta incluye Content-Disposition: attachment y MIME application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.
La plantilla se procesa internamente con ExcelJS. El parser solo acepta .xlsx moderno, limita el archivo a 2 MB, exige la hoja Movimientos, bloquea hojas no permitidas, valida encabezados exactos, rechaza fórmulas y limita Community a 500 movimientos por importación.
Tipo: compra/venta, o se infiere por signo si se deja vacío.Acciones: cantidad del instrumento; positiva para compra, negativa para venta si no se usaTipo.DivisayFX a EURson obligatorios para operaciones no EUR.Valor EURes opcional; si falta, se calcula comoabs(Acciones) * Precio * FX a EUR.- No se busca FX automáticamente durante importación.
El flujo recomendado es:
- Descargar la plantilla con
GET /api/import/template.xlsx. - Rellenar la hoja
Movimientoscon las operaciones. preview: parsea, normaliza, detecta instrumentos, calcula cantidades importables y muestra avisos.- Resolución visual de instrumentos en frontend.
- Selección de filas o grupos a importar.
commit: inserta solo filas seleccionadas y válidas de forma atómica.rollback: revierte un lote importado si hace falta corregirlo.
ValorGrid Community acepta la plantilla Excel oficial como fuente predeterminada. Las fuentes legacy (generic-csv, csv, generic-xlsx, xlsx) devuelven error 400 con el mensaje "usa la plantilla Excel de ValorGrid".
Las respuestas de error son JSON y deben mostrar mensajes orientados al usuario siempre que sea posible. En importaciones, las filas omitidas, duplicadas o ignoradas no bloquean el lote; solo bloquean las filas seleccionadas para importar que sigan siendo inválidas.