| Date | Key Changes |
|---|---|
| 2026-09-24 | Delete Bank Account API (new) |
| 2026-09-16 | Crypto Checkout & Refund v2.2 — referenceAmount, settleAmount, feeBearer |
| 2026-09-14 | Merchant Activation — LINK method + dual OTP/LINK status |
| 2026-08-14 | Fiat Withdrawal third-party (POBO) purpose-of-transaction controls |
| 2026-08-06 | Crypto Deposit Address Risk Management (webhook + address status) |
| 2026-07-17 | Merchant Activation APIs |
| 2026-07-07 | Crypto Checkout & Refund v2.0 (16 new APIs) |
| 2026-06-16 | Modified APIs |
| 2026-06-12 | Fee Estimate, Address Validation |
| 2026-06-02 | Statements, Points APIs |
| 2026-04-02 | Initial v2.0 release (73 APIs) |
| Status | Count | Note |
|---|---|---|
| New APIs | 1 | Delete Bank Account |
| Deleted APIs | 0 | — |
| Modified APIs | 0 | — |
POST /v2.0/crm/addressBook/bankAccount/delete| Field | Type | Required | Description |
|---|---|---|---|
bankAccountId | string | Yes | The bank account ID to delete |
participantCode | string | No | For delegated calls: the merchant participant code the PSP acts on behalf of. Omit for self-service deletion |
{
"code": 200,
"msg": "success",
"data": null,
"timestamp": 1789978538795,
"logId": "6ab0e7aaa34c1db61c8e55c4a94d0869"
}| HTTP | Code | Description |
|---|---|---|
| 422 | BUSINESS_BANK_ACCOUNT_HAS_IN_PROGRESS_TRANSACTION | The bank account has an in-progress deposit or withdrawal and cannot be deleted |
| 404 | RESOURCE_BANK_ACCOUNT_NOT_FOUND | The bank account does not exist, or it belongs to another participant. Cross-participant access is reported as 404 (rather than 403) so the API does not disclose whether another participant's bank account exists |
| 403 | AUTH_PARTICIPANT_MISMATCH | Delegated-call participant mismatch |
POST /v2.0/payment/crypto/checkoutsorderAmount and buyerInfo are no longer required. You must provide either orderAmount or the new referenceAmount (at least one).referenceAmount (ReferenceAmountRequestDto): quote the order in a reference currency; the platform converts it to the order currency at Create Checkout.referenceAmount (ReferenceAmountResponseDto, conversion result; present only when referenceAmount was sent) and settleAmount (settlement amount).buyerInfo / paymentMethod: paymentMethod is a top-level field; when it is provided, buyerInfo becomes mandatory.GET /v2.0/payment/crypto/checkouts/{checkoutId}referenceAmount and settleAmount.POST /v2.0/payment/crypto/refunds/refundfeeBearer is no longer required; defaults to BUYER when omitted.POST /v2.0/payment/crypto/refunds/voidfeeBearer (BUYER | MERCHANT, default BUYER).refundCurrency and blockchain are no longer required.POST /v2.0/payment/crypto/refunds/risk-refundReferenceAmountRequestDto, ReferenceAmountResponseDto.| Status | Count | Note |
|---|---|---|
| New APIs | 0 | — |
| Deleted APIs | 0 | — |
| Modified APIs | 3 | Initiate Merchant Activation, Get Merchant, Merchant Status Webhook |
Breaking change: No. Existing OTP-only integrations remain compatible: activationMethoddefaults to OTP;supportContactEmailandshowPartnerLogoare optional and additive; the original sixactivationStatusvalues are preserved (LINK adds one new value,INVALIDATED).
POST /v2.0/crm/merchant/initiateActivationactivationMethod (string, optional, enum OTP | LINK, default OTP) — Activation channel. Omitted → OTP (backward compatible).supportContactEmail (string, optional, email) — Support contact email shown in the activation email for both OTP and LINK. Overrides the partner-level support email when provided.showPartnerLogo (boolean, optional, default false) — Whether to show the partner logo in the activation email for both OTP and LINK. Silently degrades if no logo is uploaded.activationMethod (string) — Channel used (OTP | LINK).linkExpiresAt (integer, Unix ms) — LINK expiry (72-hour TTL). Returned for LINK only.supportContactEmail (string) — Effective support contact email shown in the activation email (OTP and LINK).showPartnerLogo (boolean) — Effective partner-logo flag shown in the activation email (OTP and LINK).initiateActivation(activationMethod=LINK) → end-user clicks the emailed link and consents on the hosted page → merchant moves to PENDING_ACTIVATION; the link is single-use. Re-initiating with LINK supersedes any previous link.activationStatusactivationStatus value now depends on the activation channel: OTP reports MerchantActivationStatus (unchanged), while LINK reports LinkActivationStatus.| Channel | Status values |
|---|---|
| OTP | NOT_ACTIVATED, PENDING_ACTIVATION, ACTIVATED, LOCKED, EXPIRED, NO_NEED_ACTIVATION |
| LINK | PENDING_ACTIVATION, ACTIVATED, EXPIRED, NO_NEED_ACTIVATION, INVALIDATED |
PENDING_ACTIVATION, ACTIVATED, NO_NEED_ACTIVATION. LINK adds INVALIDATED (link invalidated by re-initiation, or the other channel activated the merchant); LINK has no NOT_ACTIVATED or LOCKED.GET /v2.0/crm/addressBook/getMerchantdata.activationStatus description updated to the two-set model above. No structural change.POST /webhooks/merchant-status/v2data.activationStatus description updated to the two-set model above. No structural change.| Endpoint | Path | Type |
|---|---|---|
| Initiate Merchant Activation | POST /v2.0/crm/merchant/initiateActivation | Modified (LINK channel + new fields) |
| Get Merchant | GET /v2.0/crm/addressBook/getMerchant | Modified (two-set activationStatus) |
| Merchant Status Webhook | POST /webhooks/merchant-status/v2 | Modified (two-set activationStatus) |
POST /v2.0/payment/fiat/createWithdrawal| Status | Count | Note |
|---|---|---|
| New webhook | 1 | crypto.deposit.address.suspended.v1 |
| Modified APIs | 3 | field additions |
| Explicitly unchanged | 1 | getCryptoDepositHistory (diagnostic only in detail endpoints) |
/v2.0/crm/deposit/wallet/webhooks/crypto-deposit-address/suspendedcrypto.deposit.address.suspended.v1/webhooks/crypto-depositcrypto.deposit.updated.v2/v2.0/payment/getCryptoDeposit/v2.0/payment/getCryptoDepositHistorydepositAddressStatus is intentionally NOT added to the list endpoint. Address status is diagnostic information surfaced only in the detail endpoints (per PRD v2.3 section 3.5).| Status | Count | Note |
|---|---|---|
| New APIs | 0 | - |
| Deleted APIs | 1 | Fully removed |
| Modified APIs | 39 | With field-level changes |
| Unchanged APIs | 33 | No modifications |
| Total APIs (v2.0) | 73 |
/v1.0/oauth/token → /v2.0/oauth/token/v1.0/ledger/account → /v2.0/ledger/account/v1.0/payment/account/getInternalTransfer → /v2.0/payment/account/getInternalTransferstring -> integer/v1.0/payment/account/internalTransfer → /v2.0/payment/account/internalTransferstring -> integer/v2.0/crm/addressBook/createMerchant/v2.0/crm/addressBook/getMerchant/v1.0/crm/deposit/bankAccount → /v2.0/crm/deposit/bankAccount/v1.0/payment/fiat/deposit/detail → /v2.0/payment/fiat/deposit/detailstring -> integer/v1.0/payment/fiat/deposit/history → /v2.0/payment/fiat/deposit/historystring -> integer/v1.0/crm/addressBook/addBankAccount → /v2.0/crm/addressBook/addBankAccount/v1.0/crm/addressBook/bankAccount → /v2.0/crm/addressBook/bankAccount/v2.0/crm/fiatAccount/appStatus/v2.0/crm/fiatAccount/addInfo/submit/v2.0/payment/fiat/createWithdrawalnumber -> stringnumber -> stringnumber -> stringnumber -> string/v2.0/payment/fiat/withdrawal/detailnumber -> stringnumber -> stringnumber -> string/v2.0/payment/fiat/withdrawal/historynumber -> stringnumber -> stringnumber -> string/v1.0/payment/getCryptoDeposit → /v2.0/payment/getCryptoDeposit/v1.0/payment/getCryptoDepositHistory → /v2.0/payment/getCryptoDepositHistory/v1.0/crm/deposit/wallet → /v2.0/crm/deposit/wallet/v1.0/payment/crypto/updateCryptoDepositTravelRuleInfo → /v2.0/payment/crypto/updateCryptoDepositTravelRuleInfoFalse -> Trueobject -> nullTrue -> False/v1.0/payment/crypto/createCryptoWithdrawal → /v2.0/payment/crypto/createCryptoWithdrawalnumber -> stringnumber -> stringnumber -> string/v1.0/payment/getCryptoWithdrawal → /v2.0/payment/getCryptoWithdrawalnumber -> stringnumber -> string/v1.0/payment/getCryptoWithdrawalHistory → /v2.0/payment/getCryptoWithdrawalHistorynumber -> stringnumber -> string/v1.0/payment/crypto/getWalletAddress → /v2.0/payment/crypto/getWalletAddress/v1.0/payment/crypto/registerWalletAddress → /v2.0/payment/crypto/registerWalletAddress/v1.0/payment/crypto/removeWalletAddress → /v2.0/payment/crypto/removeWalletAddress/v1.0/trade/conversion/createConversion → /v2.0/trade/conversion/createConversion/v1.0/trade/conversion/createQuotation → /v2.0/trade/conversion/createQuotation/v1.0/trade/conversion/getConversion → /v2.0/trade/conversion/getConversion/v1.0/trade/conversion/getQuotation → /v2.0/trade/conversion/getQuotation/v2.0/auth/tools/upload/v2.0/tool/getTnC/{tncId}string -> integerConversion WebhookCrypto Deposit WebhookCrypto Withdrawal Webhooknumber -> stringnumber -> stringFiat Account Request Status WebhookFiat Deposit Webhookstring -> integerFiat Withdrawal Webhooknumber -> stringnumber -> stringnumber -> stringMerchant Status Webhook| Method | Path | Name |
|---|---|---|
| GET | /v1.0/payment/getStatement | Get Settlement Statement |
| Status | Count | Note |
|---|---|---|
| New APIs | 4 | - |
| Deleted APIs | 0 | Fully removed |
| Modified APIs | 0 | With field-level changes |
| Method | Path | Name |
|---|---|---|
| POST | /v2.0/payment/statements | Create statement |
| GET | /v2.0/payment/statements/{statementId} | Get statement overview |
| GET | /v2.0/payment/statements/{statementId}/entries | Get statement entries |
| GET | /v2.0/payment/statements/{statementId}/transactions | Get statement transactions |
| Status | Count | Note |
|---|---|---|
| New APIs | 4 | - |
| Deleted APIs | 0 | Fully removed |
| Modified APIs | 0 | With field-level changes |
| Method | Path | Name |
|---|---|---|
| POST | /v2.0/payment/withdrawal/feeEstimate | Fee Estimate |
| GET | /v2.0/points/balance | Get Points Balance |
| GET | /v2.0/points/transactions | List Points Transactions |
| GET | /v2.0/points/transactions/detail | Get Points Transaction Detail |
| Status | Count | Note |
|---|---|---|
| New APIs | 0 | — |
| Deleted APIs | 0 | — |
| Modified APIs | 3 | Field-level changes only |
Breaking change: No. All v2.0 valid requests remain valid in 20260616. URL paths, request/response structure, and field types are unchanged.
/v2.0/crm/addressBook/createMerchant (unchanged)merchantDetails → additionalCorporationDetails → natureOfBusiness (Modified)| Property | Old | New |
|---|---|---|
| Type | integer | integer (unchanged) |
| Required | Yes (tier 3 only) | Yes (all tiers) |
| Enum values | 1–18 | 1–24 |
| Description | "The nature of the company's business" | Extended with full label mapping |
| Value | Old Label | New Label |
|---|---|---|
| 2 | Manufacturing | Manufacturing and Industrial |
| 6 | Hospitality and Tourism | Hospitality and Travel |
| 7 | Real Estate and Construction | Real Estate and E-Commerce |
| 8 | Health Care and Pharmaceuticals | Healthcare |
| 9 | Professional and Services | Professional Services |
| 16 | Multimedia and Entertainment | Media and Entertainment |
| 17 | Cryptocurrency Mining | Cryptocurrency & Digital Assets |
Values 1, 3, 4, 5, 10, 11, 12, 13, 14, 15, 18 (Others) — labels unchanged. Integer values unchanged. No code change required for existing integrations.
| Value | Label |
|---|---|
| 19 | Insurance & Wealth |
| 20 | Trading & Commodities |
| 21 | Digital Products & Online Services |
| 22 | Business Support Services |
| 23 | Gaming |
| 24 | Advertising |
merchantDetails → additionalCorporationDetails → otherNatureOfBusiness (New)| Property | Value |
|---|---|
| Type | string |
| Required | No (optional) |
| Description | Specific business nature description. Use when natureOfBusiness = 18 (Others). |
merchantDetails → additionalCorporationDetails → sourceOfWealth (Modified)| Property | Old | New |
|---|---|---|
| Type | array[string] | array[string] (unchanged) |
| Required | No | Yes (tier 3) |
| Description | "Source of wealth (If HIGH risk and/or PEP)" | "Source of wealth. Required for tier 3 as of 20260616." |
merchantDetails → additionalPersonalDetails → sourceOfWealth (Modified)| Property | Old | New |
|---|---|---|
| Type | array[string] | array[string] (unchanged) |
| Required | No | Yes (tier 3) |
| Description | "Source of wealth" | "Source of wealth. Required for tier 3 as of 20260616." |
| Tier | Old Behavior | New Behavior |
|---|---|---|
| Tier 1/2 (Corporate) | additionalCorporationDetails not available | Can submit additionalCorporationDetails with only natureOfBusiness (and optional otherNatureOfBusiness). The 8-field required constraint is waived for this case (server-side exception). |
| Tier 3 (Corporate) | additionalCorporationDetails required; sourceOfWealth optional | additionalCorporationDetails required; sourceOfWealth now required (8 fields: operatingAddress, companyType, descriptionOfBusiness, purposesOfAccountOpening, sourceOfFunds, authSignatories, directors, sourceOfWealth) |
| Tier 3 (Individual) | additionalPersonalDetails optional; sourceOfWealth optional | additionalPersonalDetails optional; sourceOfWealth now required when the block is submitted (4 fields: occupation, purposesOfAccountOpening, sourceOfFunds, sourceOfWealth) |
/v2.0/crm/addressBook/getMerchant (unchanged)natureOfBusiness, otherNatureOfBusiness, and sourceOfWealth in additional details blocks.| Field | Location | Type |
|---|---|---|
natureOfBusiness | merchantInfo.merchantDetails.additionalCorporationDetails | integer (1–24) |
otherNatureOfBusiness | merchantInfo.merchantDetails.additionalCorporationDetails | string |
sourceOfWealth | merchantInfo.merchantDetails.additionalCorporationDetails | array[string] |
sourceOfWealth | merchantInfo.merchantDetails.additionalPersonalDetails | array[string] |
eventType, notificationId, data with applicationId / merchantInfo / status / statusInfo / updatedAt) is unchanged from v2.0.natureOfBusiness, otherNatureOfBusiness, sourceOfWealth) are included within merchantInfo when present on the merchant record.sourceOfWealth in tier 3 merchant creation — your existing requests remain valid.natureOfBusiness is now required for every corporate merchant creation. Submit it within additionalCorporationDetails.sourceOfWealth is now required in both additionalCorporationDetails (CORPORATE) and additionalPersonalDetails (INDIVIDUAL).natureOfBusiness = 18 (Others), consider adopting the new otherNatureOfBusiness field to provide a specific business type description.| Value | Label | Status |
|---|---|---|
| 1 | Financial Services | Unchanged |
| 2 | Manufacturing and Industrial | Renamed |
| 3 | Information Technology | Unchanged |
| 4 | Agriculture and Farming | Unchanged |
| 5 | Retail and Wholesale | Unchanged |
| 6 | Hospitality and Travel | Renamed |
| 7 | Real Estate and E-Commerce | Renamed |
| 8 | Healthcare | Renamed |
| 9 | Professional Services | Renamed |
| 10 | Education and Training | Unchanged |
| 11 | Non Profit and Charity | Unchanged |
| 12 | Transaction and Logistics | Unchanged |
| 13 | Energy and Utilities | Unchanged |
| 14 | Telecommunications | Unchanged |
| 15 | Government and Public Sector | Unchanged |
| 16 | Media and Entertainment | Renamed |
| 17 | Cryptocurrency & Digital Assets | Renamed |
| 18 | Others | Unchanged |
| 19 | Insurance & Wealth | New |
| 20 | Trading & Commodities | New |
| 21 | Digital Products & Online Services | New |
| 22 | Business Support Services | New |
| 23 | Gaming | New |
| 24 | Advertising | New |
| Status | Count | Note |
|---|---|---|
| New APIs | 17 | Crypto Checkout |
| Deleted APIs | 0 | — |
| Modified APIs | 9 | Withdrawal — amount semantics clarification (field-level only) |
Breaking change: No. All v2.0 valid requests remain valid in 20260707. Existing withdrawal integrations are backward-compatible; checkout APIs are additive.
| Method | Path | Name | Status |
|---|---|---|---|
| POST | /v2.0/payment/crypto/checkouts | Create Checkout | released |
| POST | /v2.0/payment/crypto/checkouts/quotations | Create Checkout Quotation | released |
| POST | /v2.0/payment/crypto/checkouts/{checkoutId}/confirm | Confirm Checkout | released |
| POST | /v2.0/payment/crypto/checkouts/{checkoutId}/accept | Accept Checkout | developing |
| GET | /v2.0/payment/crypto/checkouts/history | List Checkout History | developing |
| GET | /v2.0/payment/crypto/checkouts/{checkoutId} | Get Checkout Detail | released |
| POST | /v2.0/payment/crypto/checkouts/{checkoutId}/close | Close Checkout | released |
| GET | /v2.0/payment/crypto/checkouts/cryptos | Get Checkout Acceptable Cryptos | released |
| POST | (partner webhook) | Checkout Status Webhook | released |
| Method | Path | Name | Status |
|---|---|---|---|
| POST | /v2.0/payment/crypto/refunds/refund | Create Refund | released |
| POST | /v2.0/payment/crypto/refunds/risk-refund | Create Risk Refund | released |
| POST | /v2.0/payment/crypto/refunds/void | Create Void Refund | released |
| POST | /v2.0/payment/crypto/refunds/{refundId}/close | Close Refund | released |
| GET | /v2.0/payment/crypto/refunds/{refundId} | Get Refund Detail | released |
| GET | /v2.0/payment/crypto/checkouts/{checkoutId}/refundable-info | Get Checkout Refundable Info | released |
| POST | (partner webhook) | Refund Status Webhook | released |
| Method | Path | Name | Status |
|---|---|---|---|
| POST | /v2.0/payment/crypto/addresses/validate | Validate Crypto Address | released |
POST /v2.0/payment/crypto/checkouts| Field | Type | Required | Description |
|---|---|---|---|
participantCode | string | Yes | Participant's (merchant) code |
orderAmount | string | Yes | Amount to be paid |
orderCurrency | string | Yes | Payment currency code (e.g. USD) |
expiry | integer | Yes | Order expiration timestamp in milliseconds |
buyerInfo | oneOf | Yes | IndividualBuyerInfo or CorporateBuyerInfo (see below) |
productInfo | object | Yes | {"productName" (required), "description", "productImageUrl"} |
clientCheckoutId | string | Yes | External client checkout ID (unique per merchant) |
checkoutConfiguration | object | No | UI/UX config: merchantName, merchantLogo, redirectUrl, customerSupportEmail, defaultLanguage (ENGLISH/CHINESE), checkoutLinkLogo, feeBearer (BUYER/MERCHANT) |
paymentMethod | object | No | Pre-select {"paymentCurrency", "blockchain"}. If provided, acceptableCryptos in response is null |
buyerInfo oneOf option 1):| Field | Type | Required | Description |
|---|---|---|---|
firstName | string | Yes | First name |
lastName | string | Yes | Last name |
middleName | string | No | Middle name |
residentialAddress | object | ≥1000 USD | Address fields: country, state, city, postcode, addressLine1, addressLine2 |
identityType | string | No | PASSPORT or NRIC |
identityNumber | string | ≥1000 USD | Identity document number |
dateOfBirth | string | ≥1000 USD | Format: YYYY-MM-DD |
placeOfBirth | string | ≥1000 USD | Place of birth |
nationality | string | No | ISO 3166-1 alpha-2 |
≥1000 USD: at least one of {residentialAddress, identityNumber, dateOfBirth + placeOfBirth}required.
buyerInfo oneOf option 2):| Field | Type | Required | Description |
|---|---|---|---|
companyName | string | Yes | Company name |
registeredAddress | object | ≥1000 USD | Registered business address |
businessRegistrationNumber | string | ≥1000 USD | Business registration number |
countryOfIncorporation | string | ≥1000 USD | ISO 3166-1 alpha-2 |
dateOfRegistration | string | ≥1000 USD | Date of registration |
| Field | Type | Description |
|---|---|---|
checkoutId | string | e.g. CKO_20240115_001 |
status | string | OPENING |
checkoutUrl | string (uri) | Checkout page URL |
orderAmount | string | Order amount |
orderCurrency | string | Order currency |
createdAt | integer | Creation timestamp |
acceptableCryptos | array | Accepted [{cryptoCurrency, blockchains[]}] (null if paymentMethod specified) |
checkoutConfiguration | object | Echo of config |
paymentMethod | object | Payment method details |
POST /v2.0/payment/crypto/checkouts/quotations| Field | Type | Required | Description |
|---|---|---|---|
participantCode | string | Yes | Participant code |
orderAmount | string | Yes | Order amount |
orderCurrency | string | Yes | Order currency code |
paymentCurrency | string | Yes | Payment cryptocurrency (e.g. USDT) |
| Field | Type | Description |
|---|---|---|
quotationId | string | Quotation ID |
participantCode | string | Participant code |
price | string | Exchange rate |
paymentAmount | string | Amount in cryptocurrency |
paymentCurrency | string | Payment cryptocurrency |
orderAmount | string | Order amount |
orderCurrency | string | Order currency |
quotationExpiry | integer | Expiry timestamp (ms) |
POST /v2.0/payment/crypto/checkouts/{checkoutId}/confirm| Parameter | Type | Required |
|---|---|---|
checkoutId | string | Yes |
| Field | Type | Required | Description |
|---|---|---|---|
paymentCurrency | string | Yes | e.g. USDT |
blockchain | string | Yes | e.g. TRC20 |
quotationId | string | No | Quotation ID to reuse |
email | string | No | Email for refund address collection |
| Field | Type | Description |
|---|---|---|
quotationId | string | Quotation ID |
checkoutId | string | Checkout ID |
status | string | AWAITING_PAYMENT |
price | string | Exchange rate |
orderAmount / orderCurrency | string | Order details |
paymentAmount / paymentCurrency | string | Payment details |
payeeFeeAmount | object | Buyer-side fee {amount, feeCurrency} |
payerFeeAmount | object | Merchant-side fee {amount, feeCurrency} |
paymentBlockchain | string | Blockchain network |
checkoutWallet | string | Receiving address |
qrCode | string | Base64-encoded PNG QR |
quotationExpiry | integer | Expiry (ms) |
email | string | Refund email |
POST /v2.0/payment/crypto/checkouts/{checkoutId}/acceptStatus: developing
| Parameter | Type | Required | Description |
|---|---|---|---|
acceptMode | string | Yes | ACCEPT — settle all; VOID_OVERPAYMENT — settle paymentAmount & void excess; VOID_ALL — void entire order |
refundAddress | string | No | Refund address for void refunds |
| Field | Type | Description |
|---|---|---|
checkoutId | string | Checkout ID |
status | string | Order status |
acceptMode | string | Applied mode |
acceptedAt | string | Timestamp |
voidRefund | object | Void refund details (when applicable) |
GET /v2.0/payment/crypto/checkouts/historyStatus: developing
| Parameter | Type | Required |
|---|---|---|
participantCode | string | No |
startTime | string | No |
endTime | string | No |
offset | string | No |
| Field | Type | Description |
|---|---|---|
participantCode | string | Participant code |
startTime / endTime | string | Query time range |
transactions | array[CryptoCheckoutDetail] | Checkout records (see A.2.6) |
pagination | object | {limit, offset, total, hasMore} |
GET /v2.0/payment/crypto/checkouts/{checkoutId}| Field | Type | Description |
|---|---|---|
checkoutId | string | Checkout ID |
participantCode | string | Participant code |
clientCheckoutId | string | External client checkout ID |
status | string | OPENING → AWAITING_PAYMENT → RECEIVED → SUCCEEDED → SETTLED / EXPIRED / CLOSED |
orderAmount / orderCurrency | string | Order amount & currency |
paymentAmount / paymentCurrency / paymentBlockchain | string | Payment details |
accumulatedAmount | string | Total received |
quotationId / quotationExpiry | string / integer | Quotation details |
checkoutExpiry | integer | Checkout expiry (ms) |
email | string | Refund email |
payeeFeeAmount / payerFeeAmount | object | {amount, currency} — buyer/merchant fees |
riskTobeRefund | boolean | true = to be refunded; false = not; null = no risk |
receivedPayments | array | See below |
conversions | array[ConversionInfo] | Conversion records |
createdAt / updatedAt | integer | Timestamps |
| Field | Type | Description |
|---|---|---|
receivedPaymentId | string | Payment ID |
paymentSequence | integer | Sequence number |
paidAmount / paidCurrency | string | Paid amount & currency |
blockchain | string | Blockchain network |
fromAddress | string | Sender wallet |
txHash | string | Transaction hash |
status | string | PAYMENT_DETECTED / PAYMENT_ACCEPTED / PAYMENT_REJECTED / PAYMENT_ERROR |
| Field | Type | Description |
|---|---|---|
conversionId | string | Conversion ID |
quotationId / participantCode / price | string | Related quotation |
sourceCurrency / sourceAmount | string | Source |
destinationCurrency / destinationAmount | string | Destination |
status | string | INITIATED / COMPLETED / CANCELLED |
createdAt | integer | Timestamp |
POST /v2.0/payment/crypto/checkouts/{checkoutId}/close| Field | Type | Required | Description |
|---|---|---|---|
processingResult | integer | Yes | 1 = To be settled; 2 = To be closed |
| Field | Type | Description |
|---|---|---|
checkoutId | string | Checkout ID |
success | boolean | Operation result |
closedAt | integer | Closed timestamp |
GET /v2.0/payment/crypto/checkouts/cryptos| Parameter | Type | Required |
|---|---|---|
participantCode | string | Yes |
orderCurrency | string | Yes |
| Field | Type | Description |
|---|---|---|
participantCode | string | Participant code |
orderCurrency | string | Order currency |
acceptableCryptos | array | [{cryptoCurrency, blockchains[]}] |
POST (partner webhook)crypto.checkout.updated.v2. Payload: {eventType, notificationId, data: CryptoCheckoutDetail}. Respond with HTTP 200.POST /v2.0/payment/crypto/refunds/refund| Field | Type | Required | Description |
|---|---|---|---|
originalTransactionType | string | Yes | CHECKOUT or COLLECTION |
originalTransactionId | string | Yes | Original transaction ID |
amount | string | Yes | Refund amount in order currency |
refundCurrency | string | Yes | Order currency (e.g. USD) |
feeBearer | string | Yes | BUYER or MERCHANT |
clientRefundId | string | Yes | External refund ID (unique) |
refundInfo | oneOf | Yes | {"email"} or {"refundAddress"} |
| Field | Type | Description |
|---|---|---|
refundId | string | e.g. REF_20240115_001 |
refundType | string | REFUND |
originalTransactionId | string | Original transaction ID |
clientRefundId | string | External refund ID |
amount / currency | string | Refund amount & currency |
blockchain | string | Blockchain network |
feeAmount / feeCurrency | string | Transaction fee |
netAmount / netAmountCurrency | string | Net received amount |
status | string | INITIATED → PROCESSING → COMPLETED / REJECTED / CLOSED |
email / refundAddress | string | Refund destination |
POST /v2.0/payment/crypto/refunds/risk-refundCHECKOUT, COLLECTION, and DEPOSIT original transaction types.| Field | Type | Required | Description |
|---|---|---|---|
originalTransactionType | string | Yes | CHECKOUT, COLLECTION, or DEPOSIT |
originalTransactionId | string | Yes | Original transaction ID |
clientRefundId | string | Yes | External refund ID (unique) |
refundCurrency | string | No | Refund cryptocurrency |
blockchain | string | No | Blockchain network |
refundInfo | oneOf | Yes | {"email"} or {"refundAddress"} |
refundType = RISK_REFUND.POST /v2.0/payment/crypto/refunds/void| Field | Type | Required | Description |
|---|---|---|---|
originalTransactionType | string | Yes | CHECKOUT or COLLECTION |
originalTransactionId | string | Yes | Original transaction ID |
clientRefundId | string | Yes | External refund ID (unique) |
refundCurrency | string | No | Refund cryptocurrency |
blockchain | string | No | Blockchain network |
refundInfo | oneOf | Yes | {"email"} or {"refundAddress"} |
refundType = VOID.POST /v2.0/payment/crypto/refunds/{refundId}/close{}.| Field | Type | Description |
|---|---|---|
refundId | string | Refund ID |
success | boolean | Operation result |
closedAt | integer | Closed timestamp |
GET /v2.0/payment/crypto/refunds/{refundId}| Field | Type | Description |
|---|---|---|
refundId | string | Refund ID |
refundType | string | VOID, RISK_REFUND, or REFUND |
originalTransactionId | string | Original transaction ID |
participantCode | string | Merchant code |
clientRefundId | string | External refund ID |
status | string | INITIATED / PROCESSING / COMPLETED / REJECTED / CLOSED |
reason | string | Failure reason (when applicable) |
blockchain | string | Blockchain network |
currency / amount | string | Refund currency & amount |
email / refundAddress | string | Refund destination |
feeCurrency / feeAmount | string | Fee details |
netAmount / netAmountCurrency | string | Net received |
txHash | string | On-chain transaction hash |
createdAt / updatedAt | integer | Timestamps |
GET /v2.0/payment/crypto/checkouts/{checkoutId}/refundable-infonull. An order with nothing refundable still returns 200.| Parameter | Type | Required |
|---|---|---|
participantCode | string | Yes |
| Field | Type | Description |
|---|---|---|
checkoutId | string | Checkout ID |
refundableItem | object | null | Settled refundable balance |
voidableItems | array | null | VOID amounts |
riskRefundableItems | array | null | Risk-refundable amounts |
{amount: {amount, currency}, chainCode}.POST (partner webhook)crypto.refund.updated.v2. Payload: {eventType, notificationId, data: CryptoRefundDetail}. Respond with HTTP 200.POST /v2.0/payment/crypto/addresses/validatedata.valid.| Field | Type | Required | Description |
|---|---|---|---|
blockchain | string | Yes | e.g. ETH |
address | string | Yes | On-chain address |
| Field | Type | Description |
|---|---|---|
blockchain | string | Echo of request |
address | string | Echo of request |
valid | boolean | true = valid format; false = invalid |
valid: false):| failureCode | Meaning |
|---|---|
INVALID_ADDRESS | Address format incorrect for blockchain |
VALIDATION_UNAVAILABLE | Validation query failed; retry later |
amount represented a gross debit amount (total deducted from account, including fees) or a net received amount (amount the payee receives, excluding fees). This convention was derived from withdrawalType (for fiat) or beneficiaryWallet ownership (for crypto), which created ambiguity and integration complexity.amountType, adds fee bearer declaration via feeBearer, and formally separates debit / received amounts in the response via dedicated fields (debitAmount, receivedAmount). For fiat withdrawals, feeAmount and feeCurrency are added to the response (crypto withdrawal already had these fields). Legacy response fields (fees, estimatedAmountReceivable) are retained as aliases./v2.0/payment/crypto/createCryptoWithdrawal (unchanged)amountType and feeBearer request fields; amount semantics clarified.amountType (New)| Property | Value |
|---|---|
| Type | integer |
| Required | Yes (for new integrations) |
| Enum values | 1 = Debit (gross debit amount), 2 = Receive (net received amount) |
| Default (backward compat) | Falls back on beneficiaryWallet ownership: first-party wallet → Debit, third-party wallet → Receive |
| Description | Explicitly declares the meaning of amount. New integrations must provide this field. |
feeBearer (New)| Property | Value |
|---|---|
| Type | integer |
| Required | No (optional) |
| Enum values | 1 = Customer (borne by trading party), 2 = Partner (borne by platform partner) |
| Default | 1 (Customer) |
| Description | Which participant account bears the platform fee. Default behavior is unchanged from v2.0. |
amount (Modified)| Property | Old | New |
|---|---|---|
| Type | string | string (unchanged) |
| Required | Yes | Yes (unchanged) |
| Meaning | Implicitly derived from withdrawalType | Explicitly declared by amountType |
When amountTypeis not provided, the backend falls back on the existingbeneficiaryWalletlogic. Existing integrations do not need to change.
| Field | Type | Description |
|---|---|---|
amountType | integer | Echoed from request. 1=Debit, 2=Receive. |
feeBearer | integer | Echoed from request. 1=Customer, 2=Partner. |
debitAmount | string | Gross debit amount. The relationship debitAmount = receivedAmount + feeAmount always holds. feeBearer=1: full amount from trading party account; feeBearer=2: fee portion from partner account instead. |
receivedAmount | string | Net amount received by payee (excluding platform fees). |
Legacy fields unchanged. The above fields are additional — existing response fields remain.
/v2.0/payment/getCryptoWithdrawal (unchanged)amountType, feeBearer, debitAmount, receivedAmount.| Field | Type | Description |
|---|---|---|
amountType | integer | 1=Debit, 2=Receive. Echoed from creation-time value. |
feeBearer | integer | 1=Customer, 2=Partner. Echoed from creation-time value. |
debitAmount | string | Gross debit amount. |
receivedAmount | string | Net amount received by payee. |
All existing response fields unchanged. New fields are additive only.
/v2.0/payment/getCryptoWithdrawalHistory (unchanged)amountType, feeBearer, debitAmount, receivedAmount.amountType, feeBearer, debitAmount, receivedAmount.| Field | Type | Description |
|---|---|---|
amountType | integer | 1=Debit, 2=Receive |
feeBearer | integer | 1=Customer, 2=Partner |
debitAmount | string | Gross debit amount |
receivedAmount | string | Net amount received by payee |
Existing payload fields unchanged. Webhook signature verification, retry policy, and security model are unchanged.
/v2.0/payment/fiat/createWithdrawal (unchanged)amountType and feeBearer request fields; amount semantics clarified.amountType (New)| Property | Value |
|---|---|
| Type | integer |
| Required | Yes (for new integrations) |
| Enum values | 1 = Debit (gross debit amount), 2 = Receive (net received amount) |
| Default (backward compat) | Falls back on withdrawalType: withdrawalType=1 (First Party) → Debit, withdrawalType=2 (Third Party) → Receive |
| Description | Explicitly declares the meaning of amount. New integrations must provide this field. |
feeBearer (New)| Property | Value |
|---|---|
| Type | integer |
| Required | No (optional) |
| Enum values | 1 = Customer (borne by trading party), 2 = Partner (borne by platform partner) |
| Default | 1 (Customer) |
| Description | Which participant account bears the platform fee. Default behavior is unchanged. |
amount (Modified)| Property | Old | New |
|---|---|---|
| Meaning | Implicitly derived from withdrawalType | Explicitly declared by amountType |
| Field | Type | Description |
|---|---|---|
amountType | integer | Echoed from request. 1=Debit, 2=Receive. |
feeBearer | integer | Echoed from request. 1=Customer, 2=Partner. |
debitAmount | string | Gross debit amount — total actually debited from the trading party account. |
feeAmount | string | Platform fee amount. Alias for legacy field fees. |
feeCurrency | string | Fee currency (uppercase ISO 4217). Typically same as currency. |
receivedAmount | string | Net amount received by payee. Alias for legacy field estimatedAmountReceivable. |
| Legacy Field | Equivalent |
|---|---|
fees | feeAmount |
estimatedAmountReceivable | receivedAmount |
Both legacy and new field names are returned. No removal of existing fields.
/v2.0/payment/fiat/withdrawal/detail (unchanged)fees and estimatedAmountReceivable retained as aliases./v2.0/payment/fiat/withdrawal/history (unchanged)| Field | Type | Description |
|---|---|---|
amountType | integer | 1=Debit, 2=Receive |
feeBearer | integer | 1=Customer, 2=Partner |
debitAmount | string | Gross debit amount |
feeAmount | string | Platform fee (alias for legacy fees) |
feeCurrency | string | Fee currency |
receivedAmount | string | Net amount received (alias for legacy estimatedAmountReceivable) |
Legacy fields feesandestimatedAmountReceivableare retained as aliases in the webhook payload.
/v2.0/payment/withdrawal/feeEstimate (unchanged)feeBearer to request and response.Non-breaking: The totalAmount→debitAmountandreceiveAmount→receivedAmountrenames occurred before production release. No client code is affected.
feeBearer (New)| Property | Value |
|---|---|
| Type | string |
| Required | No (optional) |
| Enum values | CUSTOMER (default), PARTNER |
| Description | Which participant account bears the platform fee. |
debitAmount (Renamed from totalAmount, pre-production)| Property | Old | New |
|---|---|---|
| Name | totalAmount | debitAmount |
| Type | string | string (unchanged) |
| Description | Gross debit amount (FIRST_PARTY only). Mutually exclusive with receivedAmount. |
receivedAmount (Renamed from receiveAmount, pre-production)| Property | Old | New |
|---|---|---|
| Name | receiveAmount | receivedAmount |
| Type | string | string (unchanged) |
| Description | Net received amount (THIRD_PARTY only). Mutually exclusive with debitAmount. |
feeBearer (New, top-level): CUSTOMER or PARTNER. Echoed from request.withPoints and withoutPoints, pre-production):| Old Name | New Name |
|---|---|
totalAmount | debitAmount |
| amountType | Meaning of amount | Account is debited | Payee receives |
|---|---|---|---|
| 1 = Debit | Gross debit amount (including fees) | amount | amount - feeAmount |
| 2 = Receive | Net received amount (excluding fees) | amount + feeAmount | amount |
debitAmount = receivedAmount + feeAmount always holds, regardless of feeBearer. The feeBearer only determines whose account the fee portion is deducted from.| feeBearer | Fee deducted from | Effect |
|---|---|---|
| 1 = Customer (default) | Trading party participant account | Full debitAmount from trading party account |
| 2 = Partner | Platform partner participant account (fee portion only) | feeAmount portion from partner account; remaining from trading party account |
X-API-Key header.| Code | Type | Schema |
|---|---|---|
| 400 | BadRequest | {"code": "INVALID_REQUEST", "message": "...", "data": null} |
| 401 | Unauthorized | {"code": "UNAUTHORIZED", "message": "Invalid or missing API key"} |
| 404 | NotFound | {"code": "NOT_FOUND", "message": "Resource not found"} |
| 500 | InternalServerError | {"code": "INTERNAL_ERROR", "message": "An unexpected error occurred"} |
OPENING → AWAITING_PAYMENT → RECEIVED → SUCCEEDED → SETTLED
↓ ↓\n EXPIRED CLOSEDINITIATED → PROCESSING → COMPLETED
↓\n REJECTED
↓\n CLOSED| Type | Use Case | Endpoint |
|---|---|---|
REFUND | Standard post-settlement refund | /refunds/refund |
RISK_REFUND | KYT-triggered risk refund | /refunds/risk-refund |
VOID | Pre-settlement void (overpayment, incomplete order, wrong currency) | /refunds/void |
amountType is absent.amountType in Create Withdrawal requests. This is mandatory for new integrations.amountType to make amount semantics explicit in your integration. The fallback logic preserves your current behavior, but explicit declaration improves auditability.totalAmount → debitAmount and receiveAmount → receivedAmount renames are pre-production; no migration needed.fees or estimatedAmountReceivable, you may optionally switch to feeAmount and receivedAmount. Both sets are returned during the transition period.| Context | Old Field | New Field | Status |
|---|---|---|---|
| Request (Create Withdrawal) | amount (ambiguous) | amount + amountType | Old format still accepted |
| Response | fees | feeAmount | Alias (both returned) |
| Response | estimatedAmountReceivable | receivedAmount | Alias (both returned) |
| Fee Estimate request | totalAmount | debitAmount | Renamed (pre-production) |
| Fee Estimate request | receiveAmount | receivedAmount | Renamed (pre-production) |
| Fee Estimate response | totalAmount | debitAmount | Renamed (pre-production) |
| Field | APIs Where Added | Type | Notes |
|---|---|---|---|
acceptableCryptos | Create Checkout response; GET /cryptos response | array | Acceptable crypto+blockchain pairs |
refundableItem / voidableItems / riskRefundableItems | GET /refundable-info response | object/array/null | Refundability breakdown |
valid / failureCode | POST /addresses/validate response | boolean/string | Address validation result |
| Field | APIs Where Added | Type | Enum |
|---|---|---|---|
amountType | Create Crypto/Fiat Withdrawal (request), All queries & webhooks (response) | integer | 1=Debit, 2=Receive |
feeBearer | Create Crypto/Fiat Withdrawal, Fee Estimate (request), All queries & webhooks (response) | integer (withdrawal) / string (feeEstimate) | 1/CUSTOMER, 2/PARTNER |
debitAmount | All query & webhook responses | string | — |
feeAmount | Fiat query & webhook responses | string | — |
feeCurrency | Fiat query & webhook responses | string | — |
receivedAmount | All query & webhook responses | string | — |
| Status | Count | Note |
|---|---|---|
| New APIs | 2 | Merchant Activation (Non-FI partners) |
| Deleted APIs | 0 | — |
| Modified APIs | 3 | Merchant — activationStatus added (field-level) |
Breaking change: No. Existing integrations remain compatible — the two activation endpoints are additive; activationStatusis an additive field on existing merchant responses/payloads; request bodies of existing endpoints are unchanged.
| FI Partner | Non-FI Partner | |
|---|---|---|
| After creating a merchant | Ready to use | Activation required |
| Calling activation endpoints | Returns 400, not needed | Normal |
internalTransfer | ✅ Available | ❌ Not available |
activationStatus value | Always NO_NEED_ACTIVATION | Follows the state machine |
Main call chain: createMerchant → getMerchant → initiateActivation → confirmActivation.getTnCis not part of this chain — it is an auxiliary call used to fetch the agreement link, which the partner places on the OTP entry page for the merchant to review.
| Value | Meaning | Fund-write APIs available? |
|---|---|---|
NOT_ACTIVATED | Merchant created, activation not yet started | ❌ |
PENDING_ACTIVATION | OTP sent to merchant email, awaiting confirmation | ❌ |
EXPIRED | OTP expired unused | ❌ |
LOCKED | 5 wrong OTP attempts, locked for 30 min | ❌ |
ACTIVATED | Activated (terminal) | ✅ (except internalTransfer) |
NO_NEED_ACTIVATION | FI-partner merchant (terminal) | ✅ (all) |
createMerchant → getMerchant → initiateActivation → confirmActivation. getTnC is an auxiliary call for displaying the agreement (see the note under A.4.3).POST /v2.0/crm/addressBook/createMerchantactivationStatus = NOT_ACTIVATED. The response does not include activationStatus; query it via Get Merchant.GET /v2.0/crm/addressBook/getMerchantparticipantCode or clientReference.| Field | Description |
|---|---|
merchantStatus | KYC status: 1=PROCESSING, 2=APPROVED, 3=REJECTED |
activationStatus | Activation state, initially NOT_ACTIVATED |
Activation can only be initiated after the merchant's KYC is approved ( merchantStatus = 2).
POST /v2.0/crm/merchant/initiateActivation| Field | Type | Required | Description |
|---|---|---|---|
participantCode | string | Yes | Target merchant |
clientReference | string | No | Idempotency key, ≤100 chars |
{
"code": 200,
"msg": "success",
"data": {
"participantCode": "B0100106",
"activationStatus": "PENDING_ACTIVATION",
"otpSentToMaskedEmail": "j***@e***.com",
"otpExpiresAt": 1768636800000,
"tncId": "N001"
}
}| Response field | Description |
|---|---|
otpSentToMaskedEmail | Masked email the OTP was sent to |
otpExpiresAt | OTP expiry, UNIX timestamp (ms); valid for 10 minutes |
tncId | Agreement code for this activation; used to fetch the agreement link (below) and as acceptedTnC in A.4.4 |
ACTIVATED; re-calling in PENDING_ACTIVATION/EXPIRED → the previous OTP is invalidated and a new one sent.GET /v2.0/tool/getTnC/{tncId}tncId from the response above as the path parameter to fetch the agreement link, then place tncContent (agreement PDF) on the OTP entry page for the merchant to review.{
"code": 200,
"msg": "success",
"data": {
"tncId": "N001",
"name": "Partner_Program_Agreement_EndUser_Authorization",
"version": "V1.0",
"tncContent": "https://.../Partner_Program_Agreement_EndUser_Authorization.pdf",
"effectiveFrom": "2026-07-15"
}
}POST /v2.0/crm/merchant/confirmActivation| Field | Type | Required | Description |
|---|---|---|---|
participantCode | string | Yes | Target merchant |
otp | string | Yes | 6-digit OTP submitted by the merchant |
acceptedTnC | string[] | Yes | Agreement code(s); must match the tncId returned by initiateActivation, e.g. ["N001"] |
{
"code": 200,
"msg": "success",
"data": {
"participantCode": "B0100106",
"activationStatus": "ACTIVATED",
"activatedAt": 1768637100000
}
}ACTIVATED, fund-write APIs are unlocked.activationStatus other than ACTIVATED / NO_NEED_ACTIVATION):| Endpoint | Path | Meaning |
|---|---|---|
| Create Crypto Withdrawal | POST /v2.0/payment/crypto/createCryptoWithdrawal | Crypto withdrawal |
| Create Fiat Withdrawal | POST /v2.0/payment/fiat/createWithdrawal | Fiat withdrawal |
| Activate Same Name Withdrawal | POST /v2.0/payment/fiat/sameNameWithdrawal/activate | Same-name withdrawal activation |
| Create Conversion | POST /v2.0/trade/conversion/createConversion | Conversion |
Internal Transfer (POST /v2.0/payment/account/internalTransfer) is not available to Non-FI partners.GET /v2.0/crm/addressBook/getMerchantdata adds activationStatus (read-only, enum in A.3). Existing merchantStatus and merchantInfo are unchanged.POST /v2.0/crm/addressBook/createMerchantNOT_ACTIVATED with fund operations disabled by default until activated. activationStatus is not returned in this response — query it via Get Merchant.POST /webhooks/merchant-status/v2data adds activationStatus. Activation itself does not trigger this webhook (confirmActivation returns the result synchronously); the webhook continues to fire on existing merchant KYC-status changes, now additionally carrying activationStatus.Impact on existing integrations: Get Merchant and the webhook consumers must tolerate the new field and not reject payloads with unrecognised fields.
| Endpoint | Path | Type |
|---|---|---|
| Create Merchant | POST /v2.0/crm/addressBook/createMerchant | Existing |
| Get Merchant | GET /v2.0/crm/addressBook/getMerchant | Existing (added activationStatus) |
| Initiate Activation | POST /v2.0/crm/merchant/initiateActivation | New |
| Confirm Activation | POST /v2.0/crm/merchant/confirmActivation | New |
| Get TnC | GET /v2.0/tool/getTnC/{tncId} | Existing (auxiliary, for displaying the agreement) |
| Merchant Status Webhook | POST /webhooks/merchant-status/v2 | Existing (added activationStatus) |