Developers

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 Management page.
  • 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

  1. Request account registration on the DTC Wallet platform.
  2. Log in and go to the API Key Management page.
  3. 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.
  4. The Sign Key is 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.

  1. 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.
  2. Concatenate in order: Method + Timestamp + URL + ('?' + Querystring if present) + Body.

GET1636360576641/payment/v1/sign-in
POST1636360661729/payment/v1/query-detail{"transactionId":"220817101245678"}
  1. Sign the string with HMAC-SHA512 using the Sign Key from Before Integration, then Base64-encode the result.

  2. 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

NameTypeRequiredDescription
merchantIdLongMThe merchant ID generated by DTC system for merchant.
merchantInfoObjectMThe merchant's information — see below.
terminalIdLongMThe terminal ID generated by DTC system for merchant. Multiple terminal routes can be added to a terminal ID.
requestCurrencyStringMThe terminal's own accounting currency.
cryptoTravelRuleBooleanOWhether Travel Rule data collection applies to this terminal's crypto transactions.
channelsArrayMThe payment channels (brand + module + currency combinations) available to this terminal.

merchantInfo Parameters

NameTypeDescription
nameStringMerchant name.
countryStringMerchant country.
cityStringMerchant city.
stateStringMerchant state.
postalCodeStringMerchant postal code.
addressStringMerchant address line.

Channel Parameters

NameTypeRequiredDescription
brandIntegerMPayment brand for this channel. Refer to Enum List - Brand.
processingCurrencyStringMCurrency the payer pays in on this channel.
moduleIntegerMPayment 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

CodeDescriptionWhen it happens
500Server ErrorUnexpected 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

NameTypeRequiredDescription
transactionObjectMTransaction details, see below.
redirectUrlStringCURL DTC redirects the customer to once a final result has been received from bank/acquirer.

Transaction Request Parameters

NameTypeRequiredDescription
totalAmountDecimalMThe merchant's receive amount; settled by DTC after deducting the fee (corresponds to the terminal's request currency). Must be > 0.
saleAmountDecimalCThe original price of goods or services.
serviceFeeAmountDecimalCService fee amount (if provided, saleAmount must also be filled).
gstAmountDecimalCGoods and Services Tax amount (if provided, saleAmount must also be filled).
tipAmountDecimalCThe voluntary tip given by the customer (if provided, saleAmount must also be filled).
referenceNoStringMUnique string to locate a transaction.
billingInfoPersonalInfoCBilling info.
shippingInfoPersonalInfoCShipping info.
notificationUrlStringCWebhook URL for transaction state update notifications — see Notification.

PersonalInfo Parameters

NameTypeRequired
firstNameStringM
lastNameStringM
emailStringM
phoneStringC
countryStringM
stateStringC
cityStringC
postcodeStringM
addressStringM
address2StringO

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

NameTypeRequiredDescription
pageUrlStringMURL of the generated payment page where the merchant should redirect the customer.
timeoutLongMUnix 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

CodeDescriptionWhen it happens
400Bad Request / Invalid parameterstotalAmount <= 0
500Server ErrorUnexpected 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), and CRYPTO_HOSTED (201). Any other brand — including CRYPTO_UNHOSTED (200) — is rejected with Invalid acquirer.

用 crypto currency 支付(stg 测试环境):目前测试环境的 CRYPTO_HOSTED 仅支持以太坊(测试网)+ USDC 币种。可以通过 https://faucet.circle.com/ 领取测试 USDC 后,用自己的钱包(如 MetaMask)向本接口返回的 QR 收款地址转账完成付款;也可以直接用自己已有的测试网钱包向目标地址转账,效果相同。

Top-level Request Parameters

NameTypeRequiredDescription
transactionObjectMTransaction details, see below.

Transaction Request Parameters

NameTypeRequiredDescription
brandIntegerMPayment brand. Only 101 (WECHAT_PAY), 104 (PAY_NOW), 106 (BINANCE_PAY), 201 (CRYPTO_HOSTED) are currently supported — see note above.
moduleIntegerMPayment 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).
processingCurrencyStringMCurrency 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.
totalAmountDecimalMThe merchant's receive amount; settled by DTC after deducting the fee (corresponds to the terminal's request currency).
referenceNoStringMUnique transaction reference number.
notificationUrlStringCWebhook URL for payment status updates.
billingInfoPersonalInfoCCustomer billing information.
shippingInfoPersonalInfoCCustomer shipping information.

PersonalInfo Parameters

