API Reference
Payment Open API
Payment pages, dynamic and static QR, transaction queries, and notifications.
1 Introduction
1.1 Overview
The DTC Payment OpenAPI, a JSON RESTful web service, is for third-party merchants to integrate DTC's payment processing (payment pages, dynamic/static QR codes, transaction queries) into their own systems.
This specification defines a set of interfaces and security standards.
1.2 Specification Titles
-
Name: The JSON field name in the request or response.
-
Type: The JSON type of the field.
- String, Integer, Long, Decimal (a JSON number, not a string — see the note below), Boolean, Object, Array.
-
Required:
- M — Mandatory. Validated by the server.
- C — Conditional. Mandatory only under the condition stated in the Description column.
- O — Optional.
-
Description: The meaning, allowed values, or format of the field.
NOTE (numeric fields): Every amount/fee/rate field in this document (
totalAmount,saleAmount,serviceFeeAmount,gstAmount,tipAmount,processingAmount,processingFee,exchangeRate,secondaryAmount, etc.) is a JSON number, both in requests and responses — e.g."totalAmount": 1.23, never"totalAmount": "1.23". All JSON samples in this document follow the number convention.
1.3 Security Standards
- HTTPS: TLS 1.2, mandatory for every connection.
- Whitelist: Optional IP whitelist, configurable on the
API Key Managementpage. - Signature: Request integrity checking (identity comes entirely from the signature + merchant/terminal headers below).
1.4 Request domain name
- Sbx test environment:
https://open-api.sbx.dtcpayment.net - Production environment:
https://open-api.dtcpay.com
2 Quick Start
2.1 Before Integration
- Request account registration on the DTC Wallet platform.
- Log in and go to the
API Key Managementpage. - Click
+ Create, choose Payments API (not Wallet / Card API — that's a separate credential for the Card/Wallet/eKYC Open APIs), and fill in the Name and IP Whitelist. - The
Sign Keyis generated and shown once — copy it before closing the dialog. Each merchant's terminal has its own unique sign key.
2.2 Request Signature
For every request, a signature is mandatory in the HTTP header.
-
Components of the string to sign:
HTTP Method— uppercase.Timestamp— Timestamp number in millis, Singapore timezone. The request will be failed if the timestamp is before or after 2 minutes.URL— the request path, no scheme/host.Querystring— in-URL parameters without the leading?, un-encoded.Request Body— the exact raw body string, empty if none. Must match byte-for-byte, including invisible characters.
-
Concatenate in order:
Method + Timestamp + URL + ('?' + Querystring if present) + Body.
GET1636360576641/payment/v1/sign-in
POST1636360661729/payment/v1/query-detail{"transactionId":"220817101245678"}-
Sign the string with HMAC-SHA512 using the
Sign Keyfrom Before Integration, then Base64-encode the result. -
Attach headers to the request:
D-MERCHANT-ID— assigned by DTC.D-TERMINAL-ID— assigned by DTC.D-TIMESTAMP— Timestamp number in millis, Singapore timezone. The request will be failed if the timestamp is before or after 2 minutes.D-SIGNATURE— the generated signature.
2.2.1 Example: GET Request (Java)
import com.google.common.hash.Hashing;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
public class SignatureTestGuava {
public static void main(String[] args) {
String signKey = "4mt0MUecOtOEDI42WjN4BmM0";
String method = "GET";
String uri = "/payment/v1/sign-in";
String query = "";
String body = "";
String timestamp = String.valueOf(System.currentTimeMillis());
String stringToSign = method + timestamp + uri;
if (!query.isEmpty()) {
stringToSign += "?" + query;
}
stringToSign += body;
String signature = Base64.getEncoder().encodeToString(
Hashing.hmacSha512(signKey.getBytes(StandardCharsets.UTF_8))
.hashBytes(stringToSign.getBytes(StandardCharsets.UTF_8))
.asBytes()
);
System.out.println("Timestamp : " + timestamp);
System.out.println("StringToSign: " + stringToSign);
System.out.println("Signature : " + signature);
}
}/payment/v1/sign-in is the only GET endpoint in this domain — every other endpoint below is POST.
2.2.2 Example: POST Request (Java)
import com.google.common.hash.Hashing;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
public class SignatureTestGuavaPOST {
public static void main(String[] args) {
String signKey = "4mt0MUecOtOEDI42WjN4BmM0";
String method = "POST";
String uri = "/payment/v1/query-detail";
String query = "";
String body = "{\"transactionId\":\"220817101245678\",\"referenceNo\":\"1821938217\"}";
String timestamp = String.valueOf(System.currentTimeMillis());
String stringToSign = method + timestamp + uri;
if (!query.isEmpty()) {
stringToSign += "?" + query;
}
stringToSign += body;
String signature = Base64.getEncoder().encodeToString(
Hashing.hmacSha512(signKey.getBytes(StandardCharsets.UTF_8))
.hashBytes(stringToSign.getBytes(StandardCharsets.UTF_8))
.asBytes()
);
System.out.println("Timestamp : " + timestamp); // Value for D-TIMESTAMP
System.out.println("StringToSign: " + stringToSign); // Raw string used for signing
System.out.println("Signature : " + signature); // Value for D-SIGNATURE
}
}2.3 HTTP Headers
Every request carries:
D-MERCHANT-ID: Assigned by DTC.D-TERMINAL-ID: Assigned by DTC.D-TIMESTAMP: Timestamp number in millis, Singapore timezone. The request will be failed if the timestamp is before or after 2 minutes.D-SIGNATURE: The generated signature string.
3 API
3.1 Message Structure
Every request body:
{
"query": {}
}Paginated requests additionally carry:
{
"query": {},
"page": {
"current": 1,
"size": 10
}
}Responses come in three shapes depending on the endpoint:
Single object
{
"header": {
"success": true,
"errCode": null,
"errMsg": null
},
"result": {}
}Plain list (no pagination — used by a small number of endpoints not covered in this document)
{
"header": {
"success": true
},
"resultList": []
}Paginated list
{
"header": {
"success": true
},
"resultList": [],
"pagination": {
"current": 1,
"size": 10,
"total": 100
}
}Failure:
{
"header": {
"success": false,
"errCode": "31005",
"errMsg": "Card Information is invalid"
}
}3.2 Sign In
Endpoint
[GET] /payment/v1/sign-in
Description
Optionally performs a one-time check of the merchant/terminal's payment configuration — confirms merchant/terminal settings are correctly registered in DTC, and lists the payment channels (brand/module/currency combinations) available to this terminal.
Response Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| merchantId | Long | M | The merchant ID generated by DTC system for merchant. |
| merchantInfo | Object | M | The merchant's information — see below. |
| terminalId | Long | M | The terminal ID generated by DTC system for merchant. Multiple terminal routes can be added to a terminal ID. |
| requestCurrency | String | M | The terminal's own accounting currency. |
| cryptoTravelRule | Boolean | O | Whether Travel Rule data collection applies to this terminal's crypto transactions. |
| channels | Array | M | The payment channels (brand + module + currency combinations) available to this terminal. |
merchantInfo Parameters
| Name | Type | Description |
|---|---|---|
| name | String | Merchant name. |
| country | String | Merchant country. |
| city | String | Merchant city. |
| state | String | Merchant state. |
| postalCode | String | Merchant postal code. |
| address | String | Merchant address line. |
Channel Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| brand | Integer | M | Payment brand for this channel. Refer to Enum List - Brand. |
| processingCurrency | String | M | Currency the payer pays in on this channel. |
| module | Integer | M | Payment module for this channel. Refer to Enum List - Module. |
Response Body Sample
{
"header": {
"success": true
},
"result": {
"merchantId": 8520110007,
"merchantInfo": {
"name": "Wise & New Life Pte Ltd. (Test)",
"country": "SGP",
"city": "Singapore",
"state": "Central Singapore",
"postalCode": "018936",
"address": "7 Straits View, Marina One East Tower"
},
"terminalId": 2011100008,
"requestCurrency": "SGD",
"cryptoTravelRule": true,
"channels": [
{
"brand": 201,
"processingCurrency": "USDC",
"module": 1002
},
{
"brand": 101,
"processingCurrency": "SGD",
"module": 5
}
]
}
}Possible Error Codes
| Code | Description | When it happens |
|---|---|---|
| 500 | Server Error | Unexpected exception (e.g. downstream call to payment-api failed) — this proxy's own catch converts it into the standard {header:{success,errCode,errMsg}} shape |
3.3 Payment Page
Endpoint
[POST] /payment/v1/payment-page
Description
Creates a hosted payment page for a customer transaction. After the merchant submits transaction details (amounts, reference number, optional billing/shipping info, redirect URL), the API returns a payment page URL the customer visits to complete payment.
Top-level Request Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| transaction | Object | M | Transaction details, see below. |
| redirectUrl | String | C | URL DTC redirects the customer to once a final result has been received from bank/acquirer. |
Transaction Request Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| totalAmount | Decimal | M | The merchant's receive amount; settled by DTC after deducting the fee (corresponds to the terminal's request currency). Must be > 0. |
| saleAmount | Decimal | C | The original price of goods or services. |
| serviceFeeAmount | Decimal | C | Service fee amount (if provided, saleAmount must also be filled). |
| gstAmount | Decimal | C | Goods and Services Tax amount (if provided, saleAmount must also be filled). |
| tipAmount | Decimal | C | The voluntary tip given by the customer (if provided, saleAmount must also be filled). |
| referenceNo | String | M | Unique string to locate a transaction. |
| billingInfo | PersonalInfo | C | Billing info. |
| shippingInfo | PersonalInfo | C | Shipping info. |
| notificationUrl | String | C | Webhook URL for transaction state update notifications — see Notification. |
PersonalInfo Parameters
| Name | Type | Required |
|---|---|---|
| firstName | String | M |
| lastName | String | M |
| String | M | |
| phone | String | C |
| country | String | M |
| state | String | C |
| city | String | C |
| postcode | String | M |
| address | String | M |
| address2 | String | O |
Request Body Sample (formatted)
{
"query": {
"transaction": {
"totalAmount": 1.23,
"referenceNo": "1821938217",
"notificationUrl": "https://api.dev.dtcpayment.net",
"billingInfo": {
"firstName": "AAA",
"lastName": "BBB",
"email": "billing@xxx.yyy",
"phone": "12345678",
"country": "Singapore",
"state": "Singapore",
"city": "Singapore",
"postcode": "123456",
"address": "Billing Line 1",
"address2": "Billing Line 2"
},
"shippingInfo": {
"firstName": "CCC",
"lastName": "DDD",
"email": "shipping@xxx.yyy",
"phone": "12345678",
"country": "Singapore",
"state": "Singapore",
"city": "Singapore",
"postcode": "654321",
"address": "Shipping Line 1",
"address2": "Shipping Line 2"
}
},
"redirectUrl": "https://api.dev.dtcpayment.net"
}
}Response Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| pageUrl | String | M | URL of the generated payment page where the merchant should redirect the customer. |
| timeout | Long | M | Unix epoch timestamp, in seconds (not milliseconds), of when this payment page expires — an absolute point in time, not a countdown duration. Computed as DateTimeUtils.toSeconds(deadline) from a Singapore-timezone LocalDateTime deadline. |
Response Body Sample
{
"header": {
"success": true
},
"result": {
"pageUrl": "https://api.dev.dtcpayment.net/api/v1/payment-page/F6yAivXiKdQ8x0KGosbkjhGhVyxCA6di",
"timeout": 1604756861
}
}Possible Error Codes
| Code | Description | When it happens |
|---|---|---|
| 400 | Bad Request / Invalid parameters | totalAmount <= 0 |
| 500 | Server Error | Unexpected exception (see the envelope note under Sign In) |
3.4 Generate Merchant QR
Endpoint
[POST] /payment/v1/generate-merchant-qr
Description
Creates a dynamic QR code for a one-time merchant payment. The merchant submits amount, reference number, brand/module/currency, and optional customer info; the API returns the created transaction (see PaymentTransactionResp) including the qr content the customer scans to pay.
This endpoint currently supports four brands:
WECHAT_PAY(101),PAY_NOW(104),BINANCE_PAY(106), andCRYPTO_HOSTED(201). Any other brand — includingCRYPTO_UNHOSTED(200) — is rejected withInvalid acquirer.
用 crypto currency 支付(stg 测试环境):目前测试环境的
CRYPTO_HOSTED仅支持以太坊(测试网)+ USDC 币种。可以通过 https://faucet.circle.com/ 领取测试 USDC 后,用自己的钱包(如 MetaMask)向本接口返回的 QR 收款地址转账完成付款;也可以直接用自己已有的测试网钱包向目标地址转账,效果相同。
Top-level Request Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| transaction | Object | M | Transaction details, see below. |
Transaction Request Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| brand | Integer | M | Payment brand. Only 101 (WECHAT_PAY), 104 (PAY_NOW), 106 (BINANCE_PAY), 201 (CRYPTO_HOSTED) are currently supported — see note above. |
| module | Integer | M | Payment module, must match brand's module (WECHAT_PAY→5, PAY_NOW→6, BINANCE_PAY→11; CRYPTO_HOSTED→ whichever chain module the terminal's acquirer route is configured with, e.g. 1002 Ethereum, 1003 Tron, 1007 BSC). |
| processingCurrency | String | M | Currency actually paid by the end customer (payer) — e.g. the stablecoin the customer pays with for a Binance Pay transaction. Distinct from the merchant's own accounting currency. |
| totalAmount | Decimal | M | The merchant's receive amount; settled by DTC after deducting the fee (corresponds to the terminal's request currency). |
| referenceNo | String | M | Unique transaction reference number. |
| notificationUrl | String | C | Webhook URL for payment status updates. |
| billingInfo | PersonalInfo | C | Customer billing information. |
| shippingInfo | PersonalInfo | C | Customer shipping information. |
PersonalInfo Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| firstName | String | M | |
| lastName | String | M | |
| String | M | ||
| phone | String | C | |
| country | String | M | |
| state | String | C | |
| city | String | C | |
| postcode | String | M | |
| address | String | M | |
| address2 | String | O | |
| binanceId | String | O | Binance UID. Optional even when brand=106 (BINANCE_PAY) — verified from BinancePayVerifyService.verifyPayerIfRequired, which is a no-op whenever binanceId is blank, regardless of brand. Providing it opts the transaction into Binance's payer-verification check (requires payerType); omitting it, including on a Binance Pay transaction, simply skips that check — it is never rejected as missing. |
| payerType | String | C | Required when binanceId is set. INDIVIDUAL needs firstName/lastName (already required above); CORPORATE needs companyName/registrationNumber/registrationCountry. |
| companyName | String | C | Required when payerType is CORPORATE. |
| registrationNumber | String | C | Required when payerType is CORPORATE. |
| registrationCountry | String | C | ISO 3166-1 alpha-3 (e.g. SGP). Required when payerType is CORPORATE. |
Request Body Sample (formatted)
{
"query": {
"transaction": {
"brand": 106,
"module": 11,
"processingCurrency": "USDT",
"totalAmount": 1,
"referenceNo": "1821938217",
"billingInfo": {
"firstName": "AAA",
"lastName": "BBB",
"email": "billing@xxx.yyy",
"phone": "12345678",
"country": "Singapore",
"state": "Singapore",
"city": "Singapore",
"postcode": "123456",
"address": "Billing Line 1",
"address2": "Billing Line 2",
"binanceId": "test1231",
"payerType": "INDIVIDUAL"
},
"notificationUrl": "https://api.dev.dtcpayment.net"
}
}
}Response Body Sample
{
"header": {
"success": true
},
"result": {
"id": 220906161400163,
"brand": 106,
"module": 11,
"type": 71001,
"state": 0,
"settlementStatus": 0,
"merchantId": 8520110007,
"merchantName": "Wise & New Life Pte Ltd. (Test)",
"terminalId": 2011100008,
"requestCurrency": "SGD",
"totalAmount": 1,
"saleAmount": 1,
"serviceAmount": 0,
"serviceRate": 0,
"gstAmount": 0,
"gstRate": 0,
"tipAmount": 0,
"processingCurrency": "USDT",
"processingAmount": 0.76086,
"processingFee": 0,
"referenceNo": "1821938217",
"qr": "0x4AA25e9F824D3abd26BDa38a96D34efC53f36992",
"createdAt": "2026-09-06 16:13:59",
"updatedAt": "2026-09-06 16:14:00"
}
}Response object fields are documented once, in Appendix A: Data Structure — see the note there on why generate-merchant-qr/query-detail/query-history all return the same object shape.
Possible Error Codes
| Code | Description | When it happens |
|---|---|---|
| 400 | Invalid parameters | binanceId present but payerType is neither INDIVIDUAL nor CORPORATE, or payerType=CORPORATE but companyName/registrationNumber/registrationCountry is missing |
| 400 | Invalid acquirer | No enabled acquirer route matches this terminal/module/brand/currency combination (e.g. an unsupported brand — see the brand-support note above) |
| 400 | Payer verification failed: | binanceId provided but Binance's payer-verification call failed or returned unverified (e.g. 400601 account does not exist, 400722 KYC not completed, 406108 rate limited) |
| 500 | Server Error | Unexpected exception (see the envelope note under Sign In) |
3.5 Query Transaction Detail
Endpoint
[POST] /payment/v1/query-detail
Description
Retrieves the full details of a specific transaction, by either transactionId or referenceNo (at least one required). Returns the same object shape as Generate Merchant QR — see Appendix A.
Request Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| transactionId | String | C | The DTC generated unique transaction-id. |
| referenceNo | String | C | Unique string to locate a transaction. transactionId/referenceNo are optional for each other — provide at least one. |
Request Body Sample (formatted)
{
"query": {
"transactionId": "220817101245678",
"referenceNo": "1821938217"
}
}Response Body Sample
{
"header": {
"success": true
},
"result": {
"id": 220920212411275,
"brand": 201,
"module": 1002,
"type": 200,
"state": 200,
"settlementStatus": 0,
"merchantId": 8520110007,
"merchantName": "Wise & New Life Pte Ltd. (Test)",
"terminalId": 2011100008,
"acqTid": "0x214774e237FA1fD6895631AeBF5fc6332bb2A976",
"requestCurrency": "SGD",
"totalAmount": 1.0,
"saleAmount": 1.0,
"serviceRate": 0,
"serviceAmount": 0,
"gstRate": 0,
"gstAmount": 0,
"tipAmount": 0,
"processingCurrency": "USDT",
"processingAmount": 0.76086,
"processingFee": 0,
"exchangeRate": 1.24284,
"receiptNumber": "0x323361d9c272979304518f42a9e0833f87367d23e3d858edaa8fe3628a616c98",
"referenceNo": "1663678847502",
"cardHolderName": "11 22",
"secondaryAmount": 0.76086,
"createdAt": "2026-09-20 21:24:11",
"updatedAt": "2026-09-20 22:21:51"
}
}Possible Error Codes
| Code | Description | When it happens |
|---|---|---|
| 400 | Invalid request | Neither transactionId nor referenceNo resolves to a transaction |
| 500 | Server Error | Unexpected exception (see the envelope note under Sign In) |
3.6 Query Transaction History
Endpoint
[POST] /payment/v1/query-history
Description
Retrieves a paginated list of past transactions, optionally filtered by QR ID, QR content, and/or brand. Each record is the same object shape as Generate Merchant QR/Query Transaction Detail — see Appendix A.
Request Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| qrId | Long | O | DTC generated unique QR ID. |
| qr | String | O | QR content the payer scans. |
| brand | Integer | O | Payment brand filter. Refer to Enum List - Brand. |
| pageSize | Integer | M | Number of records per page. |
| pageNo | Integer | M | Page number to retrieve (starting from 1). |
Request Body Sample (formatted)
{
"query": {
"brand": 201,
"qrId": 4231,
"qr": "0x214774e237FA1fD6895631AeBF5fc6332bb2A976",
"pageSize": 30,
"pageNo": 1
}
}Response Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| pagination | Object | M | Paginated wrapper — see below. |
| resultList | Array | M | Transaction records — same object as Generate Merchant QR/Query Transaction Detail, see Appendix A. |
pagination Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| current | Integer | M | Current page number. |
| size | Integer | M | Page size. |
| total | Long | M | Total record count. |
Response Body Sample
{
"header": {
"success": true
},
"pagination": {
"current": 1,
"size": 30,
"total": 2
},
"resultList": [
{
"id": 220920212411275,
"brand": 201,
"type": 200,
"state": 200,
"settlementStatus": 0,
"merchantId": 8520110007,
"merchantName": "Wise & New Life Pte Ltd. (Test)",
"terminalId": 2011100008,
"acqTid": "0x214774e237FA1fD6895631AeBF5fc6332bb2A976",
"requestCurrency": "SGD",
"totalAmount": 1.0,
"saleAmount": 1.0,
"serviceRate": 0,
"serviceAmount": 0,
"gstRate": 0,
"gstAmount": 0,
"tipAmount": 0,
"processingCurrency": "USDT",
"processingAmount": 0.76086,
"processingFee": 0,
"receiptNumber": "0x323361d9c272979304518f42a9e0833f87367d23e3d858edaa8fe3628a616c98",
"referenceNo": "1663678847502",
"cardHolderName": "11 22",
"createdAt": "2026-09-20 21:24:11",
"secondaryAmount": 0.76086,
"updatedAt": "2026-09-20 22:21:51"
},
{
"id": 2506241145190106694,
"brand": 201,
"module": 1002,
"type": 71001,
"state": 200,
"settlementStatus": 3,
"merchantId": 8524010424,
"merchantName": "Mary Lopez",
"terminalId": 25061900067,
"acqTid": "0x38c09CaacBb6eb8b76003B88CD38fC294cbd56D7",
"requestCurrency": "SGD",
"totalAmount": 1,
"saleAmount": 1,
"exchangeRate": 1.24284,
"processingCurrency": "USDC",
"processingAmount": 0.81,
"processingFee": 0,
"receiptNumber": "0xfb2edef6b6088840b756cb234925508b2fc2bfafc6c76635d1b88eb7fd14b1d9",
"referenceNo": "1750736702181",
"truncatedPan": "0xC900521959fF10BFAD5e900a776A1EbAcf3822F6",
"expiresAt": "2026-06-24 11:50:18",
"createdAt": "2026-06-24 11:45:18",
"secondaryAmount": 0.81,
"updatedAt": "2026-06-24 12:55:25",
"additionalData": {
"account": "0",
"txn_ids": "0xfb2edef6b6088840b756cb234925508b2fc2bfafc6c76635d1b88eb7fd14b1d9",
"address_id": "2841",
"institution": "SAFEHERON"
}
}
]
}Possible Error Codes
| Code | Description | When it happens |
|---|---|---|
| 400 | Invalid parameters | pageSize/pageNo missing |
| 500 | Server Error | Unexpected exception (see the envelope note under Sign In) |
3.7 Generate Static QR
Endpoint
[POST] /payment/v1/generate-static-qr
Description
Creates a reusable static QR code for a merchant, identified by referenceNo/brand/module. A static QR can be scanned for multiple payments (unlike the one-time dynamic QR from Generate Merchant QR).
This endpoint currently only supports one brand:
CRYPTO_HOSTED(201). Any other brand is rejected with"Unsupported brand: <brand>".
stg 测试环境的付款方式同 Generate Merchant QR 一节的说明:仅支持以太坊测试网 + USDC,可用 https://faucet.circle.com/ 领取测试币或自己的钱包向目标地址转账。
Request Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| referenceNo | String | M | Unique identifier for the static QR. |
| brand | Integer | M | Payment brand. Only 201 (CRYPTO_HOSTED) is currently supported — see note above. |
| module | Integer | M | Payment module — for the supported CRYPTO_HOSTED brand, selects the chain (e.g. 1002=Ethereum, 1003=Tron, 1007=BSC). |
Request Body Sample (formatted)
{
"query": {
"referenceNo": "220817101245678",
"brand": 201,
"module": 1002
}
}Response Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| qrId | Long | M | Unique static QR ID generated by DTC. |
| qr | String | M | The QR content scanned by customers. |
| qrStatus | Integer | M | Static QR status. Refer to Enum List - StaticQrStatus. |
| brand | Integer | M | Payment brand. Refer to Enum List - Brand. |
| module | Integer | M | Payment module. Refer to Enum List - Module. |
| referenceNo | String | M | Unique string to locate the static QR. |
| currencies | Array | M | Currencies customers can use to pay this static QR. Refer to Enum List - Currency. |
| createdAt | String | M | Creation timestamp, yyyy-MM-dd HH:mm:ss. |
| updatedAt | String | M | Last-updated timestamp, yyyy-MM-dd HH:mm:ss. |
Response Body Sample
{
"header": {
"success": true
},
"result": {
"qrId": 3214,
"qrStatus": 1,
"brand": 201,
"module": 1002,
"currencies": [
"USDT",
"USDC"
],
"qr": "0x4AA25e9F824D3abd26BDa38a96D34efC53f36992",
"referenceNo": "220817101245678",
"createdAt": "2026-09-06 16:13:59",
"updatedAt": "2026-09-06 16:13:59"
}
}Possible Error Codes
| Code | Description | When it happens |
|---|---|---|
| 400 | Unsupported brand: | brand is anything other than 201 (CRYPTO_HOSTED) |
| 500 | Server Error | Unexpected exception (see the envelope note under Sign In) |
3.8 Query Static QR
Endpoint
[POST] /payment/v1/query-static-qr
Description
Retrieves details of an existing static QR by qrId, qr, or referenceNo (at least one required). Same response shape as Generate Static QR.
Request Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| qrId | Long | C | Unique static QR ID. |
| qr | String | C | QR content. |
| referenceNo | String | C | Static QR reference number. |
At least one of
qrId/qr/referenceNomust be provided.
Request Body Sample (formatted)
{
"query": {
"referenceNo": "220817101245678",
"qrId": 3214,
"qr": "0x4AA25e9F824D3abd26BDa38a96D34efC53f36992"
}
}Response Body Sample — same shape as Generate Static QR:
{
"header": {
"success": true
},
"result": {
"qrId": 3214,
"qrStatus": 1,
"brand": 201,
"module": 1002,
"currencies": [
"USDT",
"USDC"
],
"qr": "0x4AA25e9F824D3abd26BDa38a96D34efC53f36992",
"referenceNo": "220817101245678",
"createdAt": "2026-09-06 16:13:59",
"updatedAt": "2026-09-06 16:13:59"
}
}Possible Error Codes
| Code | Description | When it happens |
|---|---|---|
| 400 | Invalid request | None of qrId/qr/referenceNo resolves to a static QR |
| 500 | Server Error | Unexpected exception (see the envelope note under Sign In) |
4 Notification
Using the transactionId, terminalId, and merchantId inside the GET parameters of the notification, callers can further query and verify trading results. Key points:
- It is a GET request toward
notify_url(thenotificationUrlgiven in the originating request). - A webhook fires whenever a transaction's status or amount changes. On receipt, callers are recommended to call Query Transaction Detail to verify the latest transaction details rather than trusting the GET params alone.
- The result is in GET-formatted query params:
notify_url?transactionId=220819125034757&merchantId=8520120002&terminalId=2205250071&referenceNo=220819125034757&state=200| Key | Type | Description |
|---|---|---|
| transactionId | Long | Unique DTC generated transaction ID. |
| terminalId | Long | DTC terminal ID assigned to the merchant. |
| merchantId | Long | Unique merchant ID generated by DTC for the merchant. |
| referenceNo | String | Unique string to locate a transaction. |
| state | Integer | Payment transaction state. Refer to Enum List - PaymentTransactionState. |
5 Appendix A: Data Structure
PaymentTransactionResp — the single shared object returned by Generate Merchant QR, Query Transaction Detail, and each item of Query Transaction History's resultList.
Previously these three endpoints each defined their own separate response class with a silently drifting field set (e.g. query-history's records were missing qrId; generate-merchant-qr's response was missing acqTid/receiptNumber/truncatedPan/expiresAt). They are now the same object — some fields are naturally null depending on the transaction's stage (e.g. acqTid/receiptNumber are null until an acquirer route has processed the transaction; qrId/qr are only present for QR-based brands; truncatedPan/cardHolderName only for credit-card-brand transactions).
| Name | Type | Required | Description |
|---|---|---|---|
| id | Long | M | The DTC generated unique transaction-id. |
| brand | Integer | M | Payment brand. Refer to Enum List - Brand. |
| module | Integer | O | Payment module. Refer to Enum List - Module. |
| type | Integer | M | Transaction type. Refer to Enum List - PaymentTransactionType. |
| state | Integer | M | Payment transaction state. Refer to Enum List - PaymentTransactionState. |
| settlementStatus | Integer | M | Settlement status. Refer to Enum List - SettlementStatus. |
| merchantId | Long | M | The merchant ID generated by DTC system for merchant. |
| merchantName | String | M | The merchant's own name. |
| terminalId | Long | M | The terminal ID generated by DTC system for merchant. |
| acqTid | String | O | The acqTid generated by DTC system for merchant. Null until an acquirer route has processed the transaction. |
| requestCurrency | String | M | Currency of the merchant transaction (the merchant's own accounting currency). |
| totalAmount | Decimal | M | Total amount of payer transactions (saleAmount+serviceAmount+gstAmount+tipAmount = totalAmount). The merchant's receive amount, settled by DTC after deducting the fee (corresponds to the terminal's request currency). |
| saleAmount | Decimal | O | Price of goods. |
| serviceAmount | Decimal | O | Service fee amount. |
| serviceRate | Decimal | O | Service fee exchange rate. |
| gstAmount | Decimal | O | GST amount. |
| gstRate | Decimal | O | GST rate. |
| tipAmount | Decimal | O | Tips included in the transaction. |
| processingCurrency | String | M | Currency actually paid by the end customer (payer) — the settlement-facing leg of the transaction, distinct from requestCurrency. |
| processingAmount | Decimal | M | Amount actually paid by the end customer (payer) in processingCurrency — the FX-converted counterpart of totalAmount that the payer sees and pays. |
| processingFee | Decimal | O | Processing fee. |
| exchangeRate | Decimal | O | Exchange rate between requestCurrency and processingCurrency. |
| receiptNumber | String | O | Receipt number. Null until the transaction has a settled receipt. |
| referenceNo | String | M | Unique string to locate a transaction. |
| truncatedPan | String | O | Only present for credit-card-brand transactions. |
| cardHolderName | String | O | Card holder name, only present for credit-card-brand transactions. |
| secondaryAmount | Decimal | O | Secondary amount. |
| qrId | Long | O | The DTC generated unique qr-id. Only present for QR-based brands. |
| qr | String | O | The payer scans this to initiate payment. Only present for QR-based brands. |
| createdAt | String | M | The date-time when the request is received or created, yyyy-MM-dd HH:mm:ss. |
| updatedAt | String | M | The datetime when the response was last updated, yyyy-MM-dd HH:mm:ss. |
| expiresAt | String | O | Transaction expiry time, yyyy-MM-dd HH:mm:ss. Only present for brands/modules with a payment-page/QR timeout. |
| additionalData | Object | O | Additional channel-specific transaction data (free-form key/value map). |
| amountDetails | Array | O | Amount breakdown details: each entry has serviceFeeAmount, gstAmount, tipAmount, rate, currency. |
6 Appendix B: Enum List
Brand
| Name | ID | Descriptor |
|---|---|---|
| UNDEFINED | 0 | Undefined |
| VISA | 1 | Visa |
| MASTERCARD | 2 | MasterCard |
| AMEX | 3 | American Express |
| JCB | 4 | JCB |
| DINERS | 5 | Diners Club |
| DISCOVER | 6 | Discover |
| CUP | 7 | China UnionPay |
| WECHATPAY | 101 | WeChat Pay |
| ALIPAY | 102 | Alipay |
| GRABPAY | 103 | GrabPay |
| PAYNOW | 104 | PayNow |
| QUICKPASS | 105 | QuickPass |
| BINANCE_PAY | 106 | Binance Pay |
| CRYPTO_HOSTED | 201 | Crypto Hosted |
Module
| Name | ID | Descriptor |
|---|---|---|
| 5 | ||
| CIMB | 6 | CIMB (PayNow) |
| WORLDPAY | 8 | Worldpay |
| GOOGLE_PAY | 9 | Google Pay |
| SAMSUNG_PAY | 10 | Samsung Pay |
| BINANCE_PAY | 11 | Binance Pay |
| ETHEREUM | 1002 | Ethereum |
| TRON | 1003 | Tron |
| BSC | 1007 | BNB Smart Chain |
| BASE | 1008 | Base |
| SOLANA | 1009 | Solana |
| ARBITRUM | 1010 | Arbitrum |
| DTCPAY | 5001 | dtcpay |
Currency
| Name | ID | Category | Code | Descriptor |
|---|---|---|---|---|
| AUD | 1 | 0 | 036 | Australian dollar |
| CNY | 2 | 0 | 156 | Chinese yuan |
| EUR | 3 | 0 | 978 | Euro |
| HKD | 4 | 0 | 344 | Hong Kong dollar |
| JPY | 5 | 0 | 392 | Japanese yen |
| SGD | 6 | 0 | 702 | Singapore dollar |
| USD | 7 | 0 | 840 | United States dollar |
| USDT | 8 | 1 | null | USD Tether |
| BTC | 9 | 1 | null | Bitcoin |
| ETH | 10 | 1 | null | Ethereum |
| TRX | 11 | 1 | null | Tron |
| GBP | 12 | 0 | 826 | Pound sterling |
| WUSD | 13 | 1 | null | Worldwide USD |
| USDC | 14 | 1 | null | USD Coin |
CurrencyCategory
| Name | ID | Descriptor |
|---|---|---|
| FIAT | 0 | Fiat Currency |
| CRYPTO | 1 | Crypto Currency |
| E_MONEY | 2 | e-Money Currency |
SettlementStatus
| Name | ID | Descriptor |
|---|---|---|
| PENDING | 0 | Pending |
| ACQ_SETTLED | 1 | Acquirer Settled |
| APPROVED | 2 | Settlement Approved |
| PAID | 3 | Settlement Paid |
| SUBMITTED | 6 | Settlement Submitted |
| REJECTED | 8 | Settlement Rejected |
PaymentTransactionState
| Name | ID | Descriptor |
|---|---|---|
| PENDING | 0 | Pending |
| AUTHORIZED | 101 | Authorized |
| PARTIAL_PAYMENT | 103 | Partial Payment |
| SUCCESS | 200 | Success |
| CAPTURED | 221 | Captured |
| REVERSED | 301 | Reversed |
| CANCELLED | 302 | Cancelled |
| REFUNDED | 401 | Refunded |
| DENIED | 900 | Denied |
| EXPIRED | 990 | Expired |
PaymentTransactionType
| Name | ID | Descriptor |
|---|---|---|
| TOKENIZE | 0 | Tokenize |
| AUTHORIZATION | 100 | Authorization |
| SALE | 200 | Sale |
| CAPTURE | 220 | Capture |
| VOID | 300 | Void |
| REFUNDED | 400 | Refund (refund open API is not currently available; operated via the DTC business portal) |
| MERCHANT_DYNAMIC_QR | 71001 | Merchant Dynamic QR |
| CONSUMER_QR | 72001 | Consumer QR |
| STATIC_QR | 72002 | Static QR |
StaticQrStatus
| Name | ID | Descriptor |
|---|---|---|
| DISABLED | 1 | Disabled |
| ENABLED | 2 | Enabled |