Skip to main content

Create payment order

POST
URLhttps://open-api.tingee.vn/v1/direct-link/create-transfer

Create a disbursement payment order using the Maker/Checker model (BIDV only)

Header Request​

HeaderRequiredDescription
Content-Type✓application/json
x-client-id✓Partner identifier issued by TINGEE.
x-signature✓HMAC SHA512 authentication signature.
x-request-timestamp✓Time the request is sent (format: yyyyMMddHHmmssSSS, UTC+7)

Body Parameter​

💡 How transaction parameters are applied (Global vs Record-level)

The system accepts parameters at two levels to streamline creating single and batch disbursement orders:

  • Global level: Fields such as transactionType, feeMethod, effectiveDate and creditAccountType, when passed at the top level of the payload, act as default values for all transactions in the `records` list.
  • Record level: If these fields are set for an individual item in the `records` array, the system uses that value instead, overriding the global default.
FieldTypeRequiredDescription
bankBinstring✓Bank BIN. Always pass 970418 (BIDV's BIN)
actionstring✓Action performed by the maker of the disbursement order
- REQUEST_APPROVAL: Save and submit the disbursement transaction for approval immediately
- INIT: Save the disbursement transaction as a draft to submit for approval later
actionTypestring✓Purpose of the disbursement order
- INTERNAL_TRANSFER: Domestic transfer
- SALARY: Salary payment
- BILL_PAYMENT: Bill / statement payment
debitAccountNumberstring✓Payment (debit) account number
debitAccountNamestring✕Payment account holder name (for reference only, not sent to BIDV).
transactionTypestring~Transaction type (global)
- in-bank : Within the bank
- fast-out: NAPAS 247 fast transfer
- regular-out: Standard interbank transfer
Required if not passed at the record level.
feeMethodstring~Fee method (global)
- O : The payment account pays the fee
- B: The receiving account pays the fee
Required, except for INTERNAL_TRANSFER batch orders (records has more than 1 item) — in that case you can pass it per record via records[].feeMethod (default O).
For SALARY / BILL_PAYMENT, only this global value is used.
effectiveDatestring~Posting date of the transaction at the bank (format: yyyy-MM-dd) (global)
Required when action = REQUEST_APPROVAL and actionType is not INTERNAL_TRANSFER.
remarkstring~Transfer description / general description of the batch (used for SALARY / BILL_PAYMENT; for INTERNAL_TRANSFER the system uses records[].remark).
Required when action = REQUEST_APPROVAL and actionType is not INTERNAL_TRANSFER.
approvalNotestring✕Note from the maker sent along when submitting for approval (action = REQUEST_APPROVAL).
Currently only applies to SALARY / BILL_PAYMENT.
currencystring✕Posting currency of the payment account (default: VND)
creditAccountTypestring✕How the recipient receives the money (global), used when a record does not pass records[].creditAccountType:
- ACCOUNT: Receive to an account number
- ID: Receive in cash at the counter with an identity document
recordsarray✓List of transaction records to create
- Single order: array with 1 item
- Batch order: array with n items (INTERNAL_TRANSFER: up to 500 items)

Items in records​

FieldTypeRequiredDescription
requestIdstring✓Transaction reference generated by the partner, used to match results (returned in the originId field when querying). Must be unique per transaction.
Up to 50 characters (batch orders: up to 30 characters per BIDV rules).
creditAccountNumberstring✓Recipient account number.
creditAccountTypestring✕How the recipient receives the money:
- ACCOUNT: Receive to an account number (default)
- ID: Receive in cash at the counter with an identity document
If omitted, the global creditAccountType value is used.
creditIdstring~Recipient identity document number (ID card / citizen ID / passport)
Required when creditAccountType = ID.
creditIssueDatestring~Identity document issue date (format: yyyy-MM-dd)
Required when creditAccountType = ID.
creditIssueAddressstring~Identity document place of issue
Required when creditAccountType = ID.
creditBranchCodestring~Recipient bank branch code
Required when creditAccountType = ID.
creditAccountNamestring✓Recipient account holder name
(without diacritics, in UPPERCASE, up to 70 characters)
amountnumber✓Transaction amount (minimum 2,000 VND).
creditBankBinstring✓Recipient bank BIN. See Supported banks.
remarkstring✓Transfer description / transaction details.
creditCurrencystring✕Currency of the recipient account (default: VND)
transactionTypestring~Transaction type (per record)
- in-bank: Within the bank
- fast-out: NAPAS 247 fast transfer
- regular-out: Standard interbank transfer
If passed, it takes precedence (overrides the global value). Required if not set at the global level.
Note: for a single INTERNAL_TRANSFER order, if it is passed at both levels the system uses the global value.
effectiveDatestring~Transaction posting date (per record)
Format: yyyy-MM-dd.
If passed, it takes precedence (overrides the global value).
feeMethodstring✕Fee method (per record, INTERNAL_TRANSFER only)
- O: The payment account pays the fee
- B: The receiving account pays the fee
If passed, it takes precedence (overrides the global value); if neither level passes it, the default is O.

Sample Request Payload​

To match the 4 scenarios in the Response section, below are the corresponding payloads you need to send (they differ only in the action field and the records array). Click any tab below — all the Code samples and Sample Response sections further down sync automatically to the scenario you pick!

{
"actionType": "INTERNAL_TRANSFER",
"transactionType": "in-bank",
"action": "INIT",
"bankBin": "970418",
"debitAccountNumber": "8600007007",
"currency": "VND",
"feeMethod": "O",
"effectiveDate": "2026-06-04",
"records": [
{
"requestId": "TRANS_1006_A04",
"creditAccountType": "ACCOUNT",
"creditAccountNumber": "2220366666",
"creditAccountName": "NGUYEN VAN A",
"amount": 32987,
"creditBankBin": "970418",
"remark": "Chuyen tien"
}
]
}

Code samples​

curl --location --request POST 'https://open-api.tingee.vn/v1/direct-link/create-transfer' \
--header 'accept: application/json' \
--header 'x-client-id: YOUR_CLIENT_ID' \
--header 'x-request-timestamp: 20240509154004003' \
--header 'x-signature: YOUR_SIGNATURE' \
--header 'Content-Type: application/json' \
--data '{
"actionType": "INTERNAL_TRANSFER",
"action": "INIT",
"bankBin": "970418",
"debitAccountNumber": "8600007007",
"currency": "VND",
"feeMethod": "O",
"effectiveDate": "2026-06-04",
"records": [
{
"requestId": "TRANS_1006_A04",
"creditAccountType": "ACCOUNT",
"creditAccountNumber": "2220366666",
"creditAccountName": "NGUYEN VAN A",
"amount": 32987,
"creditBankBin": "970418",
"remark": "Chuyen tien"
}
]
}'

