Disbursement Order
Process
Description:
- Each request is one disbursement order for one recipient, identified by
ReferenceIdgenerated by CashPlus. Amountmust be exactly equal to the amount registered for that recipient.- Each recipient can have only 1 active order: an order can be called only when the recipient has no order at
Status0, 99, or 200. - One recipient's order does not block another recipient's orders.
- Baokim does not automatically retry when an order fails. For an order at
Status=11withRetryable=true, CashPlus may call a new order (with a newReferenceId) before cutoff. - New orders are accepted only before the 23:50:59 cutoff on day T. After cutoff, undisbursed amounts are automatically settled to the Merchant by Baokim (see Overview).
Immediate response status:
| Status | When | CashPlus Action |
|---|---|---|
| 200 | Realtime order disbursed successfully | Record it. The disbursement result webhook is still sent |
| 99 | Realtime order accepted, no final result yet | Wait for disbursement result webhook or query. Do not issue a new order for this recipient |
| 11 | Realtime order failed, funds not sent | Check Retryable and ErrorCode |
| 0 | T+1 order accepted, waiting for disbursement in the settlement period | Wait for disbursement result webhook |
API Information
Method: POST
URL: {BASE_URL}/transaction/v2/spend
Header: Signature — RSA-SHA1 signature of raw body (see Security).
Request
Main Parameters
| Field Name | Data Type | Required | Description |
|---|---|---|---|
| RequestId | String | ✅ | Request ID. Maximum 50 characters, only letters, numbers and - |
| RequestTime | Datetime | ✅ | Request time. Format: YYYY-MM-DD HH:mm:ss. Must not differ by more than 5 minutes from Baokim time |
| PartnerCode | String | ✅ | Sub-merchant code of the collection transaction |
| TransactionId | String | ✅ | Baokim collection transaction ID |
| ReferenceId | String | ✅ | CashPlus disbursement order ID, maximum 50 characters, unique. Calling with the same ReferenceId does not create a new order |
| Receiver | Integer | ✅ | Recipient: 1 = User, 2 = Merchant, 3 = CashPlus |
| Type | Integer | ✅ | Disbursement type: 1 = realtime, 2 = T+1. See Type rules |
| Amount | Integer | ✅ | Disbursement amount (VND), exactly equal to the amount registered for Receiver, including disbursement fee |
| Code | String | ✅ (when Receiver = 1) | Code of a User who has been synced |
| AccountNo | String | ✅ (when Receiver = 1) | User receiving account number. Must match the synced account |
| BankNo | String | ✅ (when Receiver = 1) | Receiving bank code. Must match the synced account |
| Memo | String | ❌ | Transfer content. If not provided → use registered Memo |
Type rules
| Receiver | Valid Type |
|---|---|
| 1 (User) | Always 1 |
| 2 (Merchant) | Exactly the registered Merchant.Type |
| 3 (CashPlus) | Always 2 |
Disbursement Fee
Recipient pays the fee: SpendAmount = Amount − FeeAmount.
| Order | Fee |
|---|---|
| Realtime to User | Per realtime fee schedule |
| Realtime to Merchant | Per realtime fee schedule; 0 when the transaction qualifies for the Merchant disbursement fee waiver |
| All T+1 orders | 0 |
Amount insufficient to cover the realtime disbursement fee → 125.
Request Example
{
"RequestId": "CP20250115100501",
"RequestTime": "2025-01-15 10:05:01",
"PartnerCode": "SHOP123",
"TransactionId": "BK6AB9B10B92C04SZ",
"ReferenceId": "CPSPEND0001",
"Receiver": 2,
"Type": 1,
"Amount": 6860,
"Memo": "Thanh toan don hang 1001"
}
Request Example — User disbursement order
{
"RequestId": "CP20250115143001",
"RequestTime": "2025-01-15 14:30:01",
"PartnerCode": "SHOP123",
"TransactionId": "BK6AB9B10B92C04SZ",
"ReferenceId": "CPSPEND0002",
"Receiver": 1,
"Type": 1,
"Amount": 7000,
"Code": "USER001",
"AccountNo": "0123******89",
"BankNo": "970416"
}
Validation Order
Baokim validates sequentially. Upon the first condition not met, returns error and does not create an order.
| Step | Condition | Error if Not Met |
|---|---|---|
| 1 | Valid signature | 120 |
| 2 | Parameters in correct format | 102, 110, 138, … |
| 3 | ReferenceId does not exist for this PartnerCode | Same content: returns ResponseCode=200 + existing order. Different content: 142 |
| 4 | TransactionId exists and belongs to PartnerCode | 112 |
| 5 | Before the 23:50:59 cutoff on day T | 141 |
| 6 | TransactionId has share amounts registered | 133 |
| 7 | Transaction was registered through API v2 | 143 |
| 8 | Recipient has no order at Status 0, 99, or 200 | 134 |
| 9 | For Receiver = 1: no previous User order failed due to a User account error | 119 |
| 10 | Type is valid according to Type rules | 107 |
| 11 | Amount equals the amount registered for the recipient | 136 |
| 12 | For Receiver = 1: account matches the synced account | 103, 104, 111 |
| 13 | Amount > disbursement fee (realtime orders) | 125 |
Response
note
HTTP 200 - Success
Main Parameters
| Field Name | Data Type | Required | Description |
|---|---|---|---|
| ResponseCode | Integer | ✅ | Result of receiving the request. 200 = order created (or already exists) |
| ResponseMessage | String | ✅ | Message |
| Data | Object | ❌ | Disbursement order information. Only present when ResponseCode=200 |
Data
| Field Name | Data Type | Description |
|---|---|---|
| TransactionId | String | Collection transaction ID |
| ReferenceId | String | CashPlus disbursement order ID |
| TransIdPayment | String | Baokim disbursement order ID. Unchanged throughout order lifetime |
| Receiver | Integer | Recipient |
| Type | Integer | Disbursement type |
| Status | Integer | Disbursement order result: 0, 99, 200, 11 (see Error Codes) |
| ErrorCode | String | Detailed error code when Status=11 |
| Retryable | Boolean | Only present when Status=11. true = a new order may be called, false = do not retry |
| RequestAmount | Integer | Requested amount (= Amount) |
| FeeAmount | Integer | Disbursement fee |
| SpendAmount | Integer | Actual amount transferred to recipient |
| Source | String | Always PARTNER for orders called by CashPlus |
Response Example — Realtime order in progress
{
"ResponseCode": 200,
"ResponseMessage": "Success",
"Data": {
"TransactionId": "BK6AB9B10B92C04SZ",
"ReferenceId": "CPSPEND0001",
"TransIdPayment": "TP2501151005010001",
"Receiver": 2,
"Type": 1,
"Status": 99,
"ErrorCode": null,
"RequestAmount": 6860,
"FeeAmount": 0,
"SpendAmount": 6860,
"Source": "PARTNER"
}
}
Response Example — User order failed due to account error
{
"ResponseCode": 200,
"ResponseMessage": "Success",
"Data": {
"TransactionId": "BK6AB9B10B92C04SZ",
"ReferenceId": "CPSPEND0002",
"TransIdPayment": "TP2501151430010002",
"Receiver": 1,
"Type": 1,
"Status": 11,
"ErrorCode": "118",
"Retryable": false,
"RequestAmount": 7000,
"FeeAmount": 2500,
"SpendAmount": 4500,
"Source": "PARTNER"
}
}
Response Example — Wrong amount
{
"ResponseCode": 136,
"ResponseMessage": "Amount must equal the amount registered for the recipient"
}
Timeout Handling
Baokim processes realtime orders synchronously before responding, which can take up to 30 seconds. CashPlus should set the timeout for this API to at least 35 seconds.
If CashPlus does not receive a response (timeout, connection loss):
- Retry with the same
ReferenceIdand the same content (or query byReferenceId). Baokim does not create duplicate orders. - Only use a new
ReferenceIdwhen query returns137(order does not exist) and it is still before cutoff.
Error Codes
| Error Code | Description |
|---|---|
| 200 | Order created or already exists (see Data.Status) |
| 101 | Error during Baokim processing. Retry with the same ReferenceId |
| 102 | RequestId or RequestTime is invalid (wrong format or time difference exceeds 5 minutes) |
| 103 | User Code is invalid (not synced) |
| 104 | User account number does not match the synced account |
| 107 | Type is invalid |
| 110 | Partner Code is invalid |
| 111 | User bank code does not match the synced account |
| 112 | Transaction ID is invalid |
| 119 | A previous User order failed due to a User account error; do not retry |
| 120 | Signature is invalid |
| 125 | Amount insufficient to cover disbursement fee |
| 133 | Share amounts not registered |
| 134 | Recipient has an active order (Status 0, 99, or 200) |
| 136 | Amount differs from the amount registered for the recipient |
| 138 | ReferenceId is invalid |
| 141 | Past the 23:50:59 cutoff of the transaction day |
| 142 | ReferenceId already used for an order with different content |
| 143 | Transaction was registered through API v1 |
Detailed order error codes (ErrorCode when Status=11): see Error Codes.