NameTypeRequiredDescription
firstNameStringM
lastNameStringM
emailStringM
phoneStringC
countryStringM
stateStringC
cityStringC
postcodeStringM
addressStringM
address2StringO
binanceIdStringOBinance 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.
payerTypeStringCRequired when binanceId is set. INDIVIDUAL needs firstName/lastName (already required above); CORPORATE needs companyName/registrationNumber/registrationCountry.
companyNameStringCRequired when payerType is CORPORATE.
registrationNumberStringCRequired when payerType is CORPORATE.
registrationCountryStringCISO 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

CodeDescriptionWhen it happens
400Invalid parametersbinanceId present but payerType is neither INDIVIDUAL nor CORPORATE, or payerType=CORPORATE but companyName/registrationNumber/registrationCountry is missing
400Invalid acquirerNo enabled acquirer route matches this terminal/module/brand/currency combination (e.g. an unsupported brand — see the brand-support note above)
400Payer 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)
500Server ErrorUnexpected 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

NameTypeRequiredDescription
transactionIdStringCThe DTC generated unique transaction-id.
referenceNoStringCUnique 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

CodeDescriptionWhen it happens
400Invalid requestNeither transactionId nor referenceNo resolves to a transaction
500Server ErrorUnexpected 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

NameTypeRequiredDescription
qrIdLongODTC generated unique QR ID.
qrStringOQR content the payer scans.
brandIntegerOPayment brand filter. Refer to Enum List - Brand.
pageSizeIntegerMNumber of records per page.
pageNoIntegerMPage number to retrieve (starting from 1).

Request Body Sample (formatted)

{
  "query": {
    "brand": 201,
    "qrId": 4231,
    "qr": "0x214774e237FA1fD6895631AeBF5fc6332bb2A976",
    "pageSize": 30,
    "pageNo": 1
  }
}

Response Parameters

NameTypeRequiredDescription
paginationObjectMPaginated wrapper — see below.
resultListArrayMTransaction records — same object as Generate Merchant QR/Query Transaction Detail, see Appendix A.

pagination Parameters

NameTypeRequiredDescription
currentIntegerMCurrent page number.
sizeIntegerMPage size.
totalLongMTotal 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

CodeDescriptionWhen it happens
400Invalid parameterspageSize/pageNo missing
500Server ErrorUnexpected 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

NameTypeRequiredDescription
referenceNoStringMUnique identifier for the static QR.
brandIntegerMPayment brand. Only 201 (CRYPTO_HOSTED) is currently supported — see note above.
moduleIntegerMPayment 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

NameTypeRequiredDescription
qrIdLongMUnique static QR ID generated by DTC.
qrStringMThe QR content scanned by customers.
qrStatusIntegerMStatic QR status. Refer to Enum List - StaticQrStatus.
brandIntegerMPayment brand. Refer to Enum List - Brand.
moduleIntegerMPayment module. Refer to Enum List - Module.
referenceNoStringMUnique string to locate the static QR.
currenciesArrayMCurrencies customers can use to pay this static QR. Refer to Enum List - Currency.
createdAtStringMCreation timestamp, yyyy-MM-dd HH:mm:ss.
updatedAtStringMLast-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

CodeDescriptionWhen it happens
400Unsupported brand: brand is anything other than 201 (CRYPTO_HOSTED)
500Server ErrorUnexpected 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

NameTypeRequiredDescription
qrIdLongCUnique static QR ID.
qrStringCQR content.
referenceNoStringCStatic QR reference number.

At least one of qrId/qr/referenceNo must 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

CodeDescriptionWhen it happens
400Invalid requestNone of qrId/qr/referenceNo resolves to a static QR
500Server ErrorUnexpected 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 (the notificationUrl given 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
KeyTypeDescription
transactionIdLongUnique DTC generated transaction ID.
terminalIdLongDTC terminal ID assigned to the merchant.
merchantIdLongUnique merchant ID generated by DTC for the merchant.
referenceNoStringUnique string to locate a transaction.
stateIntegerPayment 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).

