Koywe

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

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

Parámetros de Ruta

ParámetroRequeridoDescripción
organizationIdSíID de organización
merchantIdSíID de comercio
accountIdSíID de cuenta virtual

Parámetros de Query

ParámetroRequeridoDefaultDescripción
fromSí-Fecha inicio (YYYY-MM-DD)
toSí-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

const response = await axios.get(
  `https://api.koywe.com/api/v1/organizations/${orgId}/merchants/${merchantId}/accounts/${accountId}/reports/orders`,
  {
    params: {
      from: '2025-01-01',
      to: '2025-01-31'
    },
    headers: { 'Authorization': `Bearer ${token}` }
  }
);
 
console.log('Total Órdenes:', response.data.summary.totalOrders);
console.log('Por Tipo:', response.data.summary.byType);
console.log('Por Estado:', response.data.summary.byStatus);

Filtrar por Tipo

Obtener solo tipos específicos de órdenes:

// Obtener solo órdenes PAYIN
const payinOrders = await axios.get(
  `https://api.koywe.com/api/v1/organizations/${orgId}/merchants/${merchantId}/accounts/${accountId}/reports/orders`,
  {
    params: {
      from: '2025-01-01',
      to: '2025-01-31',
      type: 'PAYIN'
    },
    headers: { 'Authorization': `Bearer ${token}` }
  }
);
 
console.log('Órdenes PAYIN:', payinOrders.data.orders.length);
 
// Obtener solo órdenes PAYOUT
const payoutOrders = await axios.get(
  `https://api.koywe.com/api/v1/organizations/${orgId}/merchants/${merchantId}/accounts/${accountId}/reports/orders`,
  {
    params: {
      from: '2025-01-01',
      to: '2025-01-31',
      type: 'PAYOUT'
    },
    headers: { 'Authorization': `Bearer ${token}` }
  }
);
 
console.log('Órdenes PAYOUT:', payoutOrders.data.orders.length);

Filtrar por Estado

Obtener órdenes con estados específicos:

// Obtener solo órdenes completadas
const completedOrders = await axios.get(
  `https://api.koywe.com/api/v1/organizations/${orgId}/merchants/${merchantId}/accounts/${accountId}/reports/orders`,
  {
    params: {
      from: '2025-01-01',
      to: '2025-01-31',
      status: 'COMPLETED'
    },
    headers: { 'Authorization': `Bearer ${token}` }
  }
);
 
console.log('Órdenes completadas:', completedOrders.data.orders.length);
 
// Obtener órdenes fallidas para investigación
const failedOrders = await axios.get(
  `https://api.koywe.com/api/v1/organizations/${orgId}/merchants/${merchantId}/accounts/${accountId}/reports/orders`,
  {
    params: {
      from: '2025-01-01',
      to: '2025-01-31',
      status: 'FAILED'
    },
    headers: { 'Authorization': `Bearer ${token}` }
  }
);
 
console.log('Órdenes fallidas a investigar:', failedOrders.data.orders.length);

Entendiendo la Respuesta

JSON
{
  "accountId": "acc_0031c537-2301-40ab-9153-0f7c48505350",
  "currency": "CLP",
  "periodStart": "2025-01-01T00:00:00.000Z",
  "periodEnd": "2025-01-31T23:59:59.999Z",
  "orders": [
    {
      "orderId": "ord_abc123",
      "type": "PAYIN",
      "status": "COMPLETED",
      "amountIn": "1000000.00",
      "amountOut": "1000000.00",
      "originCurrency": "CLP",
      "destinationCurrency": "CLP",
      "counterparty": {
        "name": "Juan Pérez",
        "identifier": "12345678-9"
      },
      "createdAt": "2025-01-15T10:30:00.000Z",
      "completedAt": "2025-01-15T10:35:00.000Z",
      "externalId": "FAC-2025-001"
    },
    {
      "orderId": "ord_def456",
      "type": "PAYOUT",
      "status": "COMPLETED",
      "amountIn": "500000.00",
      "amountOut": "500000.00",
      "originCurrency": "CLP",
      "destinationCurrency": "CLP",
      "counterparty": {
        "name": "Proveedor SA",
        "identifier": "98765432-1"
      },
      "createdAt": "2025-01-20T14:00:00.000Z",
      "completedAt": "2025-01-20T14:15:00.000Z",
      "externalId": "OC-2025-042"
    }
  ],
  "summary": {
    "totalOrders": 150,
    "byType": {
      "PAYIN": 100,
      "PAYOUT": 50
    },
    "byStatus": {
      "COMPLETED": 140,
      "PENDING": 5,
      "FAILED": 5
    }
  },
  "pagination": {
    "cursor": "eyJvcmRlcklkIjoib3JkX2RlZjQ1NiJ9",
    "hasMore": true,
    "limit": 50
  },
  "generatedAt": "2025-01-31T12:00:00.000Z"
}

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:

JavaScript
const response = await axios.get(
  `https://api.koywe.com/api/v1/organizations/${orgId}/merchants/${merchantId}/accounts/${accountId}/reports/orders`,
  {
    params: { from: '2025-01-01', to: '2025-01-31' },
    headers: { 'Authorization': `Bearer ${token}` }
  }
);
 
const { summary } = response.data;
 
// Análisis de volumen
console.log('=== Volumen Mensual ===');
console.log(`Total Órdenes: ${summary.totalOrders}`);
 
// Por tipo
console.log('\n=== Por Tipo ===');
Object.entries(summary.byType).forEach(([type, count]) => {
  console.log(`${type}: ${count} órdenes`);
});
 
// Por estado
console.log('\n=== Por Estado ===');
Object.entries(summary.byStatus).forEach(([status, count]) => {
  const percentage = ((count / summary.totalOrders) * 100).toFixed(1);
  console.log(`${status}: ${count} (${percentage}%)`);
});
 
// Tasa de éxito
const completed = summary.byStatus.COMPLETED || 0;
const failed = summary.byStatus.FAILED || 0;
const successRate = (completed / (completed + failed) * 100).toFixed(1);
console.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.

JavaScript
// Obtener estado de cuenta
const ledger = await getLedgerStatement(orgId, merchantId, accountId, from, to, token);
 
// Obtener reporte de órdenes
const orders = await getOrdersReport(orgId, merchantId, accountId, from, to, token);
 
// Referencia cruzada
ledger.movements.forEach(movement => {
  if (movement.orderId) {
    const order = orders.orders.find(o => o.orderId === movement.orderId);
    if (order) {
      console.log(`Movimiento ${movement.ledgerEntryId} coincide con Orden ${order.orderId} (${order.type})`);
    }
  }
});

Ejemplo de Integración Completa

JavaScript
async function generarAnalisisDeOrdenes(orgId, merchantId, accountId, from, to, token) {
  // Obtener todas las órdenes (manejando paginación)
  const todasLasOrdenes = [];
  let cursor = null;
  let summary = null;
  
  do {
    const response = await axios.get(
      `https://api.koywe.com/api/v1/organizations/${orgId}/merchants/${merchantId}/accounts/${accountId}/reports/orders`,
      {
        params: {
          from,
          to,
          limit: 100,
          ...(cursor && { cursor })
        },
        headers: { 'Authorization': `Bearer ${token}` }
      }
    );
    
    todasLasOrdenes.push(...response.data.orders);
    summary = response.data.summary;
    cursor = response.data.pagination.hasMore ? response.data.pagination.cursor : null;
    
  } while (cursor);
  
  // Generar análisis
  console.log('='.repeat(60));
  console.log('REPORTE DE ANÁLISIS DE ÓRDENES');
  console.log(`Período: ${from} a ${to}`);
  console.log('='.repeat(60));
  
  // Estadísticas de resumen
  console.log('\n📊 RESUMEN');
  console.log(`Total Órdenes: ${summary.totalOrders}`);
  
  // Desglose por tipo
  console.log('\n📈 POR TIPO');
  Object.entries(summary.byType).forEach(([type, count]) => {
    const pct = ((count / summary.totalOrders) * 100).toFixed(1);
    console.log(`  ${type.padEnd(20)} ${String(count).padStart(5)} (${pct}%)`);
  });
  
  // Desglose por estado
  console.log('\n📋 POR ESTADO');
  Object.entries(summary.byStatus).forEach(([status, count]) => {
    const pct = ((count / summary.totalOrders) * 100).toFixed(1);
    console.log(`  ${status.padEnd(20)} ${String(count).padStart(5)} (${pct}%)`);
  });
  
  // Calcular totales por tipo
  console.log('\n💰 VOLUMEN POR TIPO');
  const volumenPorTipo = {};
  todasLasOrdenes.forEach(order => {
    if (!volumenPorTipo[order.type]) {
      volumenPorTipo[order.type] = 0;
    }
    volumenPorTipo[order.type] += parseFloat(order.amountIn);
  });
  
  Object.entries(volumenPorTipo).forEach(([type, volume]) => {
    console.log(`  ${type.padEnd(20)} ${volume.toLocaleString()}`);
  });
  
  // Detalle de órdenes fallidas
  const ordenesFallidas = todasLasOrdenes.filter(o => o.status === 'FAILED');
  if (ordenesFallidas.length > 0) {
    console.log('\n⚠️ ÓRDENES FALLIDAS');
    ordenesFallidas.forEach(order => {
      console.log(`  ${order.orderId} | ${order.type} | ${order.amountIn} | ${order.createdAt}`);
    });
  }
  
  console.log('\n' + '='.repeat(60));
  
  return { orders: todasLasOrdenes, summary };
}
 
// Uso
const analisis = await generarAnalisisDeOrdenes(
  'org3_xxx',
  'mrc_xxx', 
  'acc_xxx',
  '2025-01-01',
  '2025-01-31',
  token
);

Próximos Pasos