Sample Response​

Depending on the action parameter (save as draft or submit for approval) and the number of transactions (single or batch), the API returns the structure for one of the 4 cases below:

Response when saving a draft (action="INIT") for a single transaction.

{
"code": "00",
"message": "Success",
"data": {
"status": "SUCCESS",
"totalRecords": 1,
"validRecords": 1,
"invalidRecords": 0,
"requireAuth": false,
"transAuth": null,
"records": [
{
"requestId": "TRANS_1006_A04",
"status": "INIT",
"transactionId": "PM0226061000074420",
"transactionCode": "PM02",
"message": null,
"feeTotal": 11000
}
]
}
}

Response data structure​

FieldTypeDescription
statusstringDisbursement order status:
- SUCCESS: Draft saved successfully (action = INIT)
- PENDING_CONFIRMATION: Approval request created, awaiting OTP confirmation via the Confirm payment order API with confirmId
- PARTIALLY_VALID: Draft saved successfully but the batch contains invalid records (SALARY / BILL_PAYMENT only)
- REQUIRES_CONFIRMATION: BIDV returned a warning that must be confirmed before continuing (SALARY / BILL_PAYMENT only); the warning text is in message. Resend exactly the same payload within 5 minutes to confirm and continue creating the order.
messagestringWarning text from BIDV (only returned when status = REQUIRES_CONFIRMATION).
batchIdstringTransaction batch ID (only returned when creating an INTERNAL_TRANSFER batch order or a SALARY / BILL_PAYMENT order). Used for the Download batch result file API and BATCH_UPLOAD_INQUIRY queries.
confirmIdstringTransaction confirmation key (only returned when submitting for approval with REQUEST_APPROVAL).
transactionIdstringBatch-level transaction ID (SALARY / BILL_PAYMENT only) — used for the submit-for-approval, approve, reject, delete and detail inquiry APIs.
transactionCodestringBank-side transaction type code (SALARY / BILL_PAYMENT only).
totalRecordsnumberTotal number of transactions.
validRecordsnumberNumber of valid transactions.
invalidRecordsnumberNumber of invalid transactions.
requireAuthbooleanWhether additional transaction authentication is required (e.g. SmartOTP) (INTERNAL_TRANSFER only).
transAuthobjectAuthentication configuration (set when additional authentication is needed, otherwise null).
recordsarrayDetailed result of each transaction (for a batch order submitted with REQUEST_APPROVAL, this array is empty because the individual child orders have no processing result yet).
Batch with invalid records

