Detalle de Movimiento

Recibo de transacción y comprobante

Detalle de Movimiento

El endpoint de Detalle de Movimiento proporciona un recibo detallado para un movimiento específico del libro mayor, perfecto para documentación de auditoría, soporte al cliente y comprobantes contables.

¿Qué es un Recibo de Movimiento?

Cada movimiento en tu estado de cuenta tiene un ledgerEntryId único. Usa este ID para obtener información detallada sobre esa transacción específica, incluyendo:

  • Saldo antes y después del movimiento
  • Detalles del comercio y cuenta
  • Referencias a órdenes o liquidaciones asociadas
  • Descripción legible

Casos de Uso

Cuándo usar Detalle de Movimiento:

  • Documentación de auditoría: Generar comprobantes de transacciones específicas
  • Soporte al cliente: Recuperar rápidamente detalles de transacciones para consultas
  • Comprobante contable: Proporcionar recibos detallados para contabilidad
  • Resolución de disputas: Documentar detalles de transacciones para disputas
  • Cumplimiento: Mantener registros detallados para requisitos regulatorios

Endpoint de API

GET /api/v1/organizations/{organizationId}/merchants/{merchantId}/accounts/{accountId}/reports/ledger-entry/{ledgerEntryId}

Parámetros de Ruta

ParámetroRequeridoDescripción
organizationIdID de organización
merchantIdID de comercio
accountIdID de cuenta virtual
ledgerEntryIdID de entrada del libro mayor (del estado de cuenta)

Ejemplo Rápido

1const response = await axios.get(
2 `https://api.koywe.com/api/v1/organizations/${orgId}/merchants/${merchantId}/accounts/${accountId}/reports/ledger-entry/137`,
3 {
4 headers: { 'Authorization': `Bearer ${token}` }
5 }
6);
7
8console.log('ID de Entrada:', response.data.ledgerEntryId);
9console.log('Monto:', response.data.amount, response.data.currency);
10console.log('Saldo Antes:', response.data.balanceBefore);
11console.log('Saldo Después:', response.data.balanceAfter);
12console.log('Descripción:', response.data.description);

Entendiendo la Respuesta

1{
2 "ledgerEntryId": "137",
3 "accountId": "acc_0031c537-2301-40ab-9153-0f7c48505350",
4 "merchantId": "mrc_2e8f96ab-dbd5-45f9-b4b6-645945daf340",
5 "merchantName": "Acme Corporation",
6 "type": "credit",
7 "amount": "1000000.00",
8 "currency": "CLP",
9 "postedAt": "2025-01-15T10:30:00.000Z",
10 "description": "PAYIN de Juan Pérez - Transferencia bancaria recibida",
11 "category": "PAYIN",
12 "references": {
13 "orderId": "ord_abc123",
14 "settlementId": null
15 },
16 "balanceBefore": "4000000.00",
17 "balanceAfter": "5000000.00",
18 "generatedAt": "2025-01-31T12:00:00.000Z"
19}

Explicación de Campos de Respuesta

CampoDescripción
ledgerEntryIdIdentificador único de esta entrada del libro mayor
merchantIdID del comercio asociado con la cuenta
merchantNameNombre del comercio legible
typecredit (aumenta saldo) o debit (disminuye saldo)
amountMonto de la transacción
currencySímbolo de moneda
postedAtMarca de tiempo cuando se registró el movimiento
descriptionDescripción legible
categoryCategoría de movimiento (PAYIN, PAYOUT, SETTLEMENT, etc.)
references.orderIdID de orden asociada (si aplica)
references.settlementIdID de liquidación asociada (si aplica)
balanceBeforeSaldo de cuenta antes de este movimiento
balanceAfterSaldo de cuenta después de este movimiento

Los campos balanceBefore y balanceAfter proporcionan prueba lista para auditoría de cómo la transacción afectó el saldo de la cuenta.


Flujo de Trabajo: Del Estado de Cuenta al Detalle

El flujo típico es primero obtener un estado de cuenta, luego obtener detalles de entradas específicas:


Ejemplo Completo: Del Estado al Detalle

