Documentación API
Integra kakebo.io con tus propias herramientas usando nuestra API REST. Todas las peticiones requieren autenticación mediante API Key.
Autenticación
La API acepta dos métodos de autenticación: JWT (recomendado para apps móviles) y API Key.
1 JWT (recomendado para apps móviles)
Obtené un token enviando tus credenciales al endpoint de login. El token expira en 24 horas.
POST https://kakebo.io/api/v1/auth/login
Content-Type: application/json
{
"username": "tu_usuario",
"password": "tu_contraseña"
}
{
"token": "eyJhbGciOiJIUzI1NiJ9...",
"tokenType": "Bearer",
"username": "tu_usuario",
"fullName": "Tu Nombre",
"role": "ROLE_USER",
"expiresIn": 86400,
"language": "ES",
"numberFormat": "COMMA_DECIMAL",
"country": "CR",
"baseCurrency": "CRC",
"preferredTheme": "DARK",
"timezone": "America/Costa_Rica",
"accountPlan": "FREE",
"planExpiresAt": null
}
Authorization: Bearer eyJhbGciOiJIUzI1NiJ9...
2 API Key (acceso externo estático)
Encontrá tu API Key en Perfil → Seguridad → API Key. Si no tenés una, generála desde esa pantalla.
X-API-Key: YOUR_API_KEY
URL Base
https://kakebo.io/api/v1
Todas las rutas documentadas son relativas a esta URL base.
Códigos de Error
| 200 | Petición exitosa. |
| 400 | Datos inválidos o faltantes en el cuerpo de la petición. |
| 401 | API Key ausente o inválida. |
| 403 | Sin permisos para realizar esta acción. |
| 404 | Recurso no encontrado. |
| 429 | Demasiadas peticiones. Límite de tasa excedido. |
Registro de usuario
Crea una nueva cuenta de usuario con plan FREE. El usuario recibirá un correo para verificar su email antes de poder iniciar sesión.
Crea una nueva cuenta de usuario con plan FREE. El usuario recibirá un correo para verificar su email antes de poder iniciar sesión.
Parámetros
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
username |
string | Sí | Nombre de usuario único. Mín. 3 caracteres, máx. 50. |
password |
string | Sí | Contraseña en texto plano. Mín. 8 caracteres, máx. 100. |
fullName |
string | Sí | Nombre completo del usuario. Máx. 100 caracteres. |
email |
string | Sí | Correo electrónico válido. Se usará para la verificación de cuenta. |
timezone |
string | No | Zona horaria IANA del cliente (ej: America/Costa_Rica). Defecto: America/Costa_Rica. |
Petición
POST /api/v1/auth/register
Content-Type: application/json
{
"username": "maria_garcia",
"password": "MiClaveSegura123",
"fullName": "María García",
"email": "maria@correo.com",
"timezone": "America/Costa_Rica"
}
Respuesta 201
{
"message": "Cuenta creada correctamente. Revisa tu correo para verificar tu cuenta.",
"username": "maria_garcia",
"email": "maria@correo.com",
"fullName": "María García",
"accountPlan": "FREE"
}
Errores
| 400 | Datos inválidos o faltantes en el cuerpo de la petición. |
| 409 | El nombre de usuario o correo ya está registrado. |
Recuperar contraseña
Envía un email con el enlace de restablecimiento. Siempre retorna 200 para evitar enumeración de cuentas.
Envía un email con el enlace de restablecimiento. Siempre retorna 200 para evitar enumeración de cuentas.
Parámetros
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
email |
string | Sí | Correo electrónico registrado del usuario. |
Petición
POST /api/v1/auth/forgot-password
Content-Type: application/json
{
"email": "maria@correo.com"
}
Respuesta 200
{
"message": "Si ese email está registrado, recibirás instrucciones para restablecer tu contraseña."
}
Valida el token recibido por email y actualiza la contraseña del usuario.
Parámetros
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
token |
string | Sí | Token UUID recibido en el email de recuperación. |
newPassword |
string | Sí | Nueva contraseña en texto plano. Mín. 8 caracteres, máx. 100. |
Petición
POST /api/v1/auth/reset-password
Content-Type: application/json
{
"token": "a1b2c3d4-e5f6-...",
"newPassword": "NuevaClaveSegura123"
}
Respuesta 200
{
"message": "Contraseña restablecida correctamente."
}
Errores
| 400 | Token inválido, expirado o ya utilizado. |
Dashboard
Obtén todos los widgets del dashboard en una sola llamada.
Retorna en una sola respuesta: resumen mensual, reporte semanal de los últimos 7 días, avance de presupuestos, saldos de cuentas y patrimonio neto.
Parámetros
| Parámetro | Tipo | Requerido | Descripción |
|---|---|---|---|
year | integer | Opcional | Año a consultar. Por defecto: año actual. |
month | integer | Opcional | Mes a consultar (1-12). Por defecto: mes actual. |
GET /api/v1/dashboard
GET /api/v1/dashboard?year=2026&month=5
Authorization: Bearer <token>
{
"period": {
"year": 2026,
"month": 5,
"monthName": "Mayo"
},
"summary": {
"totalIncomeCRC": 850000,
"totalExpensesCRC": 620000,
"balanceCRC": 230000,
"exchangeRate": 520.50,
"transactionCount": 34,
"previousMonthTotal": 580000,
"byMacroCategory": {
"Alimentación": 120000,
"Transporte": 80000,
"Entretenimiento": 45000
},
"byCategory": {
"Supermercado": 85000,
"Restaurantes": 35000,
"Gasolina": 50000,
"Bus": 30000,
"Netflix": 25000,
"Cine": 20000
},
"dailyExpenses": {
"1": 15000,
"5": 32000,
"12": 18000
}
},
"weeklyReport": {
"labels": ["Vie", "Sáb", "Dom", "Lun", "Mar", "Mié", "Jue"],
"income": [0, 0, 0, 50000, 0, 0, 0],
"expenses": [12000, 0, 8000, 5000, 0, 22000, 0],
"totalIncome": 50000,
"totalExpenses": 47000,
"balance": 3000
},
"budgets": [
{
"categoryId": "abc123",
"categoryName": "Supermercado",
"macroCategory": "Alimentación",
"amount": 200000,
"spent": 145000,
"remaining": 55000,
"percentage": 72,
"status": "OK"
}
],
"accounts": [
{
"id": "def456",
"name": "BAC Colones",
"type": "BANK_ACCOUNT",
"currency": "CRC",
"currentBalance": 400000,
"creditUsedPct": 0,
"active": true
}
],
"netWorth": {
"totalAssetsCRC": 1200000,
"totalLiabilitiesCRC": 350000,
"netWorthCRC": 850000,
"exchangeRate": 520.50
}
}
Errores
| 401 | API Key ausente o inválida. |
| 429 | Demasiadas peticiones. Límite de tasa excedido. |
Transacciones
Crea, edita y elimina transacciones. Soporta EXPENSE, INCOME y TRANSFER. La cuenta se identifica por su ID interno y la categoría por categoryId o nombre.
Retorna las transacciones del usuario en el rango de fechas indicado. Si no se especifican parámetros, devuelve las del mes en curso.
Parámetros de consulta
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
from |
string | Opcional | Fecha de inicio en formato yyyy-MM-dd. Por defecto: primer día del mes actual. |
to |
string | Opcional | Fecha de fin en formato yyyy-MM-dd. Por defecto: último día del mes actual. |
Ejemplo de petición
GET /api/v1/transactions
GET /api/v1/transactions?from=2025-01-01&to=2025-01-31
X-API-Key: tu_api_key
Ejemplo de respuesta
[
{
"id": "abc123",
"type": "EXPENSE",
"date": "2025-01-15",
"amount": 12500.00,
"currency": "CRC",
"amountCRC": 12500.00,
"exchangeRate": null,
"accountId": "acc1",
"accountName": "Cuenta corriente",
"destinationAccountId": null,
"destinationAccountName": null,
"destinationAmount": null,
"categoryId": "cat1",
"categoryName": "Alimentación",
"notes": "Almuerzo",
"tags": ["trabajo"],
"recurring": false,
"ignoredFromBudget": false,
"createdAt": "2025-01-15T12:30:00"
}
]
Array JSON con uno o más objetos de transacción.
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
type |
string | Sí | EXPENSE (gasto) o INCOME (ingreso) |
date |
string | Sí | Fecha en formato yyyy-MM-dd |
amount |
number | Sí | Monto mayor a cero |
accountId |
string | Sí | ID interno de la cuenta origen (visible en GET /api/v1/accounts). |
categoryId |
string | Sí EXPENSE / INCOME No Opcional: TRANSFER → SAVINGS / INVESTMENT | ID de la categoría (preferido). Alternativa: usar categoryName. |
categoryName |
string | Sí EXPENSE / INCOME No Opcional: TRANSFER → SAVINGS / INVESTMENT | Nombre de la categoría (búsqueda sin distinción de mayúsculas) |
destinationAccountId |
string | TRANSFER | ID de la cuenta destino. Obligatorio para TRANSFER. |
currency |
string | No | CRC o USD. Si se omite, se usa la moneda de la cuenta. |
notes |
string | No | Notas adicionales de la transacción |
exchangeRate |
number | No | Tipo de cambio a aplicar. Si se omite, se usa el del día. |
tags |
string[] | No | Lista de etiquetas (strings). Ej: ["hogar", "mensual"] |
recurring |
boolean | No | Marcar como recurrente. Defecto: false |
ignoredFromBudget |
boolean | No | Excluir del cálculo de presupuestos. Defecto: false |
destinationAccountId apunta a una cuenta de tipo SAVINGS o INVESTMENT, podés incluir opcionalmente categoryId o categoryName para asociar la transferencia a una categoría de presupuesto. Si no se provee, la transferencia se registra igualmente sin categoría.
Ejemplo de petición
[
{
"type": "EXPENSE",
"date": "2025-05-15",
"amount": 12500.00,
"currency": "CRC",
"accountId": "664abc...",
"categoryId": "663def...",
"notes": "Compras del mes",
"tags": ["hogar", "mensual"]
},
{
"type": "TRANSFER",
"date": "2025-05-15",
"amount": 50000.00,
"currency": "CRC",
"accountId": "664abc...",
"destinationAccountId": "664xyz..."
},
{
"type": "TRANSFER",
"date": "2025-05-15",
"amount": 75000.00,
"currency": "CRC",
"accountId": "664abc...",
"destinationAccountId": "664sav...",
"categoryId": "663sav...",
"notes": "Aporte mensual a ahorros"
}
]
Respuesta 200
{
"created": 1,
"failed": 0,
"results": [
{
"index": 0,
"status": "ok",
"id": "6642f3a1c3b4e200..."
}
]
}
Reemplaza todos los campos de la transacción indicada. La cuenta se identifica por accountId y la categoría por categoryId o nombre.
Ejemplo de petición
PUT /api/v1/transactions/6642f3a1c3b4e200...
X-API-Key: tu_api_key
Content-Type: application/json
{
"type": "EXPENSE",
"date": "2025-05-20",
"amount": 15000.00,
"currency": "CRC",
"accountId": "664abc...",
"categoryId": "663def...",
"notes": "Actualizado"
}
Respuesta 200
{
"id": "6642f3a1c3b4e200...",
"type": "EXPENSE",
"date": "2025-05-20",
"amount": 15000.00,
"currency": "CRC",
"amountCRC": 15000.00,
"accountId": "acc1",
"categoryName": "Alimentación",
"notes": "Actualizado"
}
Errores
| 404 | Transacción no encontrada o no pertenece al usuario autenticado. |
| 400 | Datos inválidos o faltantes en el cuerpo de la petición. |
Elimina permanentemente la transacción indicada. Solo puede eliminarse si pertenece al usuario autenticado.
DELETE /api/v1/transactions/6642f3a1c3b4e200...
X-API-Key: tu_api_key
→ 204 No Content
Errores
| 404 | Transacción no encontrada o no pertenece al usuario autenticado. |
Cuentas
Gestiona las cuentas financieras del usuario.
Petición
GET /api/v1/accounts
Authorization: Bearer <token>
Respuesta 200
[
{
"id": "664abc...",
"name": "BAC Visa Oro",
"type": "CREDIT_CARD",
"primaryCurrency": "CRC",
"initialBalance": 0,
"currentBalance": -125000.00,
"color": "#7367f0",
"icon": "fa-solid fa-credit-card",
"ibanId": "CR21-0152-0001-0261-3392-9",
"creditLimit": 500000.00,
"goalAmount": null,
"annualInterestRate": 36.5,
"active": true,
"isDefault": false
},
{
"id": "664def...",
"name": "BAC Colones",
"type": "BANK_ACCOUNT",
"primaryCurrency": "CRC",
"initialBalance": 50000.00,
"currentBalance": 183500.00,
"color": "#28a745",
"icon": "fa-solid fa-building-columns",
"ibanId": null,
"creditLimit": null,
"goalAmount": null,
"annualInterestRate": null,
"active": true,
"isDefault": true
}
]
Parámetros
| Campo | Tipo | Descripción |
|---|---|---|
id | string | Identificador único de la cuenta. |
name | string | Nombre de la cuenta |
type | string | CASH, BANK_ACCOUNT, CREDIT_CARD, DEBIT_CARD, LOAN, INVESTMENT, SAVINGS, RETIREMENT, OTHER |
primaryCurrency | string | Moneda principal: CRC o USD |
initialBalance | number | Saldo inicial. Defecto: 0 |
currentBalance | number | Saldo actual calculado (inicial + movimientos). |
active | boolean | true si la cuenta está activa. |
isDefault | boolean | true si es la cuenta principal del usuario. Se pre-selecciona automáticamente al crear transacciones y vouchers. |
Petición
GET /api/v1/accounts/664abc...
Authorization: Bearer <token>
Respuesta 200
{
"id": "664abc...",
"name": "BAC Colones",
"type": "BANK_ACCOUNT",
"primaryCurrency": "CRC",
"initialBalance": 50000.00,
"currentBalance": 183500.00,
"color": "#28a745",
"icon": "fa-solid fa-building-columns",
"ibanId": null,
"creditLimit": null,
"goalAmount": null,
"annualInterestRate": null,
"active": true,
"isDefault": true
}
Errores
| 404 | Retorna 404 si la cuenta no existe o no pertenece al usuario autenticado. |
Parámetros
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
name | string | Sí | Nombre de la cuenta |
type | string | Sí | CASH, BANK_ACCOUNT, CREDIT_CARD, DEBIT_CARD, LOAN, INVESTMENT, SAVINGS, RETIREMENT, OTHER |
primaryCurrency | string | Sí | Moneda principal: CRC o USD |
initialBalance | number | No | Saldo inicial. Defecto: 0 |
color | string | No | Color hexadecimal para la UI |
icon | string | No | Clase CSS FontAwesome |
ibanId | string | No | IBAN u otro identificador bancario |
creditLimit | number | No | Límite de crédito — solo CREDIT_CARD |
goalAmount | number | No | Meta de ahorro o inversión — solo SAVINGS / INVESTMENT |
annualInterestRate | number | No | Tasa de interés anual en % — solo LOAN / CREDIT_CARD |
Petición
{
"name": "BAC Ahorros",
"type": "SAVINGS",
"primaryCurrency": "CRC",
"initialBalance": 150000.00,
"color": "#28a745",
"icon": "fa-solid fa-piggy-bank",
"goalAmount": 1000000.00
}
Respuesta 200
{
"id": "664xyz...",
"name": "BAC Ahorros",
"type": "SAVINGS",
"primaryCurrency": "CRC",
"initialBalance": 150000.00,
"currentBalance": 150000.00,
"color": "#28a745",
"icon": "fa-solid fa-piggy-bank",
"ibanId": null,
"creditLimit": null,
"goalAmount": 1000000.00,
"annualInterestRate": null,
"active": true,
"isDefault": false
}
Acepta el mismo cuerpo que POST. Solo se pueden editar cuentas propias.
Respuesta 200
{
"id": "664abc...",
"name": "BAC Visa Platinum",
"type": "CREDIT_CARD",
"primaryCurrency": "CRC",
"initialBalance": 0,
"currentBalance": -125000.00,
"color": "#7367f0",
"icon": "fa-solid fa-credit-card",
"ibanId": null,
"creditLimit": 750000.00,
"goalAmount": null,
"annualInterestRate": 36.5,
"active": true,
"isDefault": false
}
La cuenta se marca como inactiva y deja de aparecer en listas. Retorna 204 No Content.
Presupuestos
Administra los límites de gasto mensual por categoría.
Listar presupuestos activos
Parámetros de consulta (query params)
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
year |
integer | No | Año del período (opcional). Si se omite, se usa el año actual según la zona horaria del usuario. |
month |
integer | No | Mes del período 1-12 (opcional). Si se omite, se usa el mes actual según la zona horaria del usuario. |
Petición
GET /api/v1/budgets?year=2026&month=6
Authorization: Bearer <token>
Respuesta 200
[
{
"id": "664abc...",
"categoryId": "663def...",
"categoryName": "Supermercado",
"macroCategory": "Alimentación",
"amount": 200000.00,
"year": 2026,
"month": 6
}
]
Petición
GET /api/v1/budgets/664abc...
Authorization: Bearer <token>
Respuesta 200
{
"id": "664abc...",
"categoryId": "663def...",
"categoryName": "Supermercado",
"macroCategory": "Alimentación",
"amount": 200000.00,
"year": 2026,
"month": 6
}
Errores
| 404 | Retorna 404 si el presupuesto no existe o no pertenece al usuario autenticado. |
Si se envía id, actualiza el monto del presupuesto existente. Si no, crea uno nuevo para el año/mes indicado (o el mes actual si se omiten).
Parámetros
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
id | string | No | ID del presupuesto existente para actualizar. Omitir para crear. |
categoryId | string | Sí | ID de la categoría a presupuestar |
amount | number | Sí | Monto máximo mensual en la moneda base del usuario |
year | integer | No | Año del período (opcional). Si se omite, se usa el año actual según la zona horaria del usuario. |
month | integer | No | Mes del período 1-12 (opcional). Si se omite, se usa el mes actual según la zona horaria del usuario. |
Petición
{
"categoryId": "663def...",
"amount": 200000.00,
"year": 2026,
"month": 6
}
Respuesta 200
{
"id": "664abc...",
"categoryId": "663def...",
"categoryName": "Supermercado",
"macroCategory": "Alimentación",
"amount": 200000.00,
"year": 2026,
"month": 6
}
Petición
DELETE /api/v1/budgets/664abc...
Authorization: Bearer <token>
Respuesta 204
204 No Content
Elimina el presupuesto permanentemente. Retorna 204 No Content.
Recordatorios
Gestiona recordatorios de pago mensual.
[
{
"id": "664abc...",
"name": "BAC Visa",
"type": "CREDIT_CARD",
"dayOfMonth": 15,
"amount": 125000.00,
"currency": "CRC",
"notes": null,
"active": true,
"dismissed": false,
"nextPaymentDate": "2025-06-15"
}
]
Retorna 404 si el recordatorio no existe o no pertenece al usuario autenticado.
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
name | string | Sí | Nombre descriptivo del recordatorio |
type | string | Sí | CREDIT_CARD o BILL |
dayOfMonth | integer | Sí | Día del mes del vencimiento (1-31) |
amount | number | No | Monto esperado del pago |
currency | string | No | CRC o USD |
notes | string | No | Notas adicionales |
{
"name": "BAC Visa",
"type": "CREDIT_CARD",
"dayOfMonth": 15,
"amount": 125000.00,
"currency": "CRC"
}
Acepta el mismo cuerpo que POST. Retorna 204 No Content si fue exitoso.
Desactiva el recordatorio (soft delete). Retorna 204 No Content.
Marca el recordatorio como pagado en el ciclo actual. La alerta reaparece automáticamente el mes siguiente. Retorna 204 No Content.
Categorías
Gestiona las categorías personales del usuario autenticado y consulta las categorías globales.
Retorna las categorías globales y las personales del usuario autenticado.
Respuesta 200
[
{
"id": "6642f3a1c3b4e2001f8a9c1d",
"name": "Supermercado",
"macroCategory": "Alimentación",
"icon": "fa-solid fa-cart-shopping",
"color": "#28a745",
"global": true,
"active": true
}
]
Retorna 404 si la categoría no existe o pertenece a otro usuario.
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
name |
string | Sí | Nombre de la categoría |
macroCategory |
string | Sí | Macrocategoría o grupo al que pertenece |
icon |
string | No | Clase CSS FontAwesome. Defecto: fa-solid fa-tag |
color |
string | No | Color hexadecimal. Defecto: #c0410a |
Ejemplo de petición
[
{
"name": "Netflix",
"macroCategory": "Entretenimiento",
"icon": "fa-brands fa-netflix",
"color": "#e50914"
}
]
Respuesta 200
{
"created": 1,
"failed": 0,
"results": [
{
"index": 0,
"status": "ok",
"id": "6642f3a1c3b4e200..."
}
]
}
Acepta el mismo cuerpo que POST. Solo se pueden editar categorías propias (no globales). Retorna 400 si la validación falla o la categoría no te pertenece.
La categoría no se elimina físicamente; se marca como inactiva y deja de aparecer en las listas. Retorna 204 No Content si fue exitoso.
Perfil
Consulta y actualiza los datos del usuario autenticado.
Retorna todos los datos del perfil del usuario autenticado.
GET /api/v1/profile
Authorization: Bearer <token>
{
"id": "abc123",
"username": "octavio",
"fullName": "Octavio Soto",
"firstName": "Octavio",
"lastName": "Soto",
"email": "octavio@ejemplo.com",
"phone": "88001234",
"phoneCountryCode": "+506",
"country": "CR",
"state": "San José",
"address": "Av. Central",
"zipCode": "10101",
"organization": "Acme S.A.",
"birthDate": "1990-05-15",
"preferredLanguage": "ES",
"preferredTheme": "DARK",
"preferredNumberFormat": "COMMA_DECIMAL",
"timezone": "America/Costa_Rica",
"baseCurrency": "CRC",
"accountPlan": "FREE",
"planExpiresAt": null,
"role": "ROLE_USER",
"profilePhoto": "data:image/jpeg;base64,/9j/4AAQSkZJRgAB..."
}
Actualiza los campos editables del perfil. Los campos username, role y plan son de solo lectura.
PUT /api/v1/profile
Authorization: Bearer <token>
Content-Type: application/json
{
"fullName": "Octavio Soto",
"firstName": "Octavio",
"lastName": "Soto",
"email": "octavio@ejemplo.com",
"phone": "88001234",
"phoneCountryCode": "+506",
"country": "CR",
"state": "San José",
"address": "Av. Central",
"zipCode": "10101",
"organization": "Acme S.A.",
"birthDate": "1990-05-15",
"preferredLanguage": "ES",
"preferredTheme": "DARK",
"preferredNumberFormat": "COMMA_DECIMAL",
"timezone": "America/Costa_Rica",
"baseCurrency": "CRC",
"profilePhoto": "data:image/jpeg;base64,/9j/4AAQSkZJRgAB..."
// null = no modificar foto | "" = eliminar foto | data URI = nueva foto
}
{ /* perfil actualizado, misma estructura que GET */ }
Cambia la contraseña verificando la actual. La nueva debe tener al menos 8 caracteres, una letra, un número y un carácter especial.
PUT /api/v1/profile/password
Authorization: Bearer <token>
Content-Type: application/json
{
"currentPassword": "miContraseñaActual",
"newPassword": "miNuevaContraseña123"
}
{ "message": "Contraseña actualizada correctamente" }
| 400 | Contraseña actual incorrecta o nueva contraseña no cumple los requisitos (letras, números, carácter especial, mínimo 8 caracteres) |
| 401 | API Key ausente o inválida. |
Vouchers
Administra los comprobantes bancarios recibidos por email y pendientes de revisión.
Registra un comprobante manualmente sin pasar por el flujo de email/S3. El voucher queda pendiente de revisión para ser confirmado o descartado. Retorna el voucher creado con código 201.
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
amount |
number | Sí | Monto definitivo en la moneda indicada. Debe ser mayor a cero (obligatorio) |
currency |
string | Sí | Moneda de la transacción: CRC o USD (obligatorio) |
date |
string | No | Fecha definitiva del gasto en formato yyyy-MM-dd (obligatorio) |
merchant |
string | No | Nombre del comercio o descripción del pago (opcional) |
notes |
string | No | Notas adicionales del usuario (opcional) |
Ejemplo de petición
POST /api/v1/vouchers
X-API-Key: tu_api_key
{
"date": "2025-05-20",
"amount": 12500.00,
"currency": "CRC",
"merchant": "Super Mas",
"notes": "Compras de la semana"
}
Respuesta 201
{
"id": "6642f3a1c3b4e200...",
"date": "2025-05-20",
"amount": 12500.00,
"currency": "CRC",
"merchant": "Super Mas",
"notes": "Compras de la semana",
"sourceEmail": null,
"createdAt": "2025-05-20T14:30:00",
"defaultAccountId": "664abc..."
}
Retorna los vouchers bancarios detectados por la IA que aún no han sido confirmados ni descartados. Ordenados de más reciente a más antiguo.
Ejemplo de petición
GET /api/v1/vouchers
X-API-Key: tu_api_key
Respuesta 200
[
{
"id": "6642f3a1c3b4e200...",
"date": "2025-05-20",
"amount": 12500.00,
"currency": "CRC",
"merchant": "Super Mas",
"notes": "Compra en Super Mas por ₡12500",
"sourceEmail": "usuario@gmail.com",
"createdAt": "2025-05-20T14:30:00",
"defaultAccountId": "664abc..."
}
]
Parámetros
| Campo | Tipo | Descripción |
|---|---|---|
id | string | Identificador único del voucher. |
date | string | Fecha definitiva del gasto en formato yyyy-MM-dd (obligatorio) |
amount | number | Monto definitivo en la moneda indicada. Debe ser mayor a cero (obligatorio) |
currency | string | Moneda de la transacción: CRC o USD (obligatorio) |
merchant | string | Nombre del comercio o descripción del pago (opcional) |
notes | string | Notas adicionales del usuario (opcional) |
sourceEmail | string | Email que reenvió el comprobante. null si se creó por API. |
createdAt | string | Fecha y hora de creación en UTC (ISO 8601). |
defaultAccountId | string | ID de la cuenta principal del usuario en el momento de crear el voucher. Se usa para pre-seleccionar la cuenta en el modal de confirmación. null si no tenía cuenta principal. |
Convierte el voucher en una transacción registrada con los datos revisados por el usuario. El voucher se elimina de la lista pendiente. Retorna la transacción creada con código 200.
Parámetros de consulta
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
accountId |
string | Sí | ID de la cuenta origen del gasto (obligatorio) |
date |
string | Sí | Fecha definitiva del gasto en formato yyyy-MM-dd (obligatorio) |
amount |
number | Sí | Monto definitivo en la moneda indicada. Debe ser mayor a cero (obligatorio) |
currency |
string | Sí | Moneda de la transacción: CRC o USD (obligatorio) |
categoryId |
string | No | ID de la categoría a asignar (opcional) |
notes |
string | No | Notas adicionales del usuario (opcional) |
counterAmount |
number | No | Monto equivalente en la moneda opuesta (opcional; usar solo si la cuenta maneja una moneda distinta al gasto) |
Ejemplo de petición
POST /api/v1/vouchers/6642f3a1c3b4e200.../confirm
X-API-Key: tu_api_key
{
"accountId": "acc123",
"categoryId": "cat456",
"date": "2025-05-20",
"amount": 12500.00,
"currency": "CRC",
"notes": "Compras del mes"
}
Respuesta 200
{
"id": "6642f3a1c3b4e201...",
"type": "EXPENSE",
"date": "2025-05-20",
"amount": 12500.00,
"currency": "CRC",
"amountCRC": 12500.00,
"exchangeRate": 1,
"accountId": "acc123",
"accountName": "BAC Corriente",
"categoryId": "cat456",
"categoryName": "Supermercado",
"notes": "Compras del mes",
"recurring": false,
"ignoredFromBudget": false,
"createdAt": "2025-05-20T14:35:00"
}
Elimina el voucher de la lista pendiente sin crear ninguna transacción. Útil para comprobantes que no corresponden a gastos reales. Retorna 204 No Content.
DELETE /api/v1/vouchers/6642f3a1c3b4e200...
X-API-Key: tu_api_key
→ 204 No Content
Envía una imagen de comprobante bancario en base64; la IA extrae las transacciones y crea un voucher pendiente por cada una.
Campo
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
image |
string | Sí | Imagen del comprobante en base64 puro o como data URI completo (data:image/jpeg;base64,...). |
mimeType |
string | No | Tipo MIME de la imagen: image/jpeg, image/png, image/gif o image/webp. Se puede omitir si se envía como data URI. |
Ejemplo de petición
{
"image": "data:image/jpeg;base64,/9j/4AAQSkZ...",
"mimeType": "image/jpeg"
}
Respuesta 200
[
{
"id": "664abc...",
"date": "2025-05-20",
"amount": 15800.00,
"currency": "CRC",
"merchant": "WALMART LINDORA",
"notes": "Compra en WALMART LINDORA",
"sourceEmail": null,
"createdAt": "2025-05-20T18:32:00"
}
]
Tipo de Cambio USD → CRC
Consulta y actualiza el tipo de cambio registrado por el usuario para una fecha específica.
Retorna el tipo de cambio USD → CRC registrado para la fecha indicada. Si no se especifica fecha, usa la fecha de hoy en la zona horaria del usuario.
Parámetros de consulta
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
date |
string | No | Fecha del tipo de cambio en formato yyyy-MM-dd. Si se omite, usa la fecha de hoy. |
Ejemplo de petición
GET /api/v1/exchange-rate
GET /api/v1/exchange-rate?date=2026-06-02
X-API-Key: tu_api_key
Respuesta 200
{
"date": "2026-06-02",
"rate": 519.50,
"userId": "abc123"
}
Registra o actualiza el tipo de cambio para la fecha indicada. Si ya existe un registro para esa fecha, lo reemplaza.
Campo
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
rate |
number | Sí | Cantidad de colones equivalentes a 1 dólar (mayor a cero). |
date |
string | No | Fecha del tipo de cambio en formato yyyy-MM-dd. Si se omite, usa la fecha de hoy. |
Ejemplo de petición
PUT /api/v1/exchange-rate
X-API-Key: tu_api_key
{
"rate": 519.50,
"date": "2026-06-02"
}
Respuesta 200
{
"date": "2026-06-02",
"rate": 519.50,
"userId": "abc123"
}
Errores
| 400 | Datos inválidos o faltantes en el cuerpo de la petición. |
Asesor Financiero IA
Consulta y regenera los consejos del asesor financiero con inteligencia artificial.
Retorna los consejos almacenados en caché para el usuario y contexto indicados. Si no existen consejos previos, devuelve una lista vacía junto con los metadatos de control de actualización.
Parámetros de consulta
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
contextId |
string | Sí | Contexto del análisis: "personal" para datos propios del usuario, o el ID de un grupo compartido. |
Ejemplo de petición
GET /api/v1/advice?contextId=personal
Authorization: Bearer <token>
Respuesta 200
{
"userId": "abc123",
"contextId": "personal",
"advices": [
{
"title": "Reduce gastos en comida",
"description": "Tus gastos en alimentación representan el 40% de tus ingresos mensuales.",
"actionItem": "Prepara al menos 3 comidas en casa por semana.",
"category": "FOOD",
"priority": "HIGH"
}
],
"canRefresh": false,
"nextRefreshAt": "2026-06-09T10:30:00"
}
Errores
| 403 | El usuario autenticado no coincide con el userId solicitado. |
Fuerza la regeneración de consejos con IA para el userId y contextId indicados. Respeta el límite de una actualización cada 7 días.
Parámetros de consulta
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
contextId |
string | Sí | Contexto del análisis: "personal" para datos propios del usuario, o el ID de un grupo compartido. |
429 Too Many Requests.
Ejemplo de petición
PUT /api/v1/advice?contextId=personal
Authorization: Bearer <token>
Respuesta 200
{
"userId": "abc123",
"contextId": "personal",
"advices": [
{
"title": "Fondo de emergencia insuficiente",
"description": "Tu ahorro actual cubre solo 0.5 meses de gastos.",
"actionItem": "Destina el 10% de tus ingresos mensuales a una cuenta de ahorro dedicada.",
"category": "SAVINGS",
"priority": "HIGH"
}
],
"canRefresh": false,
"nextRefreshAt": "2026-06-09T10:30:00"
}
Respuesta 429
{
"error": "No puedes actualizar los consejos hasta el 2026-06-09",
"nextRefreshAt": "2026-06-09T10:30:00"
}
Errores
| 403 | El usuario autenticado no coincide con el userId solicitado. |
| 429 | El período mínimo de 7 días entre actualizaciones no ha transcurrido. El campo nextRefreshAt indica cuándo estará disponible. |