Reporte de Órdenes

Reporte de órdenes a nivel de transacción

Reporte de Órdenes

El Reporte de Órdenes proporciona una vista a nivel de transacción de todas las órdenes asociadas con una cuenta virtual, con filtros potentes y estadísticas de resumen.

¿Qué es el Reporte de Órdenes?

Mientras el Estado de Cuenta muestra movimientos de saldo, el Reporte de Órdenes muestra las órdenes/transacciones subyacentes que causaron esos movimientos.

Estado de CuentaReporte de Órdenes
Enfocado en saldosEnfocado en transacciones
Muestra débitos/créditosMuestra detalles de orden
Saldo actualizadoSeguimiento de estado
Para conciliaciónPara análisis de transacciones

Conceptos Clave

Tipos de Orden

TipoDescripción
PAYINPago de cliente recibido
PAYOUTPago a proveedor enviado
ONRAMPFiat convertido a crypto
OFFRAMPCrypto convertido a fiat
BALANCE_TRANSFERCambio de divisa entre cuentas
PAYMENT_LINKPago vía link de pago

Estados de Orden

EstadoDescripción
DRAFTOrden creada pero no enviada
PENDINGEsperando pago o procesamiento
PAIDPago recibido, procesando
PROCESSINGSiendo procesada
COMPLETEDCompletada exitosamente
FAILEDFalló al completar
CANCELLEDCancelada por usuario o sistema
REFUNDEDPago reembolsado
REFUND_REQUESTEDReembolso en progreso
EXPIREDOrden expirada
ON_HOLDTemporalmente retenida

Endpoint de API

GET /api/v1/organizations/{organizationId}/merchants/{merchantId}/accounts/{accountId}/reports/orders

Parámetros de Ruta

ParámetroRequeridoDescripción
organizationIdID de organización
merchantIdID de comercio
accountIdID de cuenta virtual

Parámetros de Query

ParámetroRequeridoDefaultDescripción
from-Fecha inicio (YYYY-MM-DD)
to-Fecha fin (YYYY-MM-DD)
typeNo-Filtrar por tipo de orden
statusNo-Filtrar por estado de orden
cursorNo-Cursor de paginación
limitNo50Items por página (1-100)

Ejemplo Rápido

1const response = await axios.get(
2 `https://api.koywe.com/api/v1/organizations/${orgId}/merchants/${merchantId}/accounts/${accountId}/reports/orders`,
3 {
4 params: {
5 from: '2025-01-01',
6 to: '2025-01-31'
7 },
8 headers: { 'Authorization': `Bearer ${token}` }
9 }
10);
11
12console.log('Total Órdenes:', response.data.summary.totalOrders);
13console.log('Por Tipo:', response.data.summary.byType);
14console.log('Por Estado:', response.data.summary.byStatus);

Filtrar por Tipo

Obtener solo tipos específicos de órdenes:

1// Obtener solo órdenes PAYIN
2const payinOrders = await axios.get(
3 `https://api.koywe.com/api/v1/organizations/${orgId}/merchants/${merchantId}/accounts/${accountId}/reports/orders`,
4 {
5 params: {
6 from: '2025-01-01',
7 to: '2025-01-31',
8 type: 'PAYIN'
9 },
10 headers: { 'Authorization': `Bearer ${token}` }
11 }
12);
13
14console.log('Órdenes PAYIN:', payinOrders.data.orders.length);
15
16// Obtener solo órdenes PAYOUT
17const payoutOrders = await axios.get(
18 `https://api.koywe.com/api/v1/organizations/${orgId}/merchants/${merchantId}/accounts/${accountId}/reports/orders`,
19 {
20 params: {
21 from: '2025-01-01',
22 to: '2025-01-31',
23 type: 'PAYOUT'
24 },
25 headers: { 'Authorization': `Bearer ${token}` }
26 }
27);
28
29console.log('Órdenes PAYOUT:', payoutOrders.data.orders.length);

Filtrar por Estado

Obtener órdenes con estados específicos:

1// Obtener solo órdenes completadas
2const completedOrders = await axios.get(
3 `https://api.koywe.com/api/v1/organizations/${orgId}/merchants/${merchantId}/accounts/${accountId}/reports/orders`,
4 {
5 params: {
6 from: '2025-01-01',
7 to: '2025-01-31',
8 status: 'COMPLETED'
9 },
10 headers: { 'Authorization': `Bearer ${token}` }
11 }
12);
13
14console.log('Órdenes completadas:', completedOrders.data.orders.length);
15
16// Obtener órdenes fallidas para investigación
17const failedOrders = await axios.get(
18 `https://api.koywe.com/api/v1/organizations/${orgId}/merchants/${merchantId}/accounts/${accountId}/reports/orders`,
19 {
20 params: {
21 from: '2025-01-01',
22 to: '2025-01-31',
23 status: 'FAILED'
24 },
25 headers: { 'Authorization': `Bearer ${token}` }
26 }
27);
28
29console.log('Órdenes fallidas a investigar:', failedOrders.data.orders.length);

Entendiendo la Respuesta

1{
2 "accountId": "acc_0031c537-2301-40ab-9153-0f7c48505350",
3 "currency": "CLP",
4 "periodStart": "2025-01-01T00:00:00.000Z",
5 "periodEnd": "2025-01-31T23:59:59.999Z",
6 "orders": [
7 {
8 "orderId": "ord_abc123",
9 "type": "PAYIN",
10 "status": "COMPLETED",
11 "amountIn": "1000000.00",
12 "amountOut": "1000000.00",
13 "originCurrency": "CLP",
14 "destinationCurrency": "CLP",
15 "counterparty": {
16 "name": "Juan Pérez",
17 "identifier": "12345678-9"
18 },
19 "createdAt": "2025-01-15T10:30:00.000Z",
20 "completedAt": "2025-01-15T10:35:00.000Z",
21 "externalId": "FAC-2025-001"
22 },
23 {
24 "orderId": "ord_def456",
25 "type": "PAYOUT",
26 "status": "COMPLETED",
27 "amountIn": "500000.00",
28 "amountOut": "500000.00",
29 "originCurrency": "CLP",
30 "destinationCurrency": "CLP",
31 "counterparty": {
32 "name": "Proveedor SA",
33 "identifier": "98765432-1"
34 },
35 "createdAt": "2025-01-20T14:00:00.000Z",
36 "completedAt": "2025-01-20T14:15:00.000Z",
37 "externalId": "OC-2025-042"
38 }
39 ],
40 "summary": {
41 "totalOrders": 150,
42 "byType": {
43 "PAYIN": 100,
44 "PAYOUT": 50
45 },
46 "byStatus": {
47 "COMPLETED": 140,
48 "PENDING": 5,
49 "FAILED": 5
50 }
51 },
52 "pagination": {
53 "cursor": "eyJvcmRlcklkIjoib3JkX2RlZjQ1NiJ9",
54 "hasMore": true,
55 "limit": 50
56 },
57 "generatedAt": "2025-01-31T12:00:00.000Z"
58}

Campos de Respuesta

CampoDescripción
orders[]Array de objetos de orden
orders[].orderIdID único de orden
orders[].counterpartyInformación de contacto/pagador
orders[].externalIdTu ID de referencia (si se proporcionó)
summary.totalOrdersTotal de órdenes en el período
summary.byTypeDesglose por tipo de orden
summary.byStatusDesglose por estado

Entendiendo el Resumen

El objeto summary proporciona estadísticas agregadas para análisis rápido:

Node.js
1const response = await axios.get(
2 `https://api.koywe.com/api/v1/organizations/${orgId}/merchants/${merchantId}/accounts/${accountId}/reports/orders`,
3 {
4 params: { from: '2025-01-01', to: '2025-01-31' },
5 headers: { 'Authorization': `Bearer ${token}` }
6 }
7);
8
9const { summary } = response.data;
10
11// Análisis de volumen
12console.log('=== Volumen Mensual ===');
13console.log(`Total Órdenes: ${summary.totalOrders}`);
14
15// Por tipo
16console.log('\n=== Por Tipo ===');
17Object.entries(summary.byType).forEach(([type, count]) => {
18 console.log(`${type}: ${count} órdenes`);
19});
20
21// Por estado
22console.log('\n=== Por Estado ===');
23Object.entries(summary.byStatus).forEach(([status, count]) => {
24 const percentage = ((count / summary.totalOrders) * 100).toFixed(1);
25 console.log(`${status}: ${count} (${percentage}%)`);
26});
27
28// Tasa de éxito
29const completed = summary.byStatus.COMPLETED || 0;
30const failed = summary.byStatus.FAILED || 0;
31const successRate = (completed / (completed + failed) * 100).toFixed(1);
32console.log(`\nTasa de Éxito: ${successRate}%`);

Tip de Conciliación

Relacionar Órdenes con Movimientos del Libro Mayor: Cada movimiento del libro mayor incluye un campo orderId. Usa esto para hacer referencias cruzadas entre el Reporte de Órdenes y el Estado de Cuenta.

1// Obtener estado de cuenta
2const ledger = await getLedgerStatement(orgId, merchantId, accountId, from, to, token);
3
4// Obtener reporte de órdenes
5const orders = await getOrdersReport(orgId, merchantId, accountId, from, to, token);
6
7// Referencia cruzada
8ledger.movements.forEach(movement => {
9 if (movement.orderId) {
10 const order = orders.orders.find(o => o.orderId === movement.orderId);
11 if (order) {
12 console.log(`Movimiento ${movement.ledgerEntryId} coincide con Orden ${order.orderId} (${order.type})`);
13 }
14 }
15});

Ejemplo de Integración Completa

Node.js
1async function generarAnalisisDeOrdenes(orgId, merchantId, accountId, from, to, token) {
2 // Obtener todas las órdenes (manejando paginación)
3 const todasLasOrdenes = [];
4 let cursor = null;
5 let summary = null;
6
7 do {
8 const response = await axios.get(
9 `https://api.koywe.com/api/v1/organizations/${orgId}/merchants/${merchantId}/accounts/${accountId}/reports/orders`,
10 {
11 params: {
12 from,
13 to,
14 limit: 100,
15 ...(cursor && { cursor })
16 },
17 headers: { 'Authorization': `Bearer ${token}` }
18 }
19 );
20
21 todasLasOrdenes.push(...response.data.orders);
22 summary = response.data.summary;
23 cursor = response.data.pagination.hasMore ? response.data.pagination.cursor : null;
24
25 } while (cursor);
26
27 // Generar análisis
28 console.log('='.repeat(60));
29 console.log('REPORTE DE ANÁLISIS DE ÓRDENES');
30 console.log(`Período: ${from} a ${to}`);
31 console.log('='.repeat(60));
32
33 // Estadísticas de resumen
34 console.log('\n📊 RESUMEN');
35 console.log(`Total Órdenes: ${summary.totalOrders}`);
36
37 // Desglose por tipo
38 console.log('\n📈 POR TIPO');
39 Object.entries(summary.byType).forEach(([type, count]) => {
40 const pct = ((count / summary.totalOrders) * 100).toFixed(1);
41 console.log(` ${type.padEnd(20)} ${String(count).padStart(5)} (${pct}%)`);
42 });
43
44 // Desglose por estado
45 console.log('\n📋 POR ESTADO');
46 Object.entries(summary.byStatus).forEach(([status, count]) => {
47 const pct = ((count / summary.totalOrders) * 100).toFixed(1);
48 console.log(` ${status.padEnd(20)} ${String(count).padStart(5)} (${pct}%)`);
49 });
50
51 // Calcular totales por tipo
52 console.log('\n💰 VOLUMEN POR TIPO');
53 const volumenPorTipo = {};
54 todasLasOrdenes.forEach(order => {
55 if (!volumenPorTipo[order.type]) {
56 volumenPorTipo[order.type] = 0;
57 }
58 volumenPorTipo[order.type] += parseFloat(order.amountIn);
59 });
60
61 Object.entries(volumenPorTipo).forEach(([type, volume]) => {
62 console.log(` ${type.padEnd(20)} ${volume.toLocaleString()}`);
63 });
64
65 // Detalle de órdenes fallidas
66 const ordenesFallidas = todasLasOrdenes.filter(o => o.status === 'FAILED');
67 if (ordenesFallidas.length > 0) {
68 console.log('\n⚠️ ÓRDENES FALLIDAS');
69 ordenesFallidas.forEach(order => {
70 console.log(` ${order.orderId} | ${order.type} | ${order.amountIn} | ${order.createdAt}`);
71 });
72 }
73
74 console.log('\n' + '='.repeat(60));
75
76 return { orders: todasLasOrdenes, summary };
77}
78
79// Uso
80const analisis = await generarAnalisisDeOrdenes(
81 'org3_xxx',
82 'mrc_xxx',
83 'acc_xxx',
84 '2025-01-01',
85 '2025-01-31',
86 token
87);

Próximos Pasos