1async function obtenerReciboTransaccion(orgId, merchantId, accountId, date, token) {
2 // Paso 1: Obtener estado de cuenta para la fecha
3 const statementResponse = await axios.get(
4 `https://api.koywe.com/api/v1/organizations/${orgId}/merchants/${merchantId}/accounts/${accountId}/reports/ledger-statement`,
5 {
6 params: {
7 from: date,
8 to: date
9 },
10 headers: { 'Authorization': `Bearer ${token}` }
11 }
12 );
13
14 const movements = statementResponse.data.movements;
15 console.log(`Encontrados ${movements.length} movimientos en ${date}`);
16
17 // Paso 2: Obtener detalles de cada movimiento
18 const recibos = [];
19
20 for (const movement of movements) {
21 console.log(`\nObteniendo detalles para entrada ${movement.ledgerEntryId}...`);
22
23 const detailResponse = await axios.get(
24 `https://api.koywe.com/api/v1/organizations/${orgId}/merchants/${merchantId}/accounts/${accountId}/reports/ledger-entry/${movement.ledgerEntryId}`,
25 {
26 headers: { 'Authorization': `Bearer ${token}` }
27 }
28 );
29
30 const recibo = detailResponse.data;
31 recibos.push(recibo);
32
33 // Imprimir recibo
34 console.log('='.repeat(50));
35 console.log('RECIBO DE TRANSACCIÓN');
36 console.log('='.repeat(50));
37 console.log(`ID Entrada: ${recibo.ledgerEntryId}`);
38 console.log(`Fecha: ${recibo.postedAt}`);
39 console.log(`Comercio: ${recibo.merchantName}`);
40 console.log(`Tipo: ${recibo.type.toUpperCase()}`);
41 console.log(`Categoría: ${recibo.category}`);
42 console.log(`Monto: ${recibo.amount} ${recibo.currency}`);
43 console.log('-'.repeat(50));
44 console.log(`Saldo Antes: ${recibo.balanceBefore} ${recibo.currency}`);
45 console.log(`Saldo Después: ${recibo.balanceAfter} ${recibo.currency}`);
46 console.log('-'.repeat(50));
47 console.log(`Descripción: ${recibo.description}`);
48
49 if (recibo.references.orderId) {
50 console.log(`ID Orden: ${recibo.references.orderId}`);
51 }
52 if (recibo.references.settlementId) {
53 console.log(`ID Liquidación: ${recibo.references.settlementId}`);
54 }
55
56 console.log('='.repeat(50));
57 }
58
59 return recibos;
60}
61
62// Uso: Obtener todos los recibos del 15 de enero 2025
63const recibos = await obtenerReciboTransaccion(
64 'org3_xxx',
65 'mrc_xxx',
66 'acc_xxx',
67 '2025-01-15',
68 token
69);

Encontrar el ID de Entrada del Libro Mayor

El ledgerEntryId está disponible en la respuesta del estado de cuenta. Así es cómo encontrar una entrada específica:

1// Encontrar entrada del libro mayor por orden asociada
2const statement = await getLedgerStatement(orgId, merchantId, accountId, from, to, token);
3
4const targetOrderId = 'ord_abc123';
5const entry = statement.movements.find(m => m.orderId === targetOrderId);
6
7if (entry) {
8 console.log(`Encontrada entrada ${entry.ledgerEntryId} para orden ${targetOrderId}`);
9 // Ahora obtener detalles
10 const recibo = await getLedgerEntryDetails(orgId, merchantId, accountId, entry.ledgerEntryId, token);
11}

Manejo de Errores

Errores Comunes:

  • 404 Not Found: El ID de entrada del libro mayor no existe o no pertenece a la cuenta especificada
  • 403 Forbidden: La entrada no pertenece al comercio o permisos insuficientes
  • 401 Unauthorized: Token inválido o expirado
Manejo de Errores
1async function obtenerEntradaSegura(orgId, merchantId, accountId, entryId, token) {
2 try {
3 const response = await axios.get(
4 `https://api.koywe.com/api/v1/organizations/${orgId}/merchants/${merchantId}/accounts/${accountId}/reports/ledger-entry/${entryId}`,
5 {
6 headers: { 'Authorization': `Bearer ${token}` }
7 }
8 );
9 return response.data;
10 } catch (error) {
11 if (error.response?.status === 404) {
12 console.error(`Entrada del libro mayor ${entryId} no encontrada`);
13 return null;
14 }
15 if (error.response?.status === 403) {
16 console.error(`Acceso denegado a entrada ${entryId}`);
17 return null;
18 }
19 throw error;
20 }
21}

Próximos Pasos