NameTypeRequiredDescription
idLongMThe DTC generated unique transaction-id.
brandIntegerMPayment brand. Refer to Enum List - Brand.
moduleIntegerOPayment module. Refer to Enum List - Module.
typeIntegerMTransaction type. Refer to Enum List - PaymentTransactionType.
stateIntegerMPayment transaction state. Refer to Enum List - PaymentTransactionState.
settlementStatusIntegerMSettlement status. Refer to Enum List - SettlementStatus.
merchantIdLongMThe merchant ID generated by DTC system for merchant.
merchantNameStringMThe merchant's own name.
terminalIdLongMThe terminal ID generated by DTC system for merchant.
acqTidStringOThe acqTid generated by DTC system for merchant. Null until an acquirer route has processed the transaction.
requestCurrencyStringMCurrency of the merchant transaction (the merchant's own accounting currency).
totalAmountDecimalMTotal 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).
saleAmountDecimalOPrice of goods.
serviceAmountDecimalOService fee amount.
serviceRateDecimalOService fee exchange rate.
gstAmountDecimalOGST amount.
gstRateDecimalOGST rate.
tipAmountDecimalOTips included in the transaction.
processingCurrencyStringMCurrency actually paid by the end customer (payer) — the settlement-facing leg of the transaction, distinct from requestCurrency.
processingAmountDecimalMAmount actually paid by the end customer (payer) in processingCurrency — the FX-converted counterpart of totalAmount that the payer sees and pays.
processingFeeDecimalOProcessing fee.
exchangeRateDecimalOExchange rate between requestCurrency and processingCurrency.
receiptNumberStringOReceipt number. Null until the transaction has a settled receipt.
referenceNoStringMUnique string to locate a transaction.
truncatedPanStringOOnly present for credit-card-brand transactions.
cardHolderNameStringOCard holder name, only present for credit-card-brand transactions.
secondaryAmountDecimalOSecondary amount.
qrIdLongOThe DTC generated unique qr-id. Only present for QR-based brands.
qrStringOThe payer scans this to initiate payment. Only present for QR-based brands.
createdAtStringMThe date-time when the request is received or created, yyyy-MM-dd HH:mm:ss.
updatedAtStringMThe datetime when the response was last updated, yyyy-MM-dd HH:mm:ss.
expiresAtStringOTransaction expiry time, yyyy-MM-dd HH:mm:ss. Only present for brands/modules with a payment-page/QR timeout.
additionalDataObjectOAdditional channel-specific transaction data (free-form key/value map).
amountDetailsArrayOAmount breakdown details: each entry has serviceFeeAmount, gstAmount, tipAmount, rate, currency.

6 Appendix B: Enum List

Brand

NameIDDescriptor
UNDEFINED0Undefined
VISA1Visa
MASTERCARD2MasterCard
AMEX3American Express
JCB4JCB
DINERS5Diners Club
DISCOVER6Discover
CUP7China UnionPay
WECHATPAY101WeChat Pay
ALIPAY102Alipay
GRABPAY103GrabPay
PAYNOW104PayNow
QUICKPASS105QuickPass
BINANCE_PAY106Binance Pay
CRYPTO_HOSTED201Crypto Hosted

Module

NameIDDescriptor
WECHAT5WeChat
CIMB6CIMB (PayNow)
WORLDPAY8Worldpay
GOOGLE_PAY9Google Pay
SAMSUNG_PAY10Samsung Pay
BINANCE_PAY11Binance Pay
ETHEREUM1002Ethereum
TRON1003Tron
BSC1007BNB Smart Chain
BASE1008Base
SOLANA1009Solana
ARBITRUM1010Arbitrum
DTCPAY5001dtcpay

Currency

NameIDCategoryCodeDescriptor
AUD10036Australian dollar
CNY20156Chinese yuan
EUR30978Euro
HKD40344Hong Kong dollar
JPY50392Japanese yen
SGD60702Singapore dollar
USD70840United States dollar
USDT81nullUSD Tether
BTC91nullBitcoin
ETH101nullEthereum
TRX111nullTron
GBP120826Pound sterling
WUSD131nullWorldwide USD
USDC141nullUSD Coin

CurrencyCategory

NameIDDescriptor
FIAT0Fiat Currency
CRYPTO1Crypto Currency
E_MONEY2e-Money Currency

SettlementStatus

NameIDDescriptor
PENDING0Pending
ACQ_SETTLED1Acquirer Settled
APPROVED2Settlement Approved
PAID3Settlement Paid
SUBMITTED6Settlement Submitted
REJECTED8Settlement Rejected

PaymentTransactionState

NameIDDescriptor
PENDING0Pending
AUTHORIZED101Authorized
PARTIAL_PAYMENT103Partial Payment
SUCCESS200Success
CAPTURED221Captured
REVERSED301Reversed
CANCELLED302Cancelled
REFUNDED401Refunded
DENIED900Denied
EXPIRED990Expired

PaymentTransactionType

NameIDDescriptor
TOKENIZE0Tokenize
AUTHORIZATION100Authorization
SALE200Sale
CAPTURE220Capture
VOID300Void
REFUNDED400Refund (refund open API is not currently available; operated via the DTC business portal)
MERCHANT_DYNAMIC_QR71001Merchant Dynamic QR
CONSUMER_QR72001Consumer QR
STATIC_QR72002Static QR

StaticQrStatus

NameIDDescriptor
DISABLED1Disabled
ENABLED2Enabled