Orders Report

Transaction-level order reporting

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

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

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

Filtering by Type

Retrieve only specific order types:

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

Filtering by Status

Retrieve orders with specific statuses:

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

Understanding the Response

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": "INV-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": "Supplier Co",
33 "identifier": "98765432-1"
34 },
35 "createdAt": "2025-01-20T14:00:00.000Z",
36 "completedAt": "2025-01-20T14:15:00.000Z",
37 "externalId": "PO-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}

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:

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// Volume analysis
12console.log('=== Monthly Volume ===');
13console.log(`Total Orders: ${summary.totalOrders}`);
14
15// By type
16console.log('\n=== By Type ===');
17Object.entries(summary.byType).forEach(([type, count]) => {
18 console.log(`${type}: ${count} orders`);
19});
20
21// By status
22console.log('\n=== By Status ===');
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// Success rate
29const completed = summary.byStatus.COMPLETED || 0;
30const failed = summary.byStatus.FAILED || 0;
31const successRate = (completed / (completed + failed) * 100).toFixed(1);
32console.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.

1// Get ledger statement
2const ledger = await getLedgerStatement(orgId, merchantId, accountId, from, to, token);
3
4// Get orders report
5const orders = await getOrdersReport(orgId, merchantId, accountId, from, to, token);
6
7// Cross-reference
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(`Movement ${movement.ledgerEntryId} matches Order ${order.orderId} (${order.type})`);
13 }
14 }
15});

Complete Integration Example

Node.js
1async function generateOrdersAnalysis(orgId, merchantId, accountId, from, to, token) {
2 // Fetch all orders (handling pagination)
3 const allOrders = [];
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 allOrders.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 // Generate analysis
28 console.log('='.repeat(60));
29 console.log('ORDERS ANALYSIS REPORT');
30 console.log(`Period: ${from} to ${to}`);
31 console.log('='.repeat(60));
32
33 // Summary statistics
34 console.log('\n📊 SUMMARY');
35 console.log(`Total Orders: ${summary.totalOrders}`);
36
37 // Type breakdown
38 console.log('\n📈 BY TYPE');
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 // Status breakdown
45 console.log('\n📋 BY STATUS');
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 // Calculate totals by type
52 console.log('\n💰 VOLUME BY TYPE');
53 const volumeByType = {};
54 allOrders.forEach(order => {
55 if (!volumeByType[order.type]) {
56 volumeByType[order.type] = 0;
57 }
58 volumeByType[order.type] += parseFloat(order.amountIn);
59 });
60
61 Object.entries(volumeByType).forEach(([type, volume]) => {
62 console.log(` ${type.padEnd(20)} ${volume.toLocaleString()}`);
63 });
64
65 // Failed orders detail
66 const failedOrders = allOrders.filter(o => o.status === 'FAILED');
67 if (failedOrders.length > 0) {
68 console.log('\n⚠️ FAILED ORDERS');
69 failedOrders.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: allOrders, summary };
77}
78
79// Usage
80const analysis = await generateOrdersAnalysis(
81 'org3_xxx',
82 'mrc_xxx',
83 'acc_xxx',
84 '2025-01-01',
85 '2025-01-31',
86 token
87);

Next Steps