Virtual Accounts Create API


The following endpoint creates a new virtual account

/payments/va

Request parameters

Following are the parameters to be sent in the request body:

Fieldis required?Description
bank_codemandatoryType: string

The bank code for the Virtual Account

Supported Bank Codes: "BRI", "BCA", "MANDIRI", "PERMATA", "CIMB"
namemandatoryType: string

The name of virtual account

Example: "John's Virtual Account"
is_closedoptionalType: boolean (default: false)

Whether account can accept open(any amount) or closed(specific amount)

Example: true or false
amountoptionalType: string

Specify amount to be paid to va when is_closed=true

Example: "12000.12"
customermandatoryType: object

Object containing fields (id, email, mobile, given_name). One of (id, mobile, email) is mandatory field and given_name is mandatory.

Example: { "given_name": "Ardi Hanan", "mobile": "+6288888888", "email": "ardi@gmail.com" }
expiry_minutesoptionalType: integer (default for is_reusable=true:1440 and is_reusable=false:15768000)

Number of minutes left till expiry from now maximum(15768000)

Example: 10000
account_suffixoptionalType: string (default: random)

Account suffix for the VA, if not specified a random suffix will be used to generate account_number

Example: "1234"
is_reusableoptionalType: boolean (default: true)

Whether multiple payments can be used for a particular VA

Example: true or false
min_amountoptionalType: number (default: nil)

Minimum amount to be paid to a VA in the case of is_closed=false

Example: 10000
max_amountoptionalType: number (default: nil)

Maximum amount which can be paid to a VA in the case of is_closed=false

Example: 20000
va_ref_idoptionalType: string (default: "")

A reference ID which the merchant wants to use for a specific VA

Example: "VA_XYZ_1234"
auto_disable_after_paymentoptionalType: boolean (default: false)

Disable a reusable VA temporariliy after a payment. Patch API can be used to enable it again after changing some parameters

Example: true or false

The following table has the maximum account_suffix lengths for each bank:

Bank CodeMax Length
MANDIRI7
BCA14
BRI9
PERMATA8
CIMB8

Error Codes

CodeDescription
DPAY_STATIC_VA_NOT_SUPPORTEDstatic va not supported
DPAY_STATIC_CLOSED_VA_NOT_SUPPORTEDstatic va (closed) not supported
DPAY_DYNAMIC_OPEN_VA_NOT_SUPPORTEDdynamic va (open) not supported
DPAY_MIN_MAX_AMOUNT_NOT_SUPPORTEDsetting min_amount and max_amount not supported
DPAY_STATIC_VA_EXPIRY_MINUTES_NOT_SUPPORTEDstatic va (expiry_minutes) not supported
DPAY_STATIC_VA_AUTO_DISABLING_VA_NOT_SUPPORTEDstatic va: auto disabling va not supported
DPAY_INTERNAL_ERRORan unclassified error
DPAY_INVALID_REQUESTan error in form fields
DPAY_UNAUTHORIZED_ACCESSan unauthorized access error

Sample Request

curl --location --request POST 'https://api.durianpay.id/v1/payments/va' \
--header 'Authorization: [Base64({Your_Server_Key}:)]' \
--header 'Content-Type: application/json' \
--data-raw '{
    "bank_code": "PERMATA",
    "name": "Ardi Hanan Durian",
    "is_closed": true,
    "amount": "12333",
    "customer": {
        "given_name": "Ardi Hanan",
        "mobile": "+6288888888",
        "email": "ardi@gmail.com"
    },
    "expiry_minutes": 14400,
    "account_suffix": "123456",
    "is_reusable": true,
    "va_ref_id": "1234",
    "min_amount": 10000,
    "max_amount": 15000,
    "auto_disable_after_payment": true
}'

Sample Response

The status code returned would be 201.

{
    "data": {
        "customer_id": "cus_CtZ8r2GOvq7341",
        "virtual_account": {
            "id": "va_sample_pWM5k3BUI63935",
            "bank_code": "PERMATA",
            "account_number": "88565004123456",
            "name": "Ardi Hanan Durian",
            "is_closed": true,
            "amount": 12333,
            "currency": "IDR",
            "customer_id": "cus_CtZ8r2GOvq7341",
            "is_sandbox": true,
            "created_at": "2022-06-28T10:38:54.350418Z",
            "expiry_at": "2022-07-08T05:08:54.353053Z",
            "metadata": {},
            "is_disabled": false,
            "is_paid": false,
            "is_reusable": true,
            "min_amount": null,
            "max_amount": null,
            "va_ref_id": "1234",
            "auto_disable_after_payment": true
        }
    }
}

Sample Error

Form Errors

Form errors are those which occur during form validation & contain an errors array and are thrown with status code 400.

{
    "error_code": "DPAY_INVALID_REQUEST",
    "request_id": "dp_JSN8xJULZ39583",
    "errors": [
        {
            "field": "bank_code",
            "message": "can't be blank"
        },
        {
            "field": "name",
            "message": "can't be blank"
        },
        {
            "field": "customer",
            "message": "can't be blank needs either ID, Email or Mobile"
        },
        {
            "field": "customer.given_name",
            "message": "given name cannot be empty"
        },
        {
            "field": "expiry_minutes",
            "message": "can't be less than equal to 0"
        }
    ]
}

Authorization Errors

Authorization errors are errors that occur during authorization. The status code returned is usually 401

{
    "error": "invalid Authorization header in request",
    "error_code": "DPAY_UNAUTHORIZED_ACCESS"
}

Other Errors

Other errors are failures which occur after form validation. The status codes codes are usually 400 & 500

{
    "error": "pq: VA Already Created",
    "error_code": "DPAY_INTERNAL_ERROR",
    "request_id": "dp_QMPB7IO53p6517"
}