Disbursement to Bank
Disbursement to Bank enables direct fund transfers from DANA to users' bank accounts. This API lets you validate bank details, transfer funds, receive status updates, and check transfer statuses. It offers a secure, automated disbursement process that reduces manual work and improves efficiency.
Disbursement is also available for top up to DANA Balance. Check our Disbursement Overview for more details
Before you start
You will need to register your business in our Merchant Portal to obtain your testing credentials. After you have created your test account, make sure you have done the following:
- Finish your company registration and select Disbursement to Bank as your payment solution.
- Merchant Disbursement Account (MDA) will be automatically created for you to store your balance. For sandbox testing, contact the DANA team to top up your account. In production, simply top up via the Virtual Account (VA) displayed in Merchant Portal.
- Setup your webhooks & redirect URLs to receive payment outcomes & redirect user after payment.
- Obtain your testing credentials from the merchant portal.
Process Flow
The general flow of payment using the Disbursement to Bank is as follows:
Visit the Disbursement API Overview for edge cases and other scenarios.

- Merchant calls DANA's Check Disbursement Account API to verify their current account balance before processing any bank transfers.
- DANA processes the request and returns the merchant's current balance information, ensuring sufficient funds are available for the intended disbursement.
- Merchant receives a transfer request from a user who wants to transfer funds to their bank account.
- Merchant calls DANA's Transfer to Bank Account Inquiry API to validate the recipient's bank account details before initiating the transfer.
- DANA forwards the account inquiry request to the destination bank to verify the account information and availability.
- Bank processes the inquiry and returns the account validation results to DANA, confirming whether the account is valid and can receive transfers.
- DANA returns the bank account inquiry results to merchant, providing confirmation of account validity and transfer eligibility.
- Merchant calls DANA's Transfer to Bank API to initiate fund transfer to the validated bank account.
- DANA processes the transfer request by validating the account information to Bank and deducting the specified amount from the merchant's balance.
- DANA sends the transfer request to the destination bank, initiating the fund transfer process.
- Bank processes the transfer by crediting amount to the user's beneficiary bank account.
- DANA returns transfer result to the merchant, confirming that the transfer request has been successfully submitted.
- If merchant has enabled notifications (needNotify ==
true
), DANA sends an additional status update indicating "Request in Progress (2024300)" to keep the merchant informed of the transfer processing status - Bank sends the final transfer status result to DANA, confirming whether the transfer was successfully completed or failed.
- DANA calls merchant's Transfer to Bank Notify API webhook endpoint to deliver the final transfer result, providing complete transaction status and details.
- NodeJS
- Python
- Go
- PHP
Step 1 : Library Installation
Visit our Libraries & Plugins guide for detailed information on our SDK.
DANA provides server-side API libraries for several programming languages, available through common package managers, for easier installation and version management. Follow the guide below to install our library:
Requirements
- Node.js version 18 or later
- Your testing credentials from the merchant portal.
Installation
Install using npm or visit our Githubnpm install dana-node@latest --save
Set up the env
PRIVATE_KEY or PRIVATE_KEY_PATH # Your private key
ORIGIN # Your application's origin URL
X_PARTNER_ID # clientId provided during onboarding
ENV # DANA's environment either 'sandbox' or 'production'
Obtaining merchant credentials: Authentication
Step 2 : Initialize the library
Visit our Authentication guide to learn about the authentication process when not using our Library.
Follow the guide below to initialize the library
import { Dana } from 'dana-node';
const danaClient = new Dana({
partnerId: "YOUR_PARTNER_ID", // process.env.X_PARTNER_ID
privateKey: "YOUR_PRIVATE_KEY", // process.env.X_PRIVATE_KEY
origin: "YOUR_ORIGIN", // process.env.ORIGIN
env: "sandbox", // process.env.DANA_ENV or process.env.ENV or "sandbox" or "production"
});
const { disbursementApi } = danaClient;
Step 3 : Check Your Merchant Balance
Before processing any bank transfer, call DANA's Check Disbursement Account API to verify that your merchant deposit account has sufficient funds. DANA will return your current available balance so you can confirm you have enough money for the transfer amount. If your balance is insufficient, top up your account balance via the Virtual Account (VA) displayed in Merchant Portal.
import { Dana } from 'dana-node';
import { QueryMerchantResourceRequest, QueryMerchantResourceResponse } from 'dana-node/merchant_management/v1';
const danaClient = new Dana({
partnerId: "YOUR_PARTNER_ID", // process.env.X_PARTNER_ID
privateKey: "YOUR_PRIVATE_KEY", // process.env.X_PRIVATE_KEY
origin: "YOUR_ORIGIN", // process.env.ORIGIN
env: "sandbox", // process.env.DANA_ENV or process.env.ENV or "sandbox" or "production"
});
const { merchantManagementApi } = danaClient;
const request: QueryMerchantResourceRequest = {
// Define the request parameters for the API call here
};
const response: QueryMerchantResourceResponse = await merchantManagementApi.queryMerchantResource(request);
Step 4 : Validate User's Bank Account
When a user wants to transfer money to their bank account, call DANA's Transfer to Bank Account Inquiry API to validate their bank account details before initiating the actual transfer. You'll need to provide the customerNumber, beneficiaryAccountNumber, amount, additionalInfo.fundType, and additionalInfo.beneficiaryBankCode. DANA will forward this inquiry to the destination bank, which will verify the account and return by providing the detail account information.
import { Dana } from 'dana-node';
import { BankAccountInquiryRequest, BankAccountInquiryResponse } from 'dana-node/disbursement/v1';
// .. initialize client with authentication
const request: BankAccountInquiryRequest = {
// Fill in required fields here, refer to Transfer to Bank Account Inquiry API Detail
};
const response: BankAccountInquiryResponse = await disbursementApi.bankAccountInquiry(request);;
Step 5 : Execute the Bank Transfer
Call DANA's Transfer to Bank API to process the actual fund transfer from your merchant account to the user's bank account, this process starting by validating again the user’s bank account. DANA will validate your request, deduct the funds from your merchant balance, and initiate the transfer to the user’s destination bank. The bank will then process the transfer and credit the amount to the user's account. You'll receive an response confirming the transfer submission (not completion).
import { Dana } from 'dana-node';
import { TransferToBankRequest, TransferToBankResponse } from 'dana-node/disbursement/v1';
// .. initialize client with authentication
const request: TransferToBankRequest = {
// Fill in required fields here, refer to Transfer to Bank API Detail
};
const response: TransferToBankResponse = await disbursementApi.transferToBank(request);
Set additionalInfo.needNotify = true
to receive notifications when the bank transfer request is in progress
Step 6 : Receive Transfer Status Updates
After bank processing completes, DANA sends transfer status notifications to your configured endpoint via the Transfer to Bank Notify API. Your notification URL must follow the ASPI-mandated format: /v1.0/debit/emoney/transfer-bank/notify.htm.
Example of a successful payment webhook payload:
Content-type: application/json
X-TIMESTAMP: 2020-12-21T17:50:44+07:00
{
"responseCode": "2004300",
"responseMessage": "Successful",
}
Optional Check Transfer Status Manually
If you don't receive result from Transfer to Bank API within the expected timeframe or if your transfer API call times out, use the Transfer to Bank Inquiry Status API to manually check the transfer status. You'll need your originalPartnerReferenceNo and serviceCode.
import { Dana } from 'dana-node';
import { TransferToBankInquiryStatusRequest, TransferToBankInquiryStatusResponse } from 'dana-node/disbursement/v1';
// .. initialize client with authentication
const request: TransferToBankInquiryStatusRequest = {
// Fill in required fields here, refer to Transfer to Bank Inquiry Status API Detail
};
const response: TransferToBankInquiryStatusResponse = await disbursementApi.transferToBankInquiryStatus(request);
For detailed retry procedure, see Retry Mechanism section.
Additional Enum Configuration
The library provides several enums (enumerations) to represent a fixed set of constant values, ensuring consistency and reducing errors during integration.
import { DanaAccountInquiryRequestAdditionalInfoChargeTargetEnum } from 'dana-node/disbursement/v1';
// Use the enum value
const chargeTarget = DanaAccountInquiryRequestAdditionalInfoChargeTargetEnum.Division;
The following enums are available in the Library Disbursement:
- ChargeTarget
- LatestTransactionStatus
Step 7 : Test using our automated test suite
Visit our Scenario Testing guide for detailed information on testing requirements.
We are required by local regulators to ensure your integration works correctly across all critical use cases. Use our sandbox environment and Merchant Portal to safely conduct UAT testing on a list of mandatory testing scenarios.
To complete our mandatory testing requirements, follow these steps:
- Access your Integration Checklist page inside the Merchant Portal
- Complete all the mandatory testing scenarios provided
- Download your verified API Logs using the Download Verification Proof button
- Complete your Go Live Submission checklist
- Submit your verified API logs on your Production Submission form
UAT Testing Script
Use our specialized UAT testing suite to save days of debugging.
To speed up your integration, we have provided an automated test suite. It takes under 15 minutes to run your integration against our test scenarios. Check out the Github repo for more instructions
Step 8 : Submit testing documents & apply for production
As part of regulatory compliance, merchants are required to submit UAT testing documents to meet Bank Indonesia's requirements. After completing sandbox testing, follow these steps to move to production:
Generate production keys
Create your production private and public keys, follow this instruction: Authentication - Production Credential.Complete your UAT testing checklist
Confirm that you have completed all testing scenarios from our Merchant Portal.Fill out your Production Submission form
Follow the instructions inside our Merchant Portal to apply for production credentials. We will process your application in 1-2 days.Obtain production credentials
Once approved, you will receive your production credentials such as: Merchant ID, Client ID known as X-PARTNER-ID, and Client Secret.
Testing in production environment
Configure production environment
Switch your application settings from sandbox to production environment by updating the API endpoints and credentials.Test using production credentials
Conduct the same testing scenarios as sandbox testing, using your production credentials.UAT production sign-off
Once testing is complete, DANA will prepare the UAT Production Sign Off document in the Merchant Portal. Both merchant and DANA representatives must sign this document to formally approve the integration.Receive live payments
After receiving all approvals, your DANA integration will be activated and ready for live payments from your customers.
Ready to submit testing documents?
Access our merchant portal for detailed guide to start receiving live payments
Step 1 : Library Installation
Visit our Libraries & Plugins guide for detailed information on our SDK.
DANA provides server-side API libraries for several programming languages, available through common package managers, for easier installation and version management. Follow the guide below to install our library:
Requirements
- Python 3.9.1+
- Your testing credentials from the merchant portal.
Installation
Install using pip or visit our Githubpip install dana-python
Set up the env
PRIVATE_KEY or PRIVATE_KEY_PATH # Your private key
ORIGIN # Your application's origin URL
X_PARTNER_ID # clientId provided during onboarding
ENV # DANA's environment either 'sandbox' or 'production'
Obtaining merchant credentials: Authentication
Import Package
import dana.disbursement.v1
Step 2 : Initialize the library
Visit our Authentication guide to learn about the authentication process when not using our Library.
Follow the guide below to initialize the library
import os
from dana.utils.snap_configuration import SnapConfiguration, AuthSettings, Env
configuration = SnapConfiguration(
api_key=AuthSettings(
PRIVATE_KEY=os.environ.get("PRIVATE_KEY"), # obtained from Merchant Portal
ORIGIN=os.environ.get("ORIGIN"), # Origin domain
X_PARTNER_ID=os.environ.get("X_PARTNER_ID"), # known as clientId
ENV=Env.SANDBOX # environment either 'sandbox' or 'production'
)
)
Step 3 : Check Your Merchant Balance
Before processing any bank transfer, call DANA's Check Disbursement Account API to verify that your merchant deposit account has sufficient funds. DANA will return your current available balance so you can confirm you have enough money for the transfer amount. If your balance is insufficient, top up your account balance via the Virtual Account (VA) displayed in Merchant Portal.
import os
from dana.utils.snap_configuration import SnapConfiguration, AuthSettings, Env
from dana.merchant_management.v1 import MerchantManagementApi
from dana.merchant_management.v1.models.QueryMerchantResourceRequest import QueryMerchantResourceRequest
from dana.api_client import ApiClient
from dana.rest import ApiException
from pprint import pprint
# configuration and ApiClient object can be used for multiple operations
# They should be singleton through the application lifecycle
configuration = SnapConfiguration(
api_key=AuthSettings(
PRIVATE_KEY=os.environ.get("PRIVATE_KEY"), # or you can set PRIVATE_KEY_PATH
ORIGIN=os.environ.get("ORIGIN"),
X_PARTNER_ID=os.environ.get("X_PARTNER_ID"),
DANA_ENV=os.environ.get("DANA_ENV"), # or you can set ENV
CLIENT_SECRET=os.environ.get("CLIENT_SECRET"),
)
)
# Configure API key authorization: CLIENT_SECRET
# For OPEN_API type, we use CLIENT_SECRET authentication
configuration = OpenApiConfiguration(
api_key=OpenApiAuthSettings(
CLIENT_SECRET=os.environ.get("CLIENT_SECRET"),
CLIENT_ID=os.environ.get("CLIENT_ID"),
DANA_ENV=os.environ.get("DANA_ENV"),
ENV=os.environ.get("ENV")
)
)
with ApiClient(configuration) as api_client:
api_instance = MerchantManagementApi(api_client)
query_merchant_resource_request = QueryMerchantResourceRequest()
try:
api_response = api_instance.query_merchant_resource(query_merchant_resource_request)
print("The response of MerchantManagementApi->query_merchant_resource:\n")
pprint(api_response)
except Exception as e:
print("Exception when calling MerchantManagementApi->query_merchant_resource: %s\n" % e)
Step 4 : Validate User's Bank Account
When a user wants to transfer money to their bank account, call DANA's Transfer to Bank Account Inquiry API to validate their bank account details before initiating the actual transfer. You'll need to provide the customerNumber, beneficiaryAccountNumber, amount, additionalInfo.fundType, and additionalInfo.beneficiaryBankCode. DANA will forward this inquiry to the destination bank, which will verify the account and return by providing the detail account information.
import os
from dana.utils.snap_configuration import SnapConfiguration, AuthSettings, Env
from dana.disbursement.v1 import DisbursementApi
from dana.disbursement.v1.models.BankAccountInquiryRequest import BankAccountInquiryRequest
from dana.api_client import ApiClient
from dana.rest import ApiException
from pprint import pprint
# configuration and ApiClient object can be used for multiple operations
# They should be singleton through the application lifecycle
configuration = SnapConfiguration(
// .. initialize client with authentication
)
)
with ApiClient(configuration) as api_client:
api_instance = DisbursementApi(api_client)
bank_account_inquiry_request = BankAccountInquiryRequest()
try:
api_response = api_instance.bank_account_inquiry(bank_account_inquiry_request)
print("The response of DisbursementApi->bank_account_inquiry:\n")
pprint(api_response)
except Exception as e:
print("Exception when calling DisbursementApi->bank_account_inquiry: %s\n" % e)
Step 5 : Execute the Bank Transfer
Call DANA's Transfer to Bank API to process the actual fund transfer from your merchant account to the user's bank account, this process starting by validating again the user’s bank account. DANA will validate your request, deduct the funds from your merchant balance, and initiate the transfer to the user’s destination bank. The bank will then process the transfer and credit the amount to the user's account. You'll receive an response confirming the transfer submission (not completion).
import os
from dana.utils.snap_configuration import SnapConfiguration, AuthSettings, Env
from dana.disbursement.v1 import DisbursementApi
from dana.disbursement.v1.models.TransferToBankRequest import TransferToBankRequest
from dana.api_client import ApiClient
from dana.rest import ApiException
from pprint import pprint
# configuration and ApiClient object can be used for multiple operations
# They should be singleton through the application lifecycle
configuration = SnapConfiguration(
// .. initialize client with authentication
)
)
with ApiClient(configuration) as api_client:
api_instance = DisbursementApi(api_client)
transfer_to_bank_request = TransferToBankRequest()
try:
api_response = api_instance.transfer_to_bank(transfer_to_bank_request)
print("The response of DisbursementApi->transfer_to_bank:\n")
pprint(api_response)
except Exception as e:
print("Exception when calling DisbursementApi->transfer_to_bank: %s\n" % e)
Set additionalInfo.needNotify = true
to receive notifications when the bank transfer request is in progress
Step 6 : Receive Transfer Status Updates
After bank processing completes, DANA sends transfer status notifications to your configured endpoint via the Transfer to Bank Notify API. Your notification URL must follow the ASPI-mandated format: /v1.0/debit/emoney/transfer-bank/notify.htm.
Example of a successful payment webhook payload:
Content-type: application/json
X-TIMESTAMP: 2020-12-21T17:50:44+07:00
{
"responseCode": "2004300",
"responseMessage": "Successful",
}
Optional Check Transfer Status Manually
If you don't receive result from Transfer to Bank API within the expected timeframe or if your transfer API call times out, use the Transfer to Bank Inquiry Status API to manually check the transfer status. You'll need your originalPartnerReferenceNo and serviceCode.
import os
from dana.utils.snap_configuration import SnapConfiguration, AuthSettings, Env
from dana.disbursement.v1 import DisbursementApi
from dana.disbursement.v1.models.TransferToBankInquiryStatusRequest import TransferToBankInquiryStatusRequest
from dana.api_client import ApiClient
from dana.rest import ApiException
from pprint import pprint
# configuration and ApiClient object can be used for multiple operations
# They should be singleton through the application lifecycle
configuration = SnapConfiguration(
// .. initialize client with authentication
)
)
with ApiClient(configuration) as api_client:
api_instance = DisbursementApi(api_client)
transfer_to_bank_inquiry_status_request = TransferToBankInquiryStatusRequest()
try:
api_response = api_instance.transfer_to_bank_inquiry_status(transfer_to_bank_inquiry_status_request)
print("The response of DisbursementApi->transfer_to_bank_inquiry_status:\n")
pprint(api_response)
except Exception as e:
print("Exception when calling DisbursementApi->transfer_to_bank_inquiry_status: %s\n" % e)
For detailed retry procedure, see Retry Mechanism section.
Additional Enum Configuration
The library provides several enums (enumerations) to represent a fixed set of constant values, ensuring consistency and reducing errors during integration.
from dana.disbursement.v1.enum import *
# Example of using enum
enum_value = ChargeTarget.DIVISION
The following enums are available in the Library Disbursement:
- ChargeTarget
- LatestTransactionStatus
Step 7 : Test using our automated test suite
Visit our Scenario Testing guide for detailed information on testing requirements.
We are required by local regulators to ensure your integration works correctly across all critical use cases. Use our sandbox environment and Merchant Portal to safely conduct UAT testing on a list of mandatory testing scenarios.
To complete our mandatory testing requirements, follow these steps:
- Access your Integration Checklist page inside the Merchant Portal
- Complete all the mandatory testing scenarios provided
- Download your verified API Logs using the Download Verification Proof button
- Complete your Go Live Submission checklist
- Submit your verified API logs on your Production Submission form
UAT Testing Script
Use our specialized UAT testing suite to save days of debugging.
To speed up your integration, we have provided an automated test suite. It takes under 15 minutes to run your integration against our test scenarios. Check out the Github repo for more instructions
Step 8 : Submit testing documents & apply for production
As part of regulatory compliance, merchants are required to submit UAT testing documents to meet Bank Indonesia's requirements. After completing sandbox testing, follow these steps to move to production:
Generate production keys
Create your production private and public keys, follow this instruction: Authentication - Production Credential.Complete your UAT testing checklist
Confirm that you have completed all testing scenarios from our Merchant Portal.Fill out your Production Submission form
Follow the instructions inside our Merchant Portal to apply for production credentials. We will process your application in 1-2 days.Obtain production credentials
Once approved, you will receive your production credentials such as: Merchant ID, Client ID known as X-PARTNER-ID, and Client Secret.
Testing in production environment
Configure production environment
Switch your application settings from sandbox to production environment by updating the API endpoints and credentials.Test using production credentials
Conduct the same testing scenarios as sandbox testing, using your production credentials.UAT production sign-off
Once testing is complete, DANA will prepare the UAT Production Sign Off document in the Merchant Portal. Both merchant and DANA representatives must sign this document to formally approve the integration.Receive live payments
After receiving all approvals, your DANA integration will be activated and ready for live payments from your customers.
Ready to submit testing documents?
Access our merchant portal for detailed guide to start receiving live payments
Step 1 : Library Installation
Visit our Libraries & Plugins guide for detailed information on our SDK.
DANA provides server-side API libraries for several programming languages, available through common package managers, for easier installation and version management. Follow the guide below to install our library:
Requirements
- go.mod
- go.sum file
- Your testing credentials from the merchant portal.
Installation
Install or visit our Githubgo get github.com/dana-id/dana-go
Set up the env
PRIVATE_KEY or PRIVATE_KEY_PATH # Your private key
ORIGIN # Your application's origin URL
X_PARTNER_ID # clientId provided during onboarding
ENV # DANA's environment either 'sandbox' or 'production'
Obtaining merchant credentials: Authentication
Import Package
import (
disbursement "github.com/dana-id/dana-go/disbursement/v1"
)
Step 2 : Initialize the library
Visit our Authentication guide to learn about the authentication process when not using our Library.
Follow the guide below to initialize the library
package main
import (
"context"
"fmt"
"os"
dana "github.com/dana-id/dana-go"
"github.com/dana-id/dana-go/config"
disbursement "github.com/dana-id/dana-go/disbursement/v1"
)
func main() {
// Configuring api client
// Api client should be singleton, can reuse the apiClient for multiple requests in various operations
configuration := config.NewConfiguration()
configuration.APIKey = &config.APIKey{
DANA_ENV: config.ENV_SANDBOX, // use config.ENV_PRODUCTION for production
// ENV: config.ENV_SANDBOX, // use config.ENV_PRODUCTION for production. Can use DANA_ENV instead
X_PARTNER_ID: os.Getenv("X_PARTNER_ID"),
PRIVATE_KEY: os.Getenv("PRIVATE_KEY"), // Can provide the private key directly as a string or via a file path (PRIVATE_KEY_PATH). If both added, we will prioritize the path
ORIGIN: os.Getenv("ORIGIN"),
// PRIVATE_KEY_PATH: os.Getenv("PRIVATE_KEY_PATH"),
}
apiClient := dana.NewAPIClient(configuration)
}
Step 3 : Check Your Merchant Balance
Before processing any bank transfer, call DANA's Check Disbursement Account API to verify that your merchant deposit account has sufficient funds. DANA will return your current available balance so you can confirm you have enough money for the transfer amount. If your balance is insufficient, top up your account balance via the Virtual Account (VA) displayed in Merchant Portal.
package main
import (
"context"
"fmt"
"os"
dana "github.com/dana-id/dana-go"
"github.com/dana-id/dana-go/config"
merchant_management "github.com/dana-id/dana-go/merchant_management/v1"
)
func main() {
// Define request struct directly (example)
request := merchant_management.QueryMerchantResourceRequest{
// Fill in required fields here, refer to Check Disbursement Account API Detail
}
configuration := config.NewConfiguration()
// Set API keys
configuration.APIKey = &config.APIKey{
// ENV: config.ENV_SANDBOX, // use config.ENV_PRODUCTION for production. Can use DANA_ENV instead
DANA_ENV: config.ENV_SANDBOX, // use config.ENV_PRODUCTION for production
X_PARTNER_ID: os.Getenv("X_PARTNER_ID"),
PRIVATE_KEY: os.Getenv("PRIVATE_KEY"),
ORIGIN: os.Getenv("ORIGIN"),
// PRIVATE_KEY_PATH: os.Getenv("PRIVATE_KEY_PATH"),
}
apiClient := dana.NewAPIClient(configuration)
_, r, err := apiClient.MerchantManagementAPI.QueryMerchantResource(context.Background()).QueryMerchantResourceRequest(request).Execute()
if err != nil {
fmt.Fprintf(os.Stderr, "Error when calling `MerchantManagementAPI.QueryMerchantResource``: %v\n", err)
fmt.Fprintf(os.Stderr, "Full HTTP response: %v\n", r)
}
// response from `QueryMerchantResource`: QueryMerchantResourceResponse
fmt.Fprintf(os.Stdout, "Response from `MerchantManagementAPI.QueryMerchantResource`: %v\n", r.Body)
}
Step 4 : Validate User’s Bank Account
When a user wants to transfer money to their bank account, call DANA's Transfer to Bank Account Inquiry API to validate their bank account details before initiating the actual transfer. You'll need to provide the customerNumber, beneficiaryAccountNumber, amount, additionalInfo.fundType, and additionalInfo.beneficiaryBankCode. DANA will forward this inquiry to the destination bank, which will verify the account and return by providing the detail account information.
package main
import (
"context"
"fmt"
"os"
dana "github.com/dana-id/dana-go"
"github.com/dana-id/dana-go/config"
disbursement "github.com/dana-id/dana-go/disbursement/v1"
)
func main() {
// ... define authentication
request := disbursement.BankAccountInquiryRequest{
// Fill in required fields here, refer to Transfer to Bank Account Inquiry API Detail
}
_, r, err := apiClient.DisbursementAPI.BankAccountInquiry(context.Background()).BankAccountInquiryRequest(request).Execute()
if err != nil {
fmt.Fprintf(os.Stderr, "Error when calling `DisbursementAPI.BankAccountInquiry`: %v\n", err)
fmt.Fprintf(os.Stderr, "Full HTTP response: %v\n", r)
}
// response from `BankAccountInquiry`: BankAccountInquiryResponse
fmt.Fprintf(os.Stdout, "Response from `DisbursementAPI.BankAccountInquiry`: %v\n", r.Body)
}
Step 5 : Execute the Bank Transfer
Call DANA's Transfer to Bank API to process the actual fund transfer from your merchant account to the user's bank account, this process starting by validating again the user’s bank account. DANA will validate your request, deduct the funds from your merchant balance, and initiate the transfer to the user’s destination bank. The bank will then process the transfer and credit the amount to the user's account. You'll receive an response confirming the transfer submission (not completion).
package main
import (
"context"
"fmt"
"os"
dana "github.com/dana-id/dana-go"
"github.com/dana-id/dana-go/config"
disbursement "github.com/dana-id/dana-go/disbursement/v1"
)
func main() {
// ... define authentication
request := disbursement.TransferToBankRequest{
// Fill in required fields here, refer to Transfer to Bank API Detail
}
_, r, err := apiClient.DisbursementAPI.TransferToBank(context.Background()).TransferToBankRequest(request).Execute()
if err != nil {
fmt.Fprintf(os.Stderr, "Error when calling `DisbursementAPI.TransferToBank`: %v\n", err)
fmt.Fprintf(os.Stderr, "Full HTTP response: %v\n", r)
}
// response from `TransferToBank`: TransferToBankResponse
fmt.Fprintf(os.Stdout, "Response from `DisbursementAPI.TransferToBank`: %v\n", r.Body)
}
Set additionalInfo.needNotify = true
to receive notifications when the bank transfer request is in progress
Step 6 : Receive Transfer Status Updates
After bank processing completes, DANA sends transfer status notifications to your configured endpoint via the Transfer to Bank Notify API. Your notification URL must follow the ASPI-mandated format: /v1.0/debit/emoney/transfer-bank/notify.htm.
Content-type: application/json
X-TIMESTAMP: 2020-12-21T17:50:44+07:00
{
"responseCode": "2004300",
"responseMessage": "Successful",
}
Optional Check Transfer Status Manually
If you don't receive result from Transfer to Bank API within the expected timeframe or if your transfer API call times out, use the Transfer to Bank Inquiry Status API to manually check the transfer status. You'll need your originalPartnerReferenceNo and serviceCode.
package main
import (
"context"
"fmt"
"os"
dana "github.com/dana-id/dana-go"
"github.com/dana-id/dana-go/config"
disbursement "github.com/dana-id/dana-go/disbursement/v1"
)
func main() {
// ... define authentication
request := disbursement.TransferToBankInquiryStatusRequest{
// Fill in required fields here, refer to Transfer to Bank Inquiry Status API Detail
}
_, r, err := apiClient.DisbursementAPI.TransferToBankInquiryStatus(context.Background()).TransferToBankInquiryStatusRequest(request).Execute()
if err != nil {
fmt.Fprintf(os.Stderr, "Error when calling `DisbursementAPI.TransferToBankInquiryStatus`: %v\n", err)
fmt.Fprintf(os.Stderr, "Full HTTP response: %v\n", r)
}
// response from `TransferToBankInquiryStatus`: TransferToBankInquiryStatusResponse
fmt.Fprintf(os.Stdout, "Response from `DisbursementAPI.TransferToBankInquiryStatus`: %v\n", r.Body)
}
For detailed retry procedure, see Retry Mechanism section.
Additional Enum Configuration
The library provides several enums (enumerations) to represent a fixed set of constant values, ensuring consistency and reducing errors during integration.
import disbursement "github.com/dana-id/dana-go/disbursement/v1"
value := string(disbursement.CHARGETARGET_DIVISION_)
The following enums are available in the Library Disbursement:
- ChargeTarget
- LatestTransactionStatus
Step 7 : Test using our automated test suite
Visit our Scenario Testing guide for detailed information on testing requirements.
We are required by local regulators to ensure your integration works correctly across all critical use cases. Use our sandbox environment and Merchant Portal to safely conduct UAT testing on a list of mandatory testing scenarios.
To complete our mandatory testing requirements, follow these steps:
- Access your Integration Checklist page inside the Merchant Portal
- Complete all the mandatory testing scenarios provided
- Download your verified API Logs using the Download Verification Proof button
- Complete your Go Live Submission checklist
- Submit your verified API logs on your Production Submission form
UAT Testing Script
Use our specialized UAT testing suite to save days of debugging.
To speed up your integration, we have provided an automated test suite. It takes under 15 minutes to run your integration against our test scenarios. Check out the Github repo for more instructions
Step 8 : Submit testing documents & apply for production
As part of regulatory compliance, merchants are required to submit UAT testing documents to meet Bank Indonesia's requirements. After completing sandbox testing, follow these steps to move to production:
Generate production keys
Create your production private and public keys, follow this instruction: Authentication - Production Credential.Complete your UAT testing checklist
Confirm that you have completed all testing scenarios from our Merchant Portal.Fill out your Production Submission form
Follow the instructions inside our Merchant Portal to apply for production credentials. We will process your application in 1-2 days.Obtain production credentials
Once approved, you will receive your production credentials such as: Merchant ID, Client ID known as X-PARTNER-ID, and Client Secret.
Testing in production environment
Configure production environment
Switch your application settings from sandbox to production environment by updating the API endpoints and credentials.Test using production credentials
Conduct the same testing scenarios as sandbox testing, using your production credentials.UAT production sign-off
Once testing is complete, DANA will prepare the UAT Production Sign Off document in the Merchant Portal. Both merchant and DANA representatives must sign this document to formally approve the integration.Receive live payments
After receiving all approvals, your DANA integration will be activated and ready for live payments from your customers.
Ready to submit testing documents?
Access our merchant portal for detailed guide to start receiving live payments
Step 1 : Library Installation
Visit our Libraries & Plugins guide for detailed information on our SDK.
DANA provides server-side API libraries for several programming languages, available through common package managers, for easier installation and version management. Follow the guide below to install our library:
Requirements
- PHP 7.4+, compatible with PHP 8.0.
- Your testing credentials from the merchant portal.
Installation
Install using composer or visit our Github- Using Composer
- Add the following code to
composer.json
- Add the following code to
{
"repositories": [
{
"type": "vcs",
"url": "https://github.com/GIT_USER_ID/GIT_REPO_ID.git"
}
],
"require": {
"GIT_USER_ID/GIT_REPO_ID": "*@dev"
}
}
- Run
composer install
- Manual Installation
<?php
require_once('/path/to/DanaPhp/vendor/autoload.php');
Set up the env
PRIVATE_KEY or PRIVATE_KEY_PATH # Your private key
ORIGIN # Your application's origin URL
X_PARTNER_ID # clientId provided during onboarding
ENV # DANA's environment either 'sandbox' or 'production'
Obtaining merchant credentials: Authentication
Import Package
use Dana\Disbursement\v1
Step 2 : Initialize the library
Visit our Authentication guide to learn about the authentication process when not using our Library.
Follow the guide below to initialize the library
<?php
use Dana\Configuration;
use Dana\Env;
use Dana\Disbursement\v1\Api\DisbursementApi;
use Dana\Disbursement\v1\Model\BankAccountInquiryRequest;
// Set up configuration with authentication settings
$configuration = new Configuration();
// The Configuration constructor automatically loads values from environment variables
// Choose one of PRIVATE_KEY or PRIVATE_KEY_PATH to set, if you set both, PRIVATE_KEY will be ignored
$configuration->setApiKey('PRIVATE_KEY', getenv('PRIVATE_KEY'));
// $configuration->setApiKey('PRIVATE_KEY_PATH', getenv('PRIVATE_KEY_PATH'));
$configuration->setApiKey('ORIGIN', getenv('ORIGIN'));
$configuration->setApiKey('X_PARTNER_ID', getenv('X_PARTNER_ID'));
$configuration->setApiKey('DANA_ENV', Env::SANDBOX);
// Choose one of ENV or DANA_ENV to set, if you set both, ENV will be ignored
// $configuration->setApiKey('ENV', Env::SANDBOX);
$apiInstance = new DisbursementApi(
null, // this also can be set to custom http client which implements `GuzzleHttp\ClientInterface`
$configuration
);
Step 3 : Check Your Merchant Balance
Before processing any bank transfer, call DANA's Check Disbursement Account API to verify that your merchant deposit account has sufficient funds. DANA will return your current available balance so you can confirm you have enough money for the transfer amount. If your balance is insufficient, top up your account balance via the Virtual Account (VA) displayed in Merchant Portal.
<?php
use Dana\Configuration;
use Dana\Env;
use Dana\MerchantManagement\v1\Api\MerchantManagementApi;
use Dana\MerchantManagement\v1\Model\QueryMerchantResourceRequest;
// Set up configuration with authentication settings
$configuration = new Configuration();
// The Configuration constructor automatically loads values from environment variables
// Choose one of PRIVATE_KEY or PRIVATE_KEY_PATH to set, if you set both, PRIVATE_KEY will be ignored
$configuration->setApiKey('PRIVATE_KEY', getenv('PRIVATE_KEY'));
// $configuration->setApiKey('PRIVATE_KEY_PATH', getenv('PRIVATE_KEY_PATH'));
$configuration->setApiKey('ORIGIN', getenv('ORIGIN'));
$configuration->setApiKey('X_PARTNER_ID', getenv('X_PARTNER_ID'));
$configuration->setApiKey('DANA_ENV', Env::SANDBOX);
// Choose one of ENV or DANA_ENV to set, if you set both, ENV will be ignored
// $configuration->setApiKey('ENV', Env::SANDBOX);
$configuration->setApiKey('CLIENT_SECRET', getenv('CLIENT_SECRET'));
$apiInstance = new MerchantManagementApi(
null, // this also can be set to custom http client which implements `GuzzleHttp\ClientInterface`
$configuration
);
$queryMerchantResourceRequest = QueryMerchantResourceRequest();
try {
$result = $apiInstance->queryMerchantResource($queryMerchantResourceRequest);
print_r($result);
} catch (Exception $e) {
echo 'Exception when calling MerchantManagementApi->queryMerchantResource: ', $e->getMessage(), PHP_EOL;
}
Step 4 : Validate User’s Bank Account
When a user wants to transfer money to their bank account, call DANA's Transfer to Bank Account Inquiry API to validate their bank account details before initiating the actual transfer. You'll need to provide the customerNumber, beneficiaryAccountNumber, amount, additionalInfo.fundType, and additionalInfo.beneficiaryBankCode. DANA will forward this inquiry to the destination bank, which will verify the account and return by providing the detail account information.
<?php
use Dana\Configuration;
use Dana\Env;
use Dana\Disbursement\v1\Api\DisbursementApi;
use Dana\Disbursement\v1\Model\BankAccountInquiryRequest;
// ... define authentication
$bankAccountInquiryRequest = BankAccountInquiryRequest();
try {
$result = $apiInstance->bankAccountInquiry($bankAccountInquiryRequest);
print_r($result);
} catch (Exception $e) {
echo 'Exception when calling DisbursementApi->bankAccountInquiry: ', $e->getMessage(), PHP_EOL;
}
Step 5 : Execute the Bank Transfer
Call DANA's Transfer to Bank API to process the actual fund transfer from your merchant account to the user's bank account, this process starting by validating again the user’s bank account. DANA will validate your request, deduct the funds from your merchant balance, and initiate the transfer to the user’s destination bank. The bank will then process the transfer and credit the amount to the user's account. You'll receive an response confirming the transfer submission (not completion).
<?php
use Dana\Configuration;
use Dana\Env;
use Dana\Disbursement\v1\Api\DisbursementApi;
use Dana\Disbursement\v1\Model\TransferToBankRequest;
// ... define authentication
$transferToBankRequest = TransferToBankRequest();
try {
$result = $apiInstance->transferToBank($transferToBankRequest);
print_r($result);
} catch (Exception $e) {
echo 'Exception when calling DisbursementApi->transferToBank: ', $e->getMessage(), PHP_EOL;
}
Set additionalInfo.needNotify = true
to receive notifications when the bank transfer request is in progress
Step 6 : Receive Transfer Status Updates
After bank processing completes, DANA sends transfer status notifications to your configured endpoint via the Transfer to Bank Notify API. Your notification URL must follow the ASPI-mandated format: /v1.0/debit/emoney/transfer-bank/notify.htm.
Example of a successful payment webhook payload:
Content-type: application/json
X-TIMESTAMP: 2020-12-21T17:50:44+07:00
{
"responseCode": "2004300",
"responseMessage": "Successful",
}
Optional Check Transfer Status Manually
If you don't receive result from Transfer to Bank API within the expected timeframe or if your transfer API call times out, use the Transfer to Bank Inquiry Status API to manually check the transfer status. You'll need your originalPartnerReferenceNo and serviceCode.
<?php
use Dana\Configuration;
use Dana\Env;
use Dana\Disbursement\v1\Api\DisbursementApi;
use Dana\Disbursement\v1\Model\TransferToBankInquiryStatusRequest;
// ... define authentication
$transferToBankInquiryStatusRequest = TransferToBankInquiryStatusRequest();
try {
$result = $apiInstance->transferToBankInquiryStatus($transferToBankInquiryStatusRequest);
print_r($result);
} catch (Exception $e) {
echo 'Exception when calling DisbursementApi->transferToBankInquiryStatus: ', $e->getMessage(), PHP_EOL;
}
For detailed retry procedure, see Retry Mechanism section.
Additional Enum Configuration
The library provides several enums (enumerations) to represent a fixed set of constant values, ensuring consistency and reducing errors during integration.
// Importing an enum class
use Dana\Disbursement\v1\Enum\ChargeTarget;
// Using enum constants
$model->setProperty(ChargeTarget::DIVISION);
// Using enum values directly as strings
$model->setProperty('DIVISION');
The following enums are available in the Library Disbursement:
- ChargeTarget
- LatestTransactionStatus
Step 7 : Test using our automated test suite
Visit our Scenario Testing guide for detailed information on testing requirements.
We are required by local regulators to ensure your integration works correctly across all critical use cases. Use our sandbox environment and Merchant Portal to safely conduct UAT testing on a list of mandatory testing scenarios.
To complete our mandatory testing requirements, follow these steps:
- Access your Integration Checklist page inside the Merchant Portal
- Complete all the mandatory testing scenarios provided
- Download your verified API Logs using the Download Verification Proof button
- Complete your Go Live Submission checklist
- Submit your verified API logs on your Production Submission form
UAT Testing Script
Use our specialized UAT testing suite to save days of debugging.
To speed up your integration, we have provided an automated test suite. It takes under 15 minutes to run your integration against our test scenarios. Check out the Github repo for more instructions
Step 8 : Submit testing documents & apply for production
As part of regulatory compliance, merchants are required to submit UAT testing documents to meet Bank Indonesia's requirements. After completing sandbox testing, follow these steps to move to production:
Generate production keys
Create your production private and public keys, follow this instruction: Authentication - Production Credential.Complete your UAT testing checklist
Confirm that you have completed all testing scenarios from our Merchant Portal.Fill out your Production Submission form
Follow the instructions inside our Merchant Portal to apply for production credentials. We will process your application in 1-2 days.Obtain production credentials
Once approved, you will receive your production credentials such as: Merchant ID, Client ID known as X-PARTNER-ID, and Client Secret.
Testing in production environment
Configure production environment
Switch your application settings from sandbox to production environment by updating the API endpoints and credentials.Test using production credentials
Conduct the same testing scenarios as sandbox testing, using your production credentials.UAT production sign-off
Once testing is complete, DANA will prepare the UAT Production Sign Off document in the Merchant Portal. Both merchant and DANA representatives must sign this document to formally approve the integration.Receive live payments
After receiving all approvals, your DANA integration will be activated and ready for live payments from your customers.
Ready to submit testing documents?
Access our merchant portal for detailed guide to start receiving live payments