For INTERNAL_TRANSFER batch orders and SALARY / BILL_PAYMENT orders, if BIDV checks the batch file and finds invalid records, the API returns code = "400" with data containing batchId, validRecords and invalidRecords. Use Query transactions with inquiryType = BATCH_UPLOAD_INQUIRY, the matching batchId and status = INVALID to see the error for each record.

data.transAuth details (if additional authentication is required)​

FieldTypeDescription
authTypestringAuthentication method (e.g. SMARTOTP).
expTimenumberValidity period of the QR code (in seconds).
qrDatastringData string used to render the QR code image. Scan it in the bank app to get the OTP.

Items in data.records​

FieldTypeDescription
requestIdstringThe transaction reference you sent.
statusstringTransaction status returned by BIDV; by default INIT (draft) or REQUEST_APPROVAL (submitted for approval).
transactionIdstringTransaction ID in the BIDV system (INTERNAL_TRANSFER only) — used for the submit-for-approval, approve, reject, delete and TRANSFER_DETAIL inquiry APIs (the id field).
transactionSubIdstringChild transaction ID within the batch (SALARY / BILL_PAYMENT only).
transactionCodestringBank-side transaction type code (INTERNAL_TRANSFER only).
messagestringError message (if any).
feeTotalnumberTotal transaction fee.
SmartOTP authentication guide (BIDV approval submission)

When you submit transactions for approval and the system returns requireAuth: true along with transAuth.qrData, follow these steps to get the OTP:

  1. Convert the string in qrData into a QR code image.
  2. Open the BIDV Direct app on a device (that has been granted approval rights).
  3. Use the app's QR scanner to scan the QR image you just generated.
  4. Carefully check the transaction details on the app screen and confirm with your BIDV Direct PIN.
  5. After you confirm the PIN, a SmartOTP is displayed on the screen.
  6. Pass this SmartOTP in the otp parameter of the Confirm transfer order API to complete the transaction.

Common error codes​

CodeDescriptionHow to handle
1112The transaction list (records) is emptyPass at least one record in records, then resend.
1077The BIDV authorization session of the maker (Maker) has expired or has not been grantedCall Get authorization URL with role = Maker to re-authorize, then create the transaction again.
1021The bank is not supported for the Maker/Checker flowCheck bankBin; the Maker/Checker flow applies to BIDV (970418).
90, 91, 92, 97Request authentication error (timestamp, client-id, signature)See System error codes.
OthersOther errorsSee Error codes.