Skip to Content
API ReferenceTransactionsIn-Person PaymentsBatch Close

Batch Close

Usage Flow

  1. Call the Batch Query API first to retrieve pending settlement batches. If no pending batches exist, no close operation is needed.
  2. A single terminal may connect to multiple Processors (each represented by a different channelCode). Call this API once for each channelCode returned in the Batch Query response.
  3. The channelCode value comes from the Batch Query response — always use it dynamically rather than using a fixed value.

Batch Report Printing

The optional printReceipt field defaults to AUTO. Supported values are AUTO, BOTH, TOTAL, DETAIL, and NONE. The transaction-receipt values MERCHANT and CUSTOMER are accepted for compatibility and treated as AUTO. AUTO uses the terminal’s current batch report setting; BOTH prints total and transaction detail reports.

Timeout Handling

If a Batch Close request times out due to a network issue, call the Batch Query API to verify the settlement result. The batch close was successful — and no retry is needed — if either of the following is true:

  • No pending settlement batch exists for that channelCode;
  • The batchNo of the pending batch returned by the query differs from the batchNo in your original close request (indicating the original batch has already been closed and a new batch has been opened).

ENDPOINT
POST
https://open.sunbay.us/v1/settlement/batch-close

The Batch Close API is used to close the current transaction batch and trigger the settlement process. After calling this API, the backend immediately initiates a batch close settlement request, and the API returns the batch close result. Once the batch is closed, it cannot be reversed, and transactions within the batch will enter the settlement process.

Parameters

Header parameters

NameTypeRequiredDescription
Authorization
stringYes
Bearer Token authentication, format: Bearer {your_api_key}
Example: "Bearer sk_test_4eC39HqLyjWDarjtT1zdp7dc"
Content-Type
stringYes
Request content type, fixed value: application/json
X-Client-Request-Id
string(64)Yes
Request unique identifier, used to prevent duplicate requests and issue tracking. UUID format is recommended, each request must use a unique Request ID
Example: "550e8400-e29b-41d4-a716-446655440000"
X-Timestamp
stringYes
Request timestamp, Unix timestamp (milliseconds), 13 digits. The deviation between the request timestamp and server time cannot exceed ±10 minutes
Pattern: ^[0-9]{13}$
Example: "1701234567890"

Body parameters

NameTypeRequiredDescription
appId
string(32)Yes
Application ID
Example: "app_123456"
merchantId
string(32)Yes
Merchant ID
Example: "mch_789012"
transactionRequestId
string(32)Yes
Transaction request ID. Client-generated unique identifier for API idempotency control. Must be unique per request.
Pattern: ^[A-Za-z0-9_\-]+$
Example: "BATCH_CLOSE_20231119001"
terminalSn
string(32)Yes
Payment terminal serial number. The payment terminal device serial number provided by SUNBAY, which is used for reading bank cards, processing PINs and other security operations
Example: "T1234567890"
channelCode
string(32)Yes
Payment channel code, see Payment Channel. Obtain this value from the Batch Query API response — always use it dynamically rather than using a fixed value. A single terminal may connect to multiple Processors (each represented by a different channelCode); call this API once per channelCode returned by Batch Query.
Example: "TSYS"
description
string(128)No
Batch close description
Example: "End of business day, close batch"
printReceipt
stringNo
Batch report print option. Controls what the terminal prints after batch close. Defaults to SUNBAY platform configuration if not provided
Possible values:
  • TOTAL- Print batch summary only
  • DETAIL- Print batch detail only (per-transaction breakdown)
  • BOTH- Print summary + detail
  • NONE- Do not print batch report
  • AUTO- Use SUNBAY platform configuration
Default: "AUTO"
Example: "AUTO"
attach
string(128)No
Additional data, returned as is, JSON format recommended
Example: "{\"closeTime\":\"2023-11-19T22:00:00+08:00\"}"

Request Example

{
  "appId": "app_123456",
  "merchantId": "mch_789012",
  "transactionRequestId": "BATCH_CLOSE_20231119001",
  "terminalSn": "T1234567890",
  "channelCode": "TSYS",
  "description": "End of business day, close batch",
  "printReceipt": "BOTH"
}

Code Examples

cURLbash

Response parameters

NameTypeRequiredDescription
code
string(16)Y
Response code, 0 indicates success
Example: "0"
msg
string(128)N
Response description
Example: "Batch close successful"
traceId
string(64)Y
Trace ID, used for troubleshooting
Example: "TRACE123456789"
data
objectY

Full Settlement Flow Example (Java)

The following pseudocode demonstrates the complete flow: query pending batches → close each one → handle timeout.

// 1. Query pending settlement batches BatchQueryResponse queryResponse = client.batchQuery(new BatchQueryRequest(appId, merchantId, terminalSn)); List<BatchInfo> pendingBatches = queryResponse.getPendingBatches(); if (pendingBatches == null || pendingBatches.isEmpty()) { // No pending batches — nothing to close return; } // 2. Close each batch by channelCode for (BatchInfo batch : pendingBatches) { String channelCode = batch.getChannelCode(); String batchNo = batch.getBatchNo(); try { BatchCloseResponse closeResponse = client.batchClose(new BatchCloseRequest( appId, merchantId, generateRequestId(), terminalSn, channelCode )); log.info("Batch closed successfully: channelCode={}, batchNo={}", channelCode, closeResponse.getBatchNo()); } catch (TimeoutException e) { // 3. Timeout: verify the result via Batch Query handleTimeout(client, appId, merchantId, terminalSn, channelCode, batchNo); } } /** * After a timeout, query to confirm whether the batch close has taken effect. */ private void handleTimeout(NexusClient client, String appId, String merchantId, String terminalSn, String channelCode, String originalBatchNo) { BatchQueryResponse retryQuery = client.batchQuery(new BatchQueryRequest(appId, merchantId, terminalSn)); // Check if a pending batch still exists for this channelCode Optional<BatchInfo> pending = retryQuery.getPendingBatches().stream() .filter(b -> channelCode.equals(b.getChannelCode())) .findFirst(); if (pending.isEmpty()) { // No pending batch for this channelCode → close was successful log.info("Batch close confirmed (no pending batch): channelCode={}", channelCode); return; } if (!originalBatchNo.equals(pending.get().getBatchNo())) { // Pending batchNo has changed → original batch was closed, current is a new batch log.info("Batch close confirmed (batchNo changed): channelCode={}, old={}, new={}", channelCode, originalBatchNo, pending.get().getBatchNo()); return; } // Same batchNo still pending → close did not take effect, retry log.warn("Batch close not confirmed, retrying: channelCode={}, batchNo={}", channelCode, originalBatchNo); // Retry batchClose ... }
Last updated on