Koywe
On this page

Orders Report

The Orders Report provides a transaction-level view of all orders associated with a virtual account, with powerful filtering and summary statistics.

What is the Orders Report?

While the Ledger Statement shows balance movements, the Orders Report shows the underlying orders/transactions that caused those movements.

Ledger StatementOrders Report
Balance-focusedTransaction-focused
Shows debits/creditsShows order details
Running balanceOrder status tracking
For reconciliationFor transaction analysis

Key Concepts

Order Types

TypeDescription
PAYINCustomer payment received
PAYOUTProvider payment sent
ONRAMPFiat converted to crypto
OFFRAMPCrypto converted to fiat
BALANCE_TRANSFERCurrency exchange between accounts
PAYMENT_LINKPayment via payment link

Order Statuses

StatusDescription
DRAFTOrder created but not submitted
PENDINGAwaiting payment or processing
PAIDPayment received, processing
PROCESSINGBeing processed
COMPLETEDSuccessfully completed
FAILEDFailed to complete
CANCELLEDCancelled by user or system
REFUNDEDPayment refunded
REFUND_REQUESTEDRefund in progress
EXPIREDOrder expired
ON_HOLDTemporarily held

API Endpoint

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

Path Parameters

ParameterRequiredDescription
organizationIdYesOrganization ID
merchantIdYesMerchant ID
accountIdYesVirtual account ID

Query Parameters

ParameterRequiredDefaultDescription
fromYes-Start date (YYYY-MM-DD)
toYes-End date (YYYY-MM-DD)
typeNo-Filter by order type
statusNo-Filter by order status
cursorNo-Pagination cursor
limitNo50Items per page (1-100)

Quick Example

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 Orders:', response.data.summary.totalOrders);
console.log('By Type:', response.data.summary.byType);
console.log('By Status:', response.data.summary.byStatus);

Filtering by Type

Retrieve only specific order types:

// Get only PAYIN orders
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('PAYIN orders:', payinOrders.data.orders.length);
 
// Get only PAYOUT orders
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('PAYOUT orders:', payoutOrders.data.orders.length);

Filtering by Status

Retrieve orders with specific statuses:

// Get completed orders only
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('Completed orders:', completedOrders.data.orders.length);
 
// Get failed orders for investigation
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('Failed orders to investigate:', failedOrders.data.orders.length);

Understanding the Response

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": "INV-2025-001"
    },
    {
      "orderId": "ord_def456",
      "type": "PAYOUT",
      "status": "COMPLETED",
      "amountIn": "500000.00",
      "amountOut": "500000.00",
      "originCurrency": "CLP",
      "destinationCurrency": "CLP",
      "counterparty": {
        "name": "Supplier Co",
        "identifier": "98765432-1"
      },
      "createdAt": "2025-01-20T14:00:00.000Z",
      "completedAt": "2025-01-20T14:15:00.000Z",
      "externalId": "PO-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"
}

Response Fields

FieldDescription
orders[]Array of order objects
orders[].orderIdUnique order ID
orders[].counterpartyContact/payer information
orders[].externalIdYour reference ID (if provided)
summary.totalOrdersTotal orders in period
summary.byTypeCount breakdown by order type
summary.byStatusCount breakdown by status

Understanding the Summary

The summary object provides aggregate statistics for quick analysis:

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;
 
// Volume analysis
console.log('=== Monthly Volume ===');
console.log(`Total Orders: ${summary.totalOrders}`);
 
// By type
console.log('\n=== By Type ===');
Object.entries(summary.byType).forEach(([type, count]) => {
  console.log(`${type}: ${count} orders`);
});
 
// By status
console.log('\n=== By Status ===');
Object.entries(summary.byStatus).forEach(([status, count]) => {
  const percentage = ((count / summary.totalOrders) * 100).toFixed(1);
  console.log(`${status}: ${count} (${percentage}%)`);
});
 
// Success rate
const completed = summary.byStatus.COMPLETED || 0;
const failed = summary.byStatus.FAILED || 0;
const successRate = (completed / (completed + failed) * 100).toFixed(1);
console.log(`\nSuccess Rate: ${successRate}%`);

Reconciliation Tip

Matching Orders to Ledger Entries: Each ledger movement includes an orderId field. Use this to cross-reference between the Orders Report and Ledger Statement.

JavaScript
// Get ledger statement
const ledger = await getLedgerStatement(orgId, merchantId, accountId, from, to, token);
 
// Get orders report
const orders = await getOrdersReport(orgId, merchantId, accountId, from, to, token);
 
// Cross-reference
ledger.movements.forEach(movement => {
  if (movement.orderId) {
    const order = orders.orders.find(o => o.orderId === movement.orderId);
    if (order) {
      console.log(`Movement ${movement.ledgerEntryId} matches Order ${order.orderId} (${order.type})`);
    }
  }
});

Complete Integration Example

JavaScript
async function generateOrdersAnalysis(orgId, merchantId, accountId, from, to, token) {
  // Fetch all orders (handling pagination)
  const allOrders = [];
  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}` }
      }
    );
    
    allOrders.push(...response.data.orders);
    summary = response.data.summary;
    cursor = response.data.pagination.hasMore ? response.data.pagination.cursor : null;
    
  } while (cursor);
  
  // Generate analysis
  console.log('='.repeat(60));
  console.log('ORDERS ANALYSIS REPORT');
  console.log(`Period: ${from} to ${to}`);
  console.log('='.repeat(60));
  
  // Summary statistics
  console.log('\nšŸ“Š SUMMARY');
  console.log(`Total Orders: ${summary.totalOrders}`);
  
  // Type breakdown
  console.log('\nšŸ“ˆ BY TYPE');
  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}%)`);
  });
  
  // Status breakdown
  console.log('\nšŸ“‹ BY STATUS');
  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}%)`);
  });
  
  // Calculate totals by type
  console.log('\nšŸ’° VOLUME BY TYPE');
  const volumeByType = {};
  allOrders.forEach(order => {
    if (!volumeByType[order.type]) {
      volumeByType[order.type] = 0;
    }
    volumeByType[order.type] += parseFloat(order.amountIn);
  });
  
  Object.entries(volumeByType).forEach(([type, volume]) => {
    console.log(`  ${type.padEnd(20)} ${volume.toLocaleString()}`);
  });
  
  // Failed orders detail
  const failedOrders = allOrders.filter(o => o.status === 'FAILED');
  if (failedOrders.length > 0) {
    console.log('\nāš ļø FAILED ORDERS');
    failedOrders.forEach(order => {
      console.log(`  ${order.orderId} | ${order.type} | ${order.amountIn} | ${order.createdAt}`);
    });
  }
  
  console.log('\n' + '='.repeat(60));
  
  return { orders: allOrders, summary };
}
 
// Usage
const analysis = await generateOrdersAnalysis(
  'org3_xxx',
  'mrc_xxx', 
  'acc_xxx',
  '2025-01-01',
  '2025-01-31',
  token
);

Next Steps