NAV undefined
undefined
bash php java

Introduction

Welcome! Here at Instamoney, our mission is to provide payments infrastructure that helps you succeed. We help with both the money in (accepting payments) and money out (disbursing payments). Use cases range from platform business to fintech lending and eCommerce, and everything else in between.

The Instamoney API is organized around REST. Our API has predictable, resource-oriented URLs, and uses HTTP response codes to indicate API errors. We use built-in HTTP features and HTTP verbs, which are understood by off-the-shelf HTTP clients. JSON is returned by all API responses, including errors.

Authentication

To successfully authenticate with Instamoney's APIs, you must authenticate your secret API key using Basic Auth. You can obtain your API keys in Dashboard. For example if your API key is

sk_test_PYGIfL5y0uHx5ZhLbUdSzCRb9ajpdl6lyXmRxn2zQbWlBEUQWE9218vfR0jg

Select Basic Auth authentication. Input secret API key in username and leave the password empty

Basic Auth format
{{username}}:{{password}}

Following the format (with colon)
sk_test_PYGIfL5y0uHx5ZhLbUdSzCRb9ajpdl6lyXmRxn2zQbWlBEUQWE9218vfR0jg:

Encode Basic Auth format above into Base64 format

c2tfdGVzdF9QWUdJZkw1eTB1SHg1WmhMYlVkU3pDUmI5YWpwZGw2bHlYbVJ4bjJ6UWJXbEJFVVFXRTkyMTh2ZlIwamc===

Include Base64 encoded value in HTTP(s) header

Authorization: Basic c2tfdGVzdF9QWUdJZkw1eTB1SHg1WmhMYlVkU3pDUmI5YWpwZGw2bHlYbVJ4bjJ6UWJXbEJFVVFXRTkyMTh2ZlIwamc===

Instamoney API is organized around REST to make it cleaner and easier to understand. All our API responses return JSON. To let you explore our APIs, make sure that you have registered an account. You can obtain and manage your API keys in API Keys Settings. We provide you API keys for both the test and live environments.

To authenticate your account, you have to include your secret API key in the request which can be accessed in Instamoney Dashboard. Here are the steps to authenticate your account:

  1. Generate secret API key from Dashboard
  2. Obtain your secret API key
  3. Select Basic Access Authentication or BASIC AUTH authentication
  4. BASIC AUTH format will be {{username}}:{{password}}
  5. Input Secret API key as username and leave the password empty. Make sure to include : at the end
  6. Encode the value above into Base64 format
  7. Include the base64 encoded into Authorization header

All the API requests should be made over HTTPS instead of HTTP (all calls made over plain HTTP will fail). All requests made in the test environment will never hit the banking networks and will not cost you anything. Your API keys should be kept private so do not share your secret API keys. Learn more about API key here

Libraries / SDKs

Instamoney has official libraries for different programming languages and mobile platforms. We are continuously developing more libraries and plugins. If you have implemented your own library or an example that you would like to share, send us a link to your code and we'll be happy to add it to the list!

PHP

Download PHP package here

https://packagist.org/packages/instamoney/instamoney-php-clients

PHP library is a client that is created on top of PHP so it is easier for you to integrate with us to accept payments via our supported payment channels.

Currently PHP library supports:

  1. Bank Transfer via Virtual Accounts
  2. Disbursements

Here are the steps to use Instamoney PHP library:

  1. Download PHP package here
  2. Include InstamoneyPHPClient.php in your code
  3. Create InstamoneyPHPClient object with secret API key as parameter
  4. Require InstamoneyPHPClient.php in your code

Errors

Your Instamoney integration might have to deal with errors at some point when making API requests to Instamoney. These errors fall into a few major categories:

The right approach and idempotency semantics to use for handling errors depend on the type of error being handled.

HTTP Status Code

Instamoney uses conventional HTTP response codes to indicate the success or failure of an API request. In general: Codes in the 2xx range indicate success. Codes in the 4xx range indicate an error that failed given the information provided (e.g., a required parameter was omitted, a charge failed, etc). Codes in the 5xx range indicate an error with Instamoney's servers (these are rare).

Status Code Description
200 - OK Everything worked as expected
400 - Bad Request The request was unacceptable, often due to missing a required parameter
401 - Unauthorized No valid API key provided
403 - Forbidden The API key doesn't have permissions to perform the request
404 - Not Found The requested resources doesn't exist
500 - Server Errors Something went wrong on Instamoney's end (These are rare)

Error Code

Below are some of most common errors across all our endpoints. Specific errors are located under each endpoint.

Error Code Description
API_VALIDATION_ERROR Invalid request errors arise when your request has invalid parameters
INVALID_API_KEY No valid API key provided
REQUEST_FORBIDDEN_ERROR
The API key doesn't have permissions to perform the request
SERVER_ERROR API errors cover any other type of problem (e.g. a temporary problem with Instamoney's servers), and are extremely uncommon

Error Handling

Safely retry requests with idempotency

A key part of web API design is the idea of idempotency, defined as being able to apply the same operation multiple times without changing the result beyond the first try. Because a certain amount of intermittent failure is to be expected, clients need a way of reconciling failed requests with a server, and idempotency provides a mechanism for that.

The Instamoney API guarantees the idempotency of GET requests, so it's always safe to retry them. Including an idempotency key makes POST and PATCH request idempotent, which prompts the API to do the bookkeeping required to prevent duplicate operations. For example, if a request to create disbursements does not respond due to network connection error, you can retry the request with the same idempotency key to guarantee that no more than one disbursement is created.

Idempotency keys are sent in the x-idempotency-key header, and you should use them for all POST requests to Instamoney's API whenever supported. A few common strategies for generating idempotency keys are:

A response that's being replayed from the server because it had already executed previously can be identified by the error code DUPLICATE_TRANSACTION_ERROR

Content errors

Content errros are the result of the contents of an API request being invalid and return a 4xx error code. Integrations should correct the original request and try again. Depending of the type of user error, it may be possible to handle the problem programmatically.

For a POST operation using an idempotency key, as long as an API method began execution, Instamoney's API servers will cache the results of the request regardless of what they were. A request that returns a 400 will send back the same 400 if followed by a new request with the same idempotency key. A fresh idempotency key should be generated when modifying the original request to get a successful result. The safest strategy where 4xx errors are concerned is to always generate a new idempotency key.

Network errors

Network errors are the result of connectivity problems between client and server and tend to manifest as low-level errors like socket or timeout exceptions.

This class of errors is where the value of idempotency keys and request retries is most obvious. When intermittent problems occur, clients are usually left in a state where they don't know whether or not the server received the request. To get a definitive answer, they should retry such requests with the same idempotency keys and the same parameters until they're able to receive a result from the server. Sending the same idempotency with different parameters will produce an error indicating that the new request didn't match the original.

Server errors

Server errors are the result of a server-side problem and return a 5xx error code. These errors are the most difficult to handle, so we try to ensure that they happen as infrequently as possible.

As with the errors, retrying them with the same idempotency key will usually produce the same result. The request can be retried with a new idempotency key, but we'd advice against it because it's possible for the original one to have produced side effects.

The result of a 500 request should be treated as indeterminate. The exact nature of any retroactive changes in the system depend heavily on the type of request. For example, if creating a disbursement returns a 500 error but we detect that the information has gone out to a payment network, we'll try to roll it forward and send callback after it has been completed. If not, we'll try to roll it back. However, ideal results under these circumstances are not guaranteed, and requests resulting in a 500 error may proeduce user-visible side effects.

Integration that want to maximize robustness must configure callback handlers that are capable of receiving events that have never been seen in an API response.

Balances

Get balance

Endpoint: Get Balance

GET https://api.instamoney.co/balance?account_type={account_type}

Balance is like your wallet since it will tell you how much money is available to you on Instamoney. You can retrieve it to see the current balance on your Instamoney cash account. Your balance is debited on any money out transaction, e.g. when performing disbursements or Instamoney fees are charged. Your balance is credited when money comes into your account, e.g. fixed virtual accounts are paid or you deposit funds. You can assign your money into different accounts according to your business logic (eg: cash account, tax account, escrow account) and each account has its own balance that can be accessed in the dashboard.

Get Balance Request

Example Get Balance Request

curl https://api.instamoney.co/balance -X GET \
-u sk_test_OYCEfL5xgLL+l8ZvK7QaSGGVMN73oNEpk3yz+Rxn/2bS/LCgCQZ+gw==:
<?php
  require 'vendor/autoload.php';

  $options['secret_api_key'] = 'sk_test_OYCEfL5xgLL+l8ZvK7QaSGGVMN73oNEpk3yz+Rxn/2bS/LCgCQZ+gw==';

  $instamoneyPHPClient = new InstamoneyClient\InstamoneyPHPClient($options);

  $response = $instamoneyPHPClient->getBalance();
  print_r($response);
?>
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.MediaType;

Client client = ClientBuilder.newClient();
Response response = client.target("https://api.instamoney.co/balance")
  .request(MediaType.APPLICATION_JSON_TYPE)
  .header("Authorization", "Basic c2tfdGVzdF9PWUNFZkw1eGdMTCtsOFp2SzdRYVNHR1ZNTjczb05FcGszeXorUnhuLzJiUy9MQ2dDUVorZ3c9PTo=")
  .get();

System.out.println("status: " + response.getStatus());
System.out.println("headers: " + response.getHeaders());
System.out.println("body:" + response.readEntity(String.class));

Get Balance allows you to retrieve the balance of your cash, escrow and tax account. Some use cases include: deciding when you may need to withdraw funds, determining if you have funds to disburse, and if you just like to check it’s still there :P

Currently, the API only supports querying the balance for your cash, escrow and tax account. Anything else related to the account (eg: adding new account, transferring money from accounts besides cash account, etc.) will be done at the beginning in initial configuration with our technical team.

Parameter Description
account_type
optional
default: CASH
string The selected account type (CASH or HOLDING).

Get Balance Response

Example Get Balance Response

{
  "balance": 1241231
}
Parameter Description
balance The balance remaining in your cash account

Virtual Accounts

Get banks for virtual accounts

Endpoint: Get Available Banks for Virtual Accounts

GET https://api.instamoney.co/available_virtual_account_banks

Example Get Banks for Virtual Accounts Request

curl https://api.instamoney.co/available_virtual_account_banks -X GET \
   -u sk_test_OYCEfL5xgLL+l8ZvK7QaSGGVMN73oNEpk3yz+Rxn/2bS/LCgCQZ+gw==:
<?php
  require 'vendor/autoload.php';

  $options['secret_api_key'] = 'sk_test_OYCEfL5xgLL+l8ZvK7QaSGGVMN73oNEpk3yz+Rxn/2bS/LCgCQZ+gw==';

  $instamoneyPHPClient = new InstamoneyClient\InstamoneyPHPClient($options);

  $response = $instamoneyPHPClient->getVirtualAccountBanks();
  print_r($response);
?>

import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.MediaType;

Client client = ClientBuilder.newClient();
Response response = client.target("https://api.instamoney.co/available_virtual_account_banks")
  .request(MediaType.APPLICATION_JSON_TYPE)
  .header("Authorization", "Basic c2tfdGVzdF9PWUNFZkw1eGdMTCtsOFp2SzdRYVNHR1ZNTjczb05FcGszeXorUnhuLzJiUy9MQ2dDUVorZ3c9PTo=")
  .get();

System.out.println("status: " + response.getStatus());
System.out.println("headers: " + response.getHeaders());
System.out.println("body:" + response.readEntity(String.class));

Get Banks for Virtual Accounts Response

Example Get Banks for Virtual Accounts Response

{
  "name": "Bank Negara Indonesia",
  "code": "BNI"
}
Parameter Description
name Full name of the bank
code Code of the bank, relevant during creation of virtual accounts

Create fixed virtual accounts

Endpoint: Create Fixed Virtual Account (FVA)

POST https://api.instamoney.co/callback_virtual_accounts

Fixed virtual accounts are dedicated virtual accounts under a name you choose, e.g. 'YourCompany - Becca Salim'. You will receive a callback each time this fixed virtual account is paid. Read more about fixed virtual accounts.

Create Fixed Virtual Accounts Request

Example Create Fixed Virtual Accounts Request

curl https://api.instamoney.co/callback_virtual_accounts -X POST \
   -u sk_test_OYCEfL5xgLL+l8ZvK7QaSGGVMN73oNEpk3yz+Rxn/2bS/LCgCQZ+gw==: \
   -d external_id=demo_virtual_account_1475459775872 \
   -d bank_code=BNI \
   -d name='Rika Sutanto'
<?php
  require 'vendor/autoload.php';

  $options['secret_api_key'] = 'sk_test_OYCEfL5xgLL+l8ZvK7QaSGGVMN73oNEpk3yz+Rxn/2bS/LCgCQZ+gw==';

  $instamoneyPHPClient = new InstamoneyClient\InstamoneyPHPClient($options);

  $external_id = 'demo_1475459775872';
  $bank_code = 'BNI';
  $name = 'Rika Sutanto';

  $response = $instamoneyPHPClient->createCallbackVirtualAccount($external_id, $bank_code, $name);
  print_r($response);
?>
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.MediaType;

Client client = ClientBuilder.newClient();
Entity payload = Entity.json("{  'external_id': 'user_1212412312',  'bank_code': 'BNI',  'name': 'William Sutanto'}");
Response response = client.target("https://api.instamoney.co/callback_virtual_accounts")
  .request(MediaType.APPLICATION_JSON_TYPE)
  .header("Authorization", "Basic c2tfdGVzdF9PWUNFZkw1eGdMTCtsOFp2SzdRYVNHR1ZNTjczb05FcGszeXorUnhuLzJiUy9MQ2dDUVorZ3c9PTo=")
  .post(payload);

System.out.println("status: " + response.getStatus());
System.out.println("headers: " + response.getHeaders());
System.out.println("body:" + response.readEntity(String.class));
Parameter Description
external_id
required
string An ID of your choice. Often it is unique identifier like a phone number, email or transaction ID. Maximum length allowed is 950 characters.
bank_code
required
string Bank code of the virtual account you want to create
Note: We highly recommend you redirect customers to pay into BNI Virtual Account for interbank transfers

Available bank codes: BCA, BNI, MANDIRI, SAHABAT_SAMPOERNA, BRI , PERMATA
name
required
string Name of user/virtual account, - this will be displayed in the bank's user interface, e.g. ATM confirmation screens. Note that this field can only contain letters and spaces and has no length restriction (though the banks will truncate as per their limitations)
virtual_account_number
optional
string The virtual account number you want to assign. If you do not send one, one will be picked at random
suggested_amount
optional
number The suggested amount you want to assign. If you do not send one, external id will be used
Note: suggested amounts is only supported for Mandiri and BRI
is_closed
optional
boolean When set to true, the virtual account will be closed and will only accept the amount specified in expected_amount
expected_amount
optional
number The amount that the virtual account will expect if is_closed is set to true
expiration_date
optional
ISO Date The time when the virtual account will be expired
is_single_use
optional
boolean When set to true, the virtual account will be inactive after it is paid

Create Fixed Virtual Accounts Response

Example Create Fixed Virtual Accounts Response

{
   "owner_id":"57b4e5181473eeb61c11f9b9",
   "external_id":"demo-1475804036622",
   "bank_code":"BNI",
   "merchant_code":"8808",
   "name":"Rika Sutanto",
   "account_number":"88082548",
   "is_closed": false,
   "id":"57f6fbf26b9f064272622aa6",
   "is_single_use": true,
   "status": "ACTIVE"
}
Parameter Description
owner_id Your user ID
external_id An ID of your choice which you provided upon request
bank_code Bank code for the relevant bank, e.g. BNI
merchant_code 5-digit merchant prefix to the full virtual account number
name Name for the fixed virtual account
account_number Complete virtual account number (including prefix). This is what a user will need to enter into an ATM or their Internet/mobile banking.
suggested_amount OPTIONAL suggested amount for created fixed virtual account
is_closed value that determines whether a virtual account is closed or not
expected_amount OPTIONAL the amount that is expected when is_closed is true
id Unique ID for the fixed virtual account.
is_single_use value that determines whether a virtual account will be inactive after it is paid
status Status of fixed virtual account that defines if it’s pending or inactive. Status is inactive either because it is a paid single use fixed virtual account or it is already expired.

Create Fixed Virtual Accounts Errors

Error Code Description
API_VALIDATION_ERROR
400
Inputs are failing validation. The errors field contains details about which fields are violating validation.
INVALID_JSON_FORMAT
400
The request body is not a valid JSON format.
VIRTUAL_ACCOUNT_NUMBER_OUTSIDE_RANGE
400
The virtual account number you want is outside your range.
BANK_NOT_SUPPORTED_ERROR
400
The bank code is not currently supported.
EXPIRATION_DATE_NOT_SUPPORTED_ERROR
400
Custom expiration date for the fixed virtual account is not currently supported.
EXPIRATION_DATE_INVALID_ERROR
400
Invalid custom expiration date because it's earlier than current time.
SUGGESTED_AMOUNT_NOT_SUPPORTED_ERROR
400
The suggested amount for the fixed virtual account is not currently supported.
EXPECTED_AMOUNT_REQUIRED_ERROR
400
The expected amount is required when is_closed is set to true.
CLOSED_VA_NOT_SUPPORTED_ERROR
400
The closed option for this virtual account is not currently supported.
DUPLICATE_CALLBACK_VIRTUAL_ACCOUNT_ERROR
400
The account number that you want to create is already exist
MINIMUM_EXPECTED_AMOUNT_ERROR
400
The expected amount can only be more than zero
MAXIMUM_EXPECTED_AMOUNT_ERROR
400
The expected amount can only be less than Rp.1000000000
CALLBACK_VIRTUAL_ACCOUNT_NAME_NOT_ALLOWED_ERROR
400
The name cannot contain bank or institution name

Update fixed virtual accounts

Endpoint: Update Fixed Virtual Account (FVA)

PATCH https://api.instamoney.co/callback_virtual_accounts/{fixed_virtual_account_id}

Fixed Virtual Account is so adaptable, and it's all based on your needs. Therefore, we provide you this endpoint to easily update your fixed virtual account as you like.

Update Fixed Virtual Accounts Request

Parameter Description
suggested_amount
optional
number suggested amount you want to assign
expected_amount
optional
number The amount that the virtual account will expect if is_closed is set to true
expiration_date
optional
ISO Date The time when the virtual account will be expired. You can set it to be days in the past to expire virtual account immediately
is_single_use
optional
boolean When set to true, the virtual account will be inactive after it is paid

Update Fixed Virtual Accounts Response

Example update Fixed Virtual Accounts Response

{
   "owner_id":"57b4e5181473eeb61c11f9b9",
   "external_id":"demo-1475804036622",
   "bank_code":"BNI",
   "merchant_code":"8808",
   "name":"Rika Sutanto",
   "account_number":"88082548",
   "suggested_amount":50000,
   "is_closed": false,
   "id":"57f6fbf26b9f064272622aa6",
   "is_single_use": true,
   "status": "ACTIVE"
}
Parameter Description
owner_id Your user ID
external_id An ID of your choice which you provided upon virtual account creation
bank_code Bank code for the relevant bank, e.g. BNI
merchant_code 5-digit merchant prefix to the full virtual account number
name Name for the fixed virtual account
account_number Complete virtual account number (including prefix). This is what a user will need to enter into an ATM or their Internet/mobile banking.
suggested_amount Suggested amount of updated fixed virtual account
id Unique ID for the fixed virtual account.
is_closed value that determines whether a virtual account is closed or not
expected_amount OPTIONAL the amount that is expected when is_closed is true
is_single_use value that determines whether a virtual account will be inactive after it is paid
status Status of fixed virtual account that defines if it’s pending or inactive. Status is inactive either because it is a paid single use fixed virtual account or it is already expired.

Update Fixed Virtual Accounts Errors

Error Code Description
API_VALIDATION_ERROR
400
Inputs are failing validation. The errors field contains details about which fields are violating validation.
INVALID_JSON_FORMAT
400
The request body is not a valid JSON format.
VIRTUAL_ACCOUNT_NUMBER_OUTSIDE_RANGE
400
The virtual account number you want is outside your range.
BANK_NOT_SUPPORTED_ERROR
400
The bank code is not currently supported.
SUGGESTED_AMOUNT_NOT_SUPPORTED_ERROR
400
The suggested amount for the fixed virtual account is not currently supported.
EXPECTED_AMOUNT_REQUIRED_ERROR
400
The expected amount is required when is_closed is set to true.
CLOSED_VA_NOT_SUPPORTED_ERROR
400
The closed option for this virtual account is not currently supported.
INACTIVE_VIRTUAL_ACCOUNT_ERROR
400
Account number that you want to update is inactive.
MINIMUM_EXPECTED_AMOUNT_ERROR
400
The expected amount can only be more than zero
MAXIMUM_EXPECTED_AMOUNT_ERROR
400
The expected amount can only be less than Rp.1000000000

Fixed virtual account callback

Endpoint: Fixed Virtual Account Callback

POST https://yourcompany.com/virtual_account_paid_callback_url
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.MediaType;

Client client = ClientBuilder.newClient();
Entity payload = Entity.json("{
    id: '57fb4e076fa3fa296b7f5a97',
    payment_id: 'demo-1476087608948_1476087303080',
    callback_virtual_account_id: '57fb4df9af86ce19778ad359',
    owner_id: '57b4e5181473eeb61c11f9b9',
    external_id: 'demo-1476087608948',
    account_number: '1547',
    bank_code: 'BNI',
    amount: 99000,
    transaction_timestamp: '2016-10-10T08:15:03.080Z',
    merchant_code: '8808',
    updated: '2016-10-10T08:15:03.404Z',
    created: '2016-10-10T08:15:03.404Z'
}");
Response response = client.target("https://api.instamoney.co/virtual_account_paid_callback_url")
  .request(MediaType.APPLICATION_JSON_TYPE)
  .header("X-CALLBACK-TOKEN",
  "c2tfdGVzdF9PWUNFZkw1eGdMTCtsOFp2SzdRYVNHR1ZNTjczb05FcGszeXorUnhuLzJiUy9MQ2dDUVorZ3c9PTo=")
  .post(payload);

System.out.println("status: " + response.getStatus());
System.out.println("headers: " + response.getHeaders());
System.out.println("body:" + response.readEntity(String.class));

When someone pays into your fixed virtual account, our callback APIs will hit your URL that you already set in dashboard. Our callback API will also hit your URL upon fixed virtual account creations and updates. Please see Create Fixed Virtual Accounts for more details. For further information about callbacks please read these docs.

This example is only used to show the body parameters that send from Instamoney APIs to your callback URL and cannot be tested in here. If you want to test this callback request, use the test feature in dashboard and go to settings -> configuration -> fixed virtual account.

Fixed Virtual Account Payment Callback Request

Example Fixed Virtual Account Payment Callback Request

curl --include \
     --request POST \
     --header "Content-Type: application/json" \
     --header "X-CALLBACK-TOKEN:
     c2tfdGVzdF9PWUNFZkw1eGdMTCtsOFp2SzdRYVNHR1ZNTjczb05FcGszeXorUnhuLzJiUy9MQ2dDUVorZ3c9PTo=" \
     --data-binary "{
    id: \"57fb4e076fa3fa296b7f5a97\",
    payment_id: \"demo-1476087608948_1476087303080\",
    callback_virtual_account_id: \"57fb4df9af86ce19778ad359\",
    owner_id: \"57b4e5181473eeb61c11f9b9\",
    external_id: \"demo-1476087608948\",
    account_number: \"1547\",
    bank_code: \"BNI\",
    amount: 99000,
    transaction_timestamp: \"2016-10-10T08:15:03.080Z\",
    merchant_code: \"8808\",
    sender_name: \"JOHN DOE\",
    updated: \"2016-10-10T08:15:03.404Z\",
    created: \"2016-10-10T08:15:03.404Z\"
}" \
'https://api.instamoney.co/virtual_account_paid_callback_url'
Parameter Description
payment_id Our internal system’s payment ID
callback_virtual_account_id The id field value from the response when the fixed virtual account was created. See Create Fixed Virtual Accounts
owner_id Your user ID
external_id An ID of your choice which you provided upon virtual account creation
account_number This is the virtual account number (excluding the prefix). This works just like a bank account and is what a user will need to enter in their internet banking/ATM to send funds.
bank_code Bank code for the relevant bank, e.g. BNI
amount Nominal amount to transfer
merchant_code The merchant code will be the prefix for the virtual account number, e.g 01234 your_number
id ID of fixed virtual account payment
sender_name Name of the end user that paid into the virtual account. This field is only supported for Sahabat Sampoerna virtual accounts.

Fixed Virtual Account Creation / Update Callback Request

Example Fixed Virtual Account Creation / Update Callback Request

curl --include \
     --request POST \
     --header "Content-Type: application/json" \
     --header "X-CALLBACK-TOKEN:
     c2tfdGVzdF9PWUNFZkw1eGdMTCtsOFp2SzdRYVNHR1ZNTjczb05FcGszeXorUnhuLzJiUy9MQ2dDUVorZ3c9PTo=" \
     --data-binary "{
    id: \"57fb4e076fa3fa296b7f5a97\",
    owner_id: \"5824128aa6f9f9b648be9d76\",
    external_id: \"fixed-va-1487156410\",
    merchant_code: \"88608\",
    account_number: \"886081000123456\",
    bank_code: \"MANDIRI\",
    name: \"John Doe\",
    is_closed: false,
    is_single_use: false,
    status: \"ACTIVE\",
    expiration_date: \"2048-02-15T11:01:52.722Z\",
    updated: \"2016-10-10T08:15:03.404Z\",
    created: \"2016-10-10T08:15:03.404Z\"
}" \
'https://api.instamoney.co/virtual_account_created_callback_url'
Parameter Description
owner_id Your user ID
external_id An ID of your choice which you provided upon request
bank_code Bank code for the relevant bank, e.g. MANDIRI
merchant_code 5-digit merchant prefix to the full virtual account number
name Name for the fixed virtual account
account_number Complete virtual account number (including prefix). This is what a user will need to enter into an ATM or their Internet/mobile banking.
suggested_amount OPTIONAL suggested amount for created fixed virtual account
is_closed value that determines whether a virtual account is closed or not
expected_amount OPTIONAL the amount that is expected when is_closed is true
id Unique ID for the fixed virtual account.
is_single_use value that determines whether a virtual account will be inactive after it is paid
status Status of fixed virtual account.

Fixed Virtual Account Callback Errors

Note that in the case where we don't get a successful response from your servers on the first try, we will retry 2 times more with a 30 second delay between each retry. After 3 failures, we get internal alerts that a callback has failed. Our team will then contact you to resolve the issue.

Get fixed virtual account payment

Endpoint: Get Fixed Virtual Account payment

GET https://api.instamoney.co/callback_virtual_account_payments/payment_id={payment_id}

Example Get Fixed Virtual Account Request

curl https://api.instamoney.co/callback_virtual_account_payments/payment_id={payment_id} -X GET \
    -u sk_test_OYCEfL5xgLL+l8ZvK7QaSGGVMN73oNEpk3yz+Rxn/2bS/LCgCQZ+gw==:

When you receive our callback in your URL, you can verify that the callback you receive is coming from us.

Get Fixed Virtual Account Payment Request

Parameter Description
payment_id
required
string ID of the payment to retrieve

Get Fixed Virtual Account Payment Response

Example Get Fixed Virtual Account Response

{
    "id": "598d91b1191029596846047f",
    "payment_id": "1502450097080",
    "callback_virtual_account_id": "598d5f71bf64853820c49a18",
    "external_id": "demo-1502437214715",
    "merchant_code": "77517",
    "account_number": "1000016980",
    "bank_code": "BNI",
    "amount": 5000,
    "transaction_timestamp": "2017-08-11T11:14:57.080Z"
}
Parameter Description
id ID of the fixed virtual account payment
payment_id Our internal system’s payment ID
callback_virtual_account_id ID of the fixed virtual account payment that was paid
external_id External ID on the fixed virtual account payment
merchant_code 5-digit merchant prefix to the full virtual account number
account_number Account number of the virtual account
bank_code Bank code of the virtual account number
amount Amount that was paid to this virtual account payment
transaction_timestamp Date time that the fixed virtual account was paid

Get Fixed Virtual Account Payment Errors

Error Code Description
CALLBACK_VIRTUAL_ACCOUNT_PAYMENT_NOT_FOUND_ERROR
404
Could not find callback virtual account payment by payment id.

Get fixed virtual account

Endpoint: Get Fixed Virtual Account

GET https://api.instamoney.co/callback_virtual_accounts/{callback_virtual_account_id}

Example Get Fixed Virtual Account Request

curl https://api.instamoney.co/callback_virtual_accounts/{callback_virtual_account_id} -X GET \
  -u sk_test_OYCEfL5xgLL+l8ZvK7QaSGGVMN73oNEpk3yz+Rxn/2bS/LCgCQZ+gw==:

Sometime, you need to know the detail for your fixed virtual account. This endpoint can be used to get the latest details from your fixed virtual account

Get Fixed Virtual Account Request

Parameter Description
callback_virtual_account_id
required
string ID of the fixed virtual account to retrieve

Get Fixed Virtual Account Response

Example Get Fixed Virtual Account Response

{
    "owner_id": "58cd618ba0464eb64acdb246",
    "external_id": "fixed-va-1507867286",
    "bank_code": "BRI",
    "merchant_code": "26215",
    "name": "Steve Wozniak",
    "account_number": "262151000393993",
    "is_single_use": false,
    "status": "ACTIVE",
    "expiration_date": "2048-10-12T17:00:00.000Z",
    "is_closed": false,
    "id": "59e03a976fab8b1850fdf347"
}
Parameter Description
owner_id ID of the business that own the fixed virtual account
external_id An ID of your choice which you provided upon virtual account creation
bank_code Bank code of the virtual account number
merchant_code 4 or 5-digit merchant prefix to the full virtual account number
name Name of the virtual account
account_number Account number of the virtual account
expiration_date Expiration date of the virtual account
is_closed Flag that define the fixed virtual account is close or open
id ID of the fixed virtual account
is_single_use Flag that define the fixed virtual account is single use or multiple use
status Status of fixed virtual account that defines if it’s active or inactive. Status is inactive either because it is a paid single use fixed virtual account or it is already expired.

Get Fixed Virtual Account Payment Errors

Error Code Description
CALLBACK_VIRTUAL_ACCOUNT_NOT_FOUND_ERROR
404
Could not find callback virtual account.

Retail Outlets

Create Fixed Payment Code

Endpoint: Create Fixed Payment Code (FPC)

POST https://api.instamoney.co/fixed_payment_code

One way for your customer to pay through Retail Outlets is by providing them Fixed Payment Code. Fixed payment code is a dedicated payment code under a name you choose, e.g. 'YourCompany - Becca Salim'. You will receive a callback each time this fixed payment code is paid.

Create Fixed Payment Code Request

Example Create Fixed Payment Code Request

curl https://api.instamoney.co/fixed_payment_code -X POST \
   -u sk_test_OYCEfL5xgLL+l8ZvK7QaSGGVMN73oNEpk3yz+Rxn/2bS/LCgCQZ+gw==: \
   -d external_id=demo_fixed_payment_code_123 \
   -d retail_outlet_name=ALFAMART \
   -d name='Rika Sutanto' \
   -d expected_amount=10000
Parameter Description
external_id
required
string An ID of your choice. Often it is unique identifier like a phone number, email or transaction ID. Maximum length allowed is 950 characters.
retail_outlet_name
required
string Name of the fixed payment code you want to create
name
required
string Name of user - this might be used by the Retail Outlets cashier to validate the end user
expected_amount
required
number The amount that is expected to be paid by end customer. The minimum is Rp 10,000 and the maximum is Rp 2,500,000.
payment_code
optional
string The fixed payment code that you want to assign. If you do not send one, one will be picked at random
expiration_date
optional
ISO Date The time when the fixed payment code will be expired
is_single_use
optional
boolean When set to true, the fixed payment code will be inactive after it is paid

Create Fixed Payment Code Response

Example Create Fixed Payment Code Response

{
    "owner_id": "5b614aa8e79f9214007244d4",
    "external_id": "123",
    "retail_outlet_name": "ALFAMART",
    "prefix": "TEST",
    "name": "Rika Sutanto",
    "payment_code": "TEST123456",
    "type": "USER",
    "expected_amount": 10000,
    "is_single_use": true,
    "expiration_date": "2049-07-31T17:00:00.000Z",
    "id": "5b61881e6cc2770f00117f73"
}
Parameter Description
owner_id Your user ID
external_id An ID of your choice which you provided upon request
retail_outlet_name Name for the relevant Retail Outlets, e.g. ALFAMART
prefix 3-6 characters that differentiate your fixed payment code from the others
name Name for the fixed payment code
payment_code Complete fixed payment code (including prefix). This is what a user will need to tell Retail Outlets cashier
expected_amount The amount that is expected to be paid by end customer
is_single_use Value that determines whether a fixed payment code will be inactive after it is paid or not
expiration_date The time when the fixed payment code will be expired
id Unique ID for the fixed payment code

Create Fixed Payment Code Errors

Error Code Description
API_VALIDATION_ERROR
400
Inputs are failing validation. The errors field contains details about which fields are violating validation.
INVALID_JSON_FORMAT
400
The request body is not a valid JSON format.
PAYMENT_CODE_OUTSIDE_RANGE
400
The fixed payment code you want is outside your range.
RETAIL_OUTLET_NOT_SUPPORTED_ERROR
400
The Retail Outlets is not currently supported.
DUPLICATE_PAYMENT_CODE_ERROR
400
The payment code that you want to create is already exist
EXPIRATION_DATE_INVALID_ERROR
400
Invalid custom expiration date because it's earlier than current time.
MINIMUM_EXPECTED_AMOUNT_ERROR
400
The expected amount can only be more than or equal Rp 10,0000
MAXIMUM_EXPECTED_AMOUNT_ERROR
400
The expected amount can only be less than or equal Rp 2,500,000

Update Fixed Payment Code

Endpoint: Update Fixed Payment Code (FPC)

PATCH https://api.instamoney.co/fixed_payment_code/{fixed_payment_code_id}

Fixed Payment Code is so adaptable, and it's all based on your needs. Therefore, we provide you this endpoint to easily update your fixed payment code as you like.

Update Fixed Payment Code Request

Example Create Fixed Payment Code Request

curl https://api.instamoney.co/fixed_payment_code/{fixed_payment_code_id} -X PATCH \
   -u sk_test_OYCEfL5xgLL+l8ZvK7QaSGGVMN73oNEpk3yz+Rxn/2bS/LCgCQZ+gw==: \
   -d expected_amount=20000
   -d name='Joe Contini'
Parameter Description
name
optional
string Name for the fixed payment code
expected_amount
optional
number The amount that is expected to be paid by end customer. The minimum is Rp 10,000 and the maximum is Rp 2,500,000.
expiration_date
optional
ISO Date The time when the fixed payment code will be expired. You can set it to be days in the past to expire fixed payment code immediately

Update Fixed Payment Code Response

Example Update Fixed Payment Code Response

{
    "owner_id": "5b614aa8e79f9214007244d4",
    "external_id": "123",
    "retail_outlet_name": "ALFAMART",
    "prefix": "TEST",
    "name": "Joe Contini",
    "payment_code": "TEST123456",
    "type": "USER",
    "expected_amount": 20000,
    "is_single_use": true,
    "expiration_date": "2049-07-31T17:00:00.000Z",
    "id": "5b61881e6cc2770f00117f73"
}
Parameter Description
owner_id Your user ID
external_id An ID of your choice which you provided upon request
retail_outlet_name Name for the relevant Retail Outlets, e.g. ALFAMART
prefix 3-6 characters that differentiate your fixed payment code from the others
name Name for the fixed payment code
payment_code Complete fixed payment code (including prefix). This is what a user will need to tell Retail Outlets cashier
expected_amount The amount that is expected to be paid by end customer
is_single_use Value that determines whether a fixed payment code will be inactive after it is paid or not
expiration_date The time when the fixed payment code will be expired
id Unique ID for the fixed payment code

Update Fixed Payment Code Errors

Error Code Description
API_VALIDATION_ERROR
400
Inputs are failing validation. The errors field contains details about which fields are violating validation.
INVALID_JSON_FORMAT
400
The request body is not a valid JSON format.
PAYMENT_CODE_OUTSIDE_RANGE
400
The fixed payment code you want is outside your range.
INACTIVE_FIXED_PAYMENT_CODE_ERROR
400
Account number that you want to update is inactive.
MINIMUM_EXPECTED_AMOUNT_ERROR
400
The expected amount can only be more than or equal Rp 10,000
MAXIMUM_EXPECTED_AMOUNT_ERROR
400
The expected amount can only be less than or equal Rp 2,500,000

Get Fixed Payment Code

Endpoint: Get Fixed Payment Code

GET https://api.instamoney.co/fixed_payment_code/{fixed_payment_code_id}

Example Get Fixed Payment Code Request

curl https://api.instamoney.co/fixed_payment_code/{fixed_payment_code_id} -X GET \
  -u sk_test_OYCEfL5xgLL+l8ZvK7QaSGGVMN73oNEpk3yz+Rxn/2bS/LCgCQZ+gw==:

Sometime, you need to know the detail for your fixed payment code. This endpoint can be used to get the latest details from your fixed payment code

Get Fixed Payment Code Request

Parameter Description
fixed_payment_code_id
required
string ID of the fixed payment code to retrieve

Get Fixed Payment Code Response

Example Get Fixed Payment Code Response

{
    "owner_id": "5b614aa8e79f9214007244d4",
    "external_id": "123",
    "retail_outlet_name": "ALFAMART",
    "prefix": "TEST",
    "name": "Joe Contini",
    "payment_code": "TEST123456",
    "type": "USER",
    "expected_amount": 20000,
    "is_single_use": true,
    "expiration_date": "2049-07-31T17:00:00.000Z",
    "id": "5b61881e6cc2770f00117f73"
}
Parameter Description
owner_id Your user ID
external_id An ID of your choice which you provided upon request
retail_outlet_name Name for the relevant Retail Outlets, e.g. ALFAMART
prefix 3-6 characters that differentiate your fixed payment code from the others
name Name for the fixed payment code
payment_code Complete fixed payment code (including prefix). This is what a user will need to tell Retail Outlets cashier
expected_amount The amount that is expected to be paid by end customer
is_single_use Value that determines whether a fixed payment code will be inactive after it is paid or not
expiration_date The time when the fixed payment code will be expired
id Unique ID for the fixed payment code

Get Fixed Payment Code Errors

Error Code Description
FIXED_PAYMENT_CODE_NOT_FOUND_ERROR
404
Could not find fixed payment code.

Fixed Payment Code Callback

Endpoint: Fixed Payment Code Callback

POST https://yourcompany.com/fixed_payment_code_paid_callback_url

When someone pays into your fixed payment code, our callback APIs will hit your URL that you already set in dashboard.

This example is only used to show the body parameters that send from Instamoney APIs to your callback URL and cannot be tested in here. If you want to test this callback request, use the test feature in dashboard and go to settings -> configuration -> retail outlets.

Fixed Payment Code Payment Callback Request

Example Fixed Payment Code Payment Callback Request

curl --include \
    --request POST \
    --url https://yourcompany.com/fixed_payment_code_paid_callback_url \
    --header 'content-type: application/json' \
    --header 'x-callback-token: MuaJALKJSDK12LASHD123kSAKSDHzjahwUWjkasJSDSA12KSNAK21n==' \
    --data '{
  "id": "58a435201b6ce2a355f46070",
  "external_id": "fixed-payment-code-14876410",
  "prefix": "TEST",
  "payment_code": "TEST123",
  "retail_outlet_name": "ALFAMART",
  "name": "John Doe",
  "amount": 123456,
  "status": "SETTLING",
  "transaction_timestamp": "2019-11-08T11:51:28.613Z",
  "payment_id": "1573213888613",
  "fixed_payment_code_payment_id": "5dc556c07a58de7c114f0347",
  "fixed_payment_code_id": "5dc5567bdf120fd64988a79b",
  "owner_id": "5be9b2f03ef77262c2bd49e6"
}'
Parameter Description
id Unique identifier for this transaction
external_id An ID of your choice which you provided upon fixed payment code creation
prefix 3-6 characters that differentiate your fixed payment code from the others
payment_code Complete fixed payment code (including prefix). This is what a user will need to tell Retail Outlets cashier
retail_outlet_name Name for the relevant Retail Outlets, e.g. ALFAMART
name Name for the fixed payment code
amount Nominal amount that is paid
status Status of payment. Possible value(s): SETTLING or COMPLETED
transaction_timestamp Date time that the fixed payment code was paid
payment_id Our internal system’s payment ID that can be used as payment reference
fixed_payment_code_payment_id Unique ID for the fixed payment code payment
fixed_payment_code_id Unique ID for the fixed payment code
owner_id Your user ID

Fixed Payment Code Callback Errors

Note that in the case where we don't get a successful response from your servers on the first try, we will retry 2 times more with a 30 second delay between each retry. After 3 failures, we get internal alerts that a callback has failed. Our team will then contact you to resolve the issue.

Disburse Funds

Disbursements allow you to instruct Instamoney to instantly send money to any bank account across Indonesia on your behalf.

Create disbursement

Endpoint: Create Disbursement

POST https://api.instamoney.co/disbursements

Create Disbursement Request

Example Create Disbursement Request

<?php
  require 'vendor/autoload.php';

  $options['secret_api_key'] = 'sk_test_OYCEfL5xgLL+l8ZvK7QaSGGVMN73oNEpk3yz+Rxn/2bS/LCgCQZ+gw==';

  $instamoneyPHPClient = new InstamoneyClient\InstamoneyPHPClient($options);

  $external_id = 'demo_1475459775872';
  $amount = 17000;
  $bank_code = 'BCA';
  $account_holder_name = 'Bob Jones';
  $account_number = '1231241231';
  $disbursement_options['description'] = 'Reimbursement for shoes';

  $response = $instamoneyPHPClient->createDisbursement($external_id, $amount, $bank_code, $account_holder_name, $account_number, $disbursement_options);
  print_r($response);
?>
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.MediaType;

Client client = ClientBuilder.newClient();
Entity payload = Entity.json("{  'external_id': 'disbursement_12345',  'amount': 500000,  'bank_code': 'BCA',  'account_holder_name': 'Rizky',  'account_number': '1231241231',  'description': 'Custom description'}");
Response response = client.target("https://api.instamoney.co/disbursements")
  .request(MediaType.APPLICATION_JSON_TYPE)
  .header("Authorization", "Basic c2tfdGVzdF9PWUNFZkw1eGdMTCtsOFp2SzdRYVNHR1ZNTjczb05FcGszeXorUnhuLzJiUy9MQ2dDUVorZ3c9PTo=")
  .post(payload);

System.out.println("status: " + response.getStatus());
System.out.println("headers: " + response.getHeaders());
System.out.println("body:" + response.readEntity(String.class));
Header Description
X-IDEMPOTENCY-KEY
optional
string A unique key to prevent processing duplicate requests. Can be your external_id or any GUID. Must be unique across development & production environments.

Characters Special and alphanumeric
Maximum length No maximum characters
Minimum length 1 character
Parameter Description
external_id
required
string ID of the disbursement in your system, used to reconcile disbursements after they have been completed.

Characters Special and alphanumeric
Maximum length 1000 maximum characters
Minimum length 1 character
bank_code
required
string Code of the destination bank

The bank code must match the bank codes here precisely
account_holder_name
required
string Name of account holder as per the bank's or e-wallet's records. Used for verification and error/customer support scenarios.

Characters Special and alphanumeric
Maximum length No maximum characters
Minimum length 1 character
account_number
required
string Destination bank account number. If disbursing to an e-wallet, phone number registered with the e-wallet account.

Characters Numeric and hyphens
BCA required length 10 characters
Other banks maximum length No maximum characters
Other banks minimum length 1 character
E-wallets Phone number registered with the e-wallet (Example: 0812XXXXXX)

*** We support disbursements to virtual accounts of major banks (BRI, BNI, Mandiri, CIMB Niaga, Permata, BTN, and NOBU Bank).
*** We support disbursements to major e-wallets (GoPay, OVO, and Mandiri e-cash).

description
required
string Description to send with the disbursement

Characters Special and alphanumeric
Maximum length No maximum characters
Minimum length 1 character
amount
required
number Amount to disburse

Characters Numerical integers, no decimals
Maximum limit (BCA, Mandiri, BRI, BNI, BNI_SYR, CIMB, CIMB_UUS, PERMATA) No Limit***
Minimum limit (BCA, Mandiri, BRI, BNI, BNI_SYR, CIMB, CIMB_UUS, PERMATA) No Limit
Maximum Limit (Other banks) Rp. 100.000.000
Minimum Limit (Other banks) Rp. 10.000

*** While there is theoretically no maximum transfer limit for transfers to these banks, please note that we may have to report all transaction amounts above Rp 100.000.000 to the financial authorities in Indonesia along with supporting documentation regarding the underlying transactions.

email_to
optional
string[] Email addresses that get notified of disbursement details after the disbursement is completed.
Maximum 3 email addresses accepted.
email_cc
optional
string[] Email addresses that get notified as carbon copy receiver of disbursement details after the disbursement is completed.
Maximum 3 email addresses accepted.
Only allowed if email_to provided.
email_bcc
optional
string[] Email addresses that get notified as blind carbon copy receiver of disbursement details after the disbursement is completed.
Maximum 3 email addresses accepted.
Only allowed if email_to provided.

Create Disbursement Response

Example Create Disbursement Response

{
  "user_id": "5785e6334d7b410667d355c4",
  "external_id": "12345",
  "amount": 1000,
  "bank_code": "BCA",
  "account_holder_name": "RAIDY WIJAYA",
  "disbursement_description": "Refunds for shoes",
  "status": "PENDING",
  "id": "57f1ce05bb1a631a65eee662",
  "email_to": ["test+to1@instamoney.co","test+to2@instamoney.co"],
  "email_cc": ["test+cc@instamoney.co"],
  "email_bcc": ["test+bcc@instamoney.co"]
}
Parameter Description
user_id
required
string Your Instamoney Business ID
external_id
required
string Custom ID of your choice to identify the transaction. Our customers often use a phone number, email address, or transaction/order ID
amount
required
number Amount to disburse
bank_code
required
string Bank code of destination bank or e-wallet. See bank codes
account_holder_name
required
string Name of account holder as per the bank's or e-wallet’s records. Used for verification and error/customer support scenarios
disbursement_description
required
This is the description you give us :)
status
required
string
PENDING Transfer is initiated but not yet completed by bank.
id
required
string Unique disbursement ID
email_to
optional
string[] Email addresses that get notified of disbursement details after the disbursement is completed.
This response parameter is only returned if this field is filled.
email_cc
optional
string[] Email addresses that get notified as carbon copy receiver of disbursement details after the disbursement is completed.
This response parameter is only returned if this field is filled.
email_bcc
optional
string[] Email addresses that get notified as blind carbon copy receiver of disbursement details after the disbursement is completed.
This response parameter is only returned if this field is filled.

Create Disbursement Errors

Error Code Description
API_VALIDATION_ERROR
400
Inputs are failing validation. The errors field contains details about which fields are violating validation.
INVALID_JSON_FORMAT
400
The request body is not a valid JSON format.
DISBURSEMENT_DESCRIPTION_NOT_FOUND_ERROR
400
Disbursement description is not set in Dashboard > Configuration > Disbursement. Add a default description before retrying.
DIRECT_DISBURSEMENT_BALANCE_INSUFFICIENT_ERROR
400
Not enough balance to disburse. Add more balance before retrying.
DUPLICATE_TRANSACTION_ERROR
400
Idempotency key has been used before. Use a unique idempotency key and try again.
BANK_CODE_NOT_SUPPORTED_ERROR
400
Destination bank code is not supported.
RECIPIENT_ACCOUNT_NUMBER_ERROR
400
For transfers to BCA, account_number input needs to be 10 digits. Check the account number length before retrying.
RECIPIENT_AMOUNT_ERROR
400
The transfer amount requested is lower than the prescribed minimum for the chosen destination bank. Amend the transfer amount before retrying.
MAXIMUM_TRANSFER_LIMIT_ERROR
400
The transfer amount requested is higher than the prescribed maximum for the chosen destination bank. Amend the transfer amount before retrying.
SERVER_ERROR
500
Error connecting to our server. Please use Get disbursement by external_id API to check whether the disbursement has already been created. If you receive DIRECT_DISBURSEMENT_NOT_FOUND_ERROR, the disbursement has not been created; please retry the disbursement request in 1-2 hours.

Get disbursement by id

Endpoint: Get Disbursement by id

GET https://api.instamoney.co/disbursements/{disbursement_id}

This endpoint queries the current status of a disbursement. This is often used for checking the status of a transaction.

Get Disbursement Request

Example Get Disbursement Request

curl https://api.instamoney.co/disbursements/57c9010f5ef9e7077bcb96b6 -X GET \
  -u sk_test_OYCEfL5xgLL+l8ZvK7QaSGGVMN73oNEpk3yz+Rxn/2bS/LCgCQZ+gw==:
<?php
  require 'vendor/autoload.php';

  $options['secret_api_key'] = 'sk_test_OYCEfL5xgLL+l8ZvK7QaSGGVMN73oNEpk3yz+Rxn/2bS/LCgCQZ+gw==';

  $instamoneyPHPClient = new InstamoneyClient\InstamoneyPHPClient($options);

  $disbursement_id = '587cc7ea77535fb94bb4e8eb';

  $response = $instamoneyPHPClient->getDisbursement($disbursement_id);
  print_r($response);
?>
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.MediaType;

Client client = ClientBuilder.newClient();
Response response = client.target("https://api.instamoney.co/disbursements/{disbursement_id}")
  .request(MediaType.APPLICATION_JSON_TYPE)
  .header("Authorization", "Basic c2tfdGVzdF9PWUNFZkw1eGdMTCtsOFp2SzdRYVNHR1ZNTjczb05FcGszeXorUnhuLzJiUy9MQ2dDUVorZ3c9PTo=")
  .get();

System.out.println("status: " + response.getStatus());
System.out.println("headers: " + response.getHeaders());
System.out.println("body:" + response.readEntity(String.class));
Parameter Description
disbursement_id
required
string ID of the disbursement to retrieve
The disbursement_id must match the unique disbursement ID provided in our success response at disbursement creation precisely

Get Disbursement Response

Example Get Disbursement Response

{
  "user_id": "5785e6334d7b410667d355c4",
  "external_id": "disbursement_12345",
  "amount": 500000,
  "bank_code": "BCA",
  "account_holder_name": "Rizky",
  "disbursement_description": "Custom description",
  "status": "PENDING",
  "id": "57c9010f5ef9e7077bcb96b6",
  "email_to": ["test+to1@instamoney.co","test+to2@instamoney.co"],
  "email_cc": ["test+cc@instamoney.co"],
  "email_bcc": ["test+bcc@instamoney.co"]
}
Parameter Description
user_id Your Instamoney Business ID
external_id Custom ID set at disbursement creation. Our customers often use a phone number, email address, or transaction/order ID
amount Amount to disburse
bank_code Destination bank code. See bank codes
account_holder_name Bank account name as per the bank's records. Used for verification and error/customer support scenarios
disbursement_description This is the description you give us :)
status PENDING Transfer is initiated.
COMPLETED Bank has confirmed transmission of funds.
FAILED Bank rejected disbursement. We will not retry.
id Unique disbursement ID
email_to Email addresses that get notified of disbursement details after the disbursement is completed.
This response parameter is only returned if this field is filled.
email_cc Email addresses that get notified as carbon copy receiver of disbursement details after the disbursement is completed.
This response parameter is only returned if this field is filled.
email_bcc Email addresses that get notified as blind carbon copy receiver of disbursement details after the disbursement is completed.
This response parameter is only returned if this field is filled.

Get Disbursement Errors

Error Code Description
INVALID_JSON_FORMAT
400
The request body is not a valid JSON format.
INVALID_PERMISSION_ERROR
403
Could not access that disbursement.
DIRECT_DISBURSEMENT_NOT_FOUND_ERROR
404
Could not find direct disbursement.

Get disbursement by external_id

Endpoint: Get Disbursement by external_id

GET https://api.instamoney.co/disbursements?external_id={external_id}

This endpoint queries the current status of all disbursements with requested external_id. This is often used to check the status of a transaction with external_id.

Get Disbursement Request

Example Get Disbursement Request

curl https://api.instamoney.co/disbursements?external_id=72655 -X GET \
  -u sk_test_OYCEfL5xgLL+l8ZvK7QaSGGVMN73oNEpk3yz+Rxn/2bS/LCgCQZ+gw==:
<?php
  require 'vendor/autoload.php';

  $options['secret_api_key'] = 'sk_test_OYCEfL5xgLL+l8ZvK7QaSGGVMN73oNEpk3yz+Rxn/2bS/LCgCQZ+gw==';

  $instamoneyPHPClient = new InstamoneyClient\InstamoneyPHPClient($options);

  $external_id = 'disbursement_12345';

  $response = $instamoneyPHPClient->getDisbursementByExternalId($external_id);
  print_r($response);
?>
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.MediaType;

Client client = ClientBuilder.newClient();
Response response = client.target("https://api.instamoney.co/disbursements?external_id={external_id}")
  .request(MediaType.APPLICATION_JSON_TYPE)
  .header("Authorization", "Basic c2tfdGVzdF9PWUNFZkw1eGdMTCtsOFp2SzdRYVNHR1ZNTjczb05FcGszeXorUnhuLzJiUy9MQ2dDUVorZ3c9PTo=")
  .get();

System.out.println("status: " + response.getStatus());
System.out.println("headers: " + response.getHeaders());
System.out.println("body:" + response.readEntity(String.class));
Query Description
external_id
required
string Custom ID of the disbursement set by the customer at disbursement creation
The external_id must match the external_id used at disbursement creation precisely

Get Disbursement Response

Example Get Disbursement Response

[{
  "user_id": "5785e6334d7b410667d355c4",
  "external_id": "disbursement_12345",
  "amount": 500000,
  "bank_code": "BCA",
  "account_holder_name": "Rizky",
  "disbursement_description": "Custom description",
  "status": "PENDING",
  "id": "57c9010f5ef9e7077bcb96b6"
},{
  "user_id": "5785e6334d7b410667d355c4",
  "external_id": "disbursement_12345",
  "amount": 450000,
  "bank_code": "BNI",
  "account_holder_name": "Jajang",
  "disbursement_description": "Custom description",
  "status": "COMPLETED",
  "id": "5a963089fd5fe5b6508f0b7b",
  "email_to": ["test+to1@instamoney.co","test+to2@instamoney.co"],
  "email_cc": ["test+cc@instamoney.co"],
  "email_bcc": ["test+bcc@instamoney.co"]
}]
Parameter Description
user_id Your Instamoney Business ID
external_id Custom ID set at disbursement creation. Our customers often use a phone number, email address, or transaction/order ID
amount Amount to disburse
bank_code Destination bank code. See bank codes
account_holder_name Bank account name as per the bank's records. Used for verification and error/customer support scenarios
disbursement_description This is the description you give us :)
status PENDING Transfer is initiated.
COMPLETED Bank has confirmed transmission of funds.
FAILED Bank rejected disbursement. We will not retry.
id Unique disbursement ID
email_to Email addresses that get notified of disbursement details after the disbursement is completed.
This response parameter is only returned if this field is filled.
email_cc Email addresses that get notified as carbon copy receiver of disbursement details after the disbursement is completed.
This response parameter is only returned if this field is filled.
email_bcc Email addresses that get notified as blind carbon copy receiver of disbursement details after the disbursement is completed.
This response parameter is only returned if this field is filled.

Get Disbursement Errors

Error Code Description
DIRECT_DISBURSEMENT_NOT_FOUND_ERROR
404
Could not find direct disbursement.

Disbursement callback

Endpoint: Disbursement Callback

POST https://yourcompany.com/disbursement_callback_url
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.MediaType;

Client client = ClientBuilder.newClient();
Entity payload = Entity.json("{ 'id' : '57e214ba82b034c325e84d6e' , 'user_id' : '57c5aa7a36e3b6a709b6e148' , 'external_id' : 'disbursement_123124123' , 'amount' : '50000, 'bank_code' : 'BCA' , 'instamoney_fee_amount' : ', 'account_holder_name' : 'INSTAMONEY' , 'transaction_id' : '57ec8b7e906aa2606ecf8ffc' , 'transaction_sequence' : '1799' , 'disbursement_id' : '57ec8b8130d2d0243f438e11' , 'disbursement_description' : 'Instamoney disbursement' , 'failure_code' : 'INVALID_DESTINATION' , 'is_instant' : 'alse, 'status' : 'FAILED' , 'updated' : '2016-10-10T08:15:03.404Z' , 'created' : '2016-10-10T08:15:03.404Z' , 'email_to' : ' 'test+to1@instamoney.co' , 'test+to2@instamoney.co '], 'email_cc' : ' 'test+cc@instamoney.co '], 'email_bcc' : ' 'test+bcc@instamoney.co ']}");
Response response = client.target("https://yourcompany.com/disbursement_callback_url")
  .request(MediaType.APPLICATION_JSON_TYPE)
  .post(payload);

System.out.println("status: " + response.getStatus());
System.out.println("headers: " + response.getHeaders());
System.out.println("body:" + response.readEntity(String.class));

When a disbursement transaction is successful, our callback APIs will hit your URL that you already set in dashboard. For further information about callbacks please read these docs.

This example is only used to show the body parameters that send from Instamoney APIs to your callback URL. If you want to test this callback request, use the test feature in dashboard and go to Settings -> Configuration -> Disbursement.

Disbursement Callback Request

Example Disbursement Callback Request

curl --include \
     --request POST \
     --header "Content-Type: application/json" \
     --header "X-CALLBACK-TOKEN: c2tfdGVzdF9PWUNFZkw1eGdMTCtsOFp2SzdRYVNHR1ZNTjczb05FcGszeXorUnhuLzJiUy9MQ2dDUVorZ3c9PTo=" \
     --data-binary "{
    \"id\": \"57e214ba82b034c325e84d6e\",
    \"user_id\": \"57c5aa7a36e3b6a709b6e148\",
    \"external_id\": \"disbursement_123124123\",
    \"amount\": 150000,
    \"bank_code\": \"BCA\",
    \"account_holder_name\": \"INSTAMONEY\",
    \"disbursement_description\": \"Instamoney disbursement\",
    \"failure_code\": \"INVALID_DESTINATION\",
    \"is_instant\": false,
    \"status\": \"FAILED\",
    \"updated\": \"2016-10-10T08:15:03.404Z\",
    \"created\": \"2016-10-10T08:15:03.404Z\",
    \"email_to\": [\"test+to1@instamoney.co\", \"test+to2@instamoney.co\"],
    \"email_cc\": [\"test+cc@instamoney.co\"],
    \"email_bcc\": [\"test+bcc@instamoney.co\"]
}" \
'https://yourcompany.com/disbursement_callback_url'
Parameter Description
is_instant Indicates whether the disbursement is being disbursed instantly
user_id Your Instamoney Business ID
external_id Custom ID set at disbursement creation. Our customers often use a phone number, email address, or transaction/order ID
amount Amount to disburse
bank_code Destination bank code. See bank codes
account_holder_name Bank account name as per the bank's records. Used for verification and error/customer support scenarios
disbursement_description This is the description you give us :)
status COMPLETED Bank has confirmed transmission of funds.
FAILED Disbursement failed because of failure code
failure_code (optional) INSUFFICIENT_BALANCE The balance in your account is insufficient to make the disbursement in the desired amount
UNKNOWN_BANK_NETWORK_ERROR The bank networks have returned an unknown error to us. We are unable to predict whether the disbursement will succeed should you retry the same disbursement request.
TEMPORARY_BANK_NETWORK_ERROR The bank networks are experiencing a temporary error. Please retry the disbursement in 1-3 hours
INVALID_DESTINATION The banks have reported that the destination account is unregistered or blocked. If unsure about this, please retry again or contact the destination bank directly regarding the status of the destination account
SWITCHING_NETWORK_ERROR At least one of the switching networks is encountering an issue. Please retry the disbursement in 1-3 hours
REJECTED_BY_BANK The bank has rejected this transaction for unclear reasons. We are unable to predict whether the disbursement will succeed should you retry the same disbursement request.
TRANSFER_ERROR We’ve encountered a fatal error while processing this disbursement. Certain API fields in your request may be invalid. Please contact our customer support team for more information
TEMPORARY_TRANSFER_ERROR We’ve encountered a temporary issue while processing this disbursement. Please retry the disbursement in 1-2 hours

For detailed information regarding the different error codes above, please see Common Errors in Disbursements.
id Unique disbursement ID
email_to Email addresses that get notified of disbursement details after the disbursement is completed.
This callback parameter is only returned if this field is filled.
email_cc Email addresses that get notified as carbon copy receiver of disbursement details after the disbursement is completed.
This callback parameter is only returned if this field is filled.
email_bcc Email addresses that get notified as blind carbon copy receiver of disbursement details after the disbursement is completed.
This callback parameter is only returned if this field is filled.

Disbursement Callback Errors

Note that in the case where we don't get a successful response from your servers on the first try, we will retry 2 times more with a 30 second delay between each retry. After 3 failures, we get internal alerts that a callback has failed. Our team will then contact you to resolve the issue.

Get available disbursement banks

Endpoint: Get Available Disbursement Banks

GET https://api.instamoney.co/available_disbursements_banks

Example Get Available Disbursement Banks Request

curl https://api.instamoney.co/available_disbursements_banks -X GET \
    -u sk_test_OYCEfL5xgLL+l8ZvK7QaSGGVMN73oNEpk3yz+Rxn/2bS/LCgCQZ+gw==:
<?php
  require 'vendor/autoload.php';

  $options['secret_api_key'] = 'sk_test_OYCEfL5xgLL+l8ZvK7QaSGGVMN73oNEpk3yz+Rxn/2bS/LCgCQZ+gw==';

  $instamoneyPHPClient = new InstamoneyClient\InstamoneyPHPClient($options);

  $response = $instamoneyPHPClient->getAvailableDisbursementBanks();
  print_r($response);
?>
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.MediaType;

Client client = ClientBuilder.newClient();
Response response = client.target("https://api.instamoney.co/available_disbursements_banks")
  .request(MediaType.APPLICATION_JSON_TYPE)
  .header("Authorization", "Basic c2tfdGVzdF9PWUNFZkw1eGdMTCtsOFp2SzdRYVNHR1ZNTjczb05FcGszeXorUnhuLzJiUy9MQ2dDUVorZ3c9PTo=")
  .get();

System.out.println("status: " + response.getStatus());
System.out.println("headers: " + response.getHeaders());
System.out.println("body:" + response.readEntity(String.class));

This API endpoint will provide you the current list of banks we support for disbursements. We support transfers to 140+ banks in Indonesia, including some BPDs and BPRs, and virtual accounts of major banks (BRI, BNI, Mandiri, CIMB Niaga, Permata, BTN, and NOBU Bank). We also support disbursements to major e-wallets (GoPay, OVO, and Mandiri e-cash). If you would like us to support payment to a specific destination, please contact us at support@instamoney.co.

Get Available Disbursement Banks Response

Get Available Disbursement Banks Response

[
  {
    "name": "Bank Mandiri",
    "code": "MANDIRI",
    "can_disburse": true,
    "can_name_validate": true
  },
  {
    "name": "Bank Rakyat Indonesia (BRI)",
    "code": "BRI",
    "can_disburse": true,
    "can_name_validate": true
  },
  {
    "name": "Bank Central Asia (BCA)",
    "code": "BCA",
    "can_disburse": true,
    "can_name_validate": true
  }
]
Parameter Description
name Full name of the bank or e-wallet
code Code of the bank or e-wallet you would like to disburse to

eWallets

eWallet payment channel allows you to receive payments directly from top ewallets provider in Indonesia, such as OVO.

Create Payment

Endpoint: Create Payment

POST https://api.instamoney.co/ewallets

OVO

Create Payment Request

Example: Create Payment Request

curl https://api.instamoney.co/ewallets -X POST \
   -u sk_test_vynfjIxiKTiEIJXjeMuKWSmQFTAcmwpqdV7oUvpsYWkzd6oifq3vudl3O3pjlh0: \
   -H "x-api-version: 2020-02-01" \
   -d external_id='ovo-ewallet' \
   -d amount=1000 \
   -d phone='08123123123'\
   -d ewallet_type='OVO'
  <?php
      $url = 'https://api.instamoney.co/ewallets';
      $apiKey = 'sk_test_vynfjIxiKTiEIJXjeMuKWSmQFTAcmwpqdV7oUvpsYWkzd6oifq3vudl3O3pjlh0:';
      $headers = [];
      $headers[] = 'Content-Type: application/json';
      $data = [
          'external_id ' => 'hello-ewallet',
          'amount' => 1000,
          'phone' => '08123123123',
          'ewallet_type' => 'OVO'
      ];

      $curl = curl_init();

      $payload = json_encode($data);
      curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
      curl_setopt($curl, CURLOPT_USERPWD, $apiKey.":");
      curl_setopt($curl, CURLOPT_URL, $url);
      curl_setopt($curl, CURLOPT_POST, true);
      curl_setopt($curl, CURLOPT_POSTFIELDS, $payload);
      curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);

      $result = curl_exec($curl);
      echo $result;
Parameter Description
external_id
required
string An ID of your choice. Often it is unique identifier like a phone number, email or transaction ID.
Note: The only allowed punctuation is -.
Note: Maximum length allowed is 1000 characters.
Note: It has to be unique per payment request.
amount
required
number Amount end-customer will pay.
Note: minimum amount is 1 IDR and maximum is 10,000,000 IDR
phone
required
string Phone number of end-customer (e.g. 08123123123)
Note: End-customer must have an active ewallet account registered to Indonesian phone number prior to payment request.
Note: Phone number format should always be "088889998888" (not using "+62").
ewallet_type
required
string ewallet_type must be in capital letters - 'OVO'

Create Payment API Response

Example: Create Ewallet Payment API Success Response

{
  "business_id": "585te55dst9791ing4009123",
  "external_id": "ovo-ewallet",
  "amount": 1000,
  "phone": "08123123123",
  "ewallet_type": "OVO",
  "status": "PENDING",
  "created": "2020-02-20T00:00:00.000Z",
}
Parameter Description
business_id
required
string Unique identifier for the merchant
external_id
required
string Unique identifier for the payment request of a merchant
amount
required
number Amount requested
phone
required
string Phone number of the end user
ewallet_type
required
string Type of eWallet. Value: OVO
status
required
string Status of payment. Value: PENDING
created
required
string Timestamp ISO 8601 when the payment was requested (in UTC)

Create Payment API Response Errors

Example: Create Ewallet Payment API Error Response

{
    "error_code": "DUPLICATE_PAYMENT_REQUEST_ERROR",
    "message": "There is already a payment request with external_id: ovo-ewallet-testing-id-12345"
}
Error Code Description
API_VALIDATION_ERROR
422
There is invalid input in one of the required request fields.
DUPLICATE_PAYMENT_REQUEST_ERROR
400
The payment with the same external_id has already been made before.
EWALLET_TYPE_NOT_SUPPORTED
422
Your requested ewallet_type is not supported yet
REQUEST_FORBIDDEN_ERROR
403
API key in use does not have necessary permissions to perform the request. Please assign proper permissions for the key. Learn more here

Get Payment Status

Endpoint: Get Payment Status

GET https://api.instamoney.co/ewallets?external_id=<your ewallet payment ext id>&ewallet_type=<your ewallet type>

This endpoint is used to get payment status of an single payment. You need to specify the external_id and ewallet_type.

Get Payment Status Request

Example: Get Payment Status Request

curl https://api.instamoney.co/ewallets\?external_id\='hello-ewallet'\&ewallet_type\='OVO' \
   -X GET \
   -u sk_test_vynfjIxiKTiEIJXjeMuKWSmQFTAcmwpqdV7oUvpsYWkzd6oifq3vudl3O3pjlh0:
  <?php
      $url = 'https://api.instamoney.co/ewallets';
      $apiKey = 'sk_test_vynfjIxiKTiEIJXjeMuKWSmQFTAcmwpqdV7oUvpsYWkzd6oifq3vudl3O3pjlh0:';
      $headers = [];
      $headers[] = 'Content-Type: application/json';

      $externalId = 'hello-ewallet';
      $ewalletType = 'OVO';

      $urlWithParams = $url . '?external_id=' . $externalId . '&ewallet_type=' . $ewalletType;

      $curl = curl_init();

      curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
      curl_setopt($curl, CURLOPT_USERPWD, $apiKey.":");
      curl_setopt($curl, CURLOPT_URL, $urlWithParams);
      curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);

      $result = curl_exec($curl);
      echo $result;
Parameter Description
external_id
required
string An ID of your choice. Often it is unique identifier like a phone number, email or transaction ID. Maximum length allowed is 1000 characters.
ewallet_type
required
string The type of ewallet to be paid. Must be in capital letters.
Supported ewallet types: OVO

Get Payment Status API Response

Example: Get Payment Status Success Response

{
  "amount": 777777,
  "external_id": "demo_hello_world",
  "transaction_date": "2019-04-07T01:35:46.658Z",
  "business_id": "5850eteStin791bd40096364",
  "ewallet_type": "OVO",
  "status": "COMPLETED"
}
Status Description
COMPLETED Payment transaction for specified external_id is successfully
PENDING Payment transaction for specified external_id is awaiting approval by OVO user
FAILED Payment transaction for specified external_id has failed and is not completed (e.g. user did not complete the payment process or payment session timed out)

Get Payment Status API Response Errors

Example: Get Payment Status Error Response

{
  "error_code": "PAYMENT_NOT_FOUND_ERROR",
  "message": "Payment not found"
}
Error Code Description
PAYMENT_NOT_FOUND_ERROR
404
Payment not found
REQUEST_FORBIDDEN_ERROR
403
API key in use does not have necessary permissions to perform the request. Please assign proper permissions for the key. Learn more here

Payment Status Callback

You need to provide an endpoint in your system to receive payment callback notification from our system. You will receive the callback when end-customer completed the payment for OVO. The payment callback notification will be sent as POST request to the "callback_url" that you have set in the dashboard. Note: Please give this notification a response back with status 200 so we know that our notification is received.

OVO

Payment Callback Payload

Example: Success Payment Callback Payload

{
  "event": "ewallet.payment",
  "id": "6bb25ae6-cf57-437a-9b36-7ad2ee17b727",
  "external_id": "ECLrAZPq8F6",
  "business_id": "5850eteStin791bd40096364",
  "phone": "081234567890",
  "ewallet_type": "OVO",
  "amount": 20000,
  "created": "2019-11-01T12:34:56.007Z",
  "status": "COMPLETED"
}
Parameter Description
event required string Available value: "ewallet.payment"
id required string Unique identifier generated for the payment (payment_id)
external_id required string Unique identifier for the payment request of a merchant
business_id required string Unique identifier for the merchant
phone required string Phone number of the end user
ewallet_type required string Type of eWallet. Value: OVO
amount required number Amount paid
status required string Status of payment.
Possible values: FAILED, COMPLETED
failure_code optional string If the payment FAILED, we include a failure code for more details on the failure.
Possible values: See Error Code column in this table
created optional string If the payment is COMPLETED, we include the timestamp ISO 8601 when the payment was made (in UTC)

Payment Callback Payload Failures

Example: Failed Payment Callback Payload

{
  "event": "ewallet.payment",
  "id": "6bb25ae6-cf57-437a-9b36-7ad2ee17b727",
  "external_id": "ECLrAZPq8F6",
  "business_id": "5850eteStin791bd40096364",
  "phone": "081234567890",
  "ewallet_type": "OVO",
  "amount": 20000,
  "failure_code": "USER_DECLINED_THE_TRANSACTION",
  "status": "FAILED"
}
Failure Code Failure Message
USER_DID_NOT_AUTHORIZE_THE_PAYMENT User did not authorize the payment request within time limit
USER_DECLINED_THE_TRANSACTION User declined the payment request
PHONE_NUMBER_NOT_REGISTERED Phone number the user tried to pay is not registered
EWALLET_APP_UNREACHABLE The ewallet provider/server can't reach the user ewallet app/phone. Common cases are the ewallet app is uninstalled
OVO_TIMEOUT_ERROR There was a connection timeout from the OVO app to the OVO server
CREDENTIALS_ERROR The merchant is not registered in e-wallet provider system
ACCOUNT_AUTHENTICATION_ERROR User authentication has failed
ACCOUNT_BLOCKED_ERROR Unable to process the transaction because the user account is blocked
SENDING_TRANSACTION_ERROR Error while sending transaction notification to OVO
EXTERNAL_ERROR There is an error on the e-wallet provider side

Testing Payment

In development mode, you can use these amount values to simulate payment and error cases. When using these numbers, you can use any external-id and appropriately formatted Indonesian phone number. Errors will be received through merchant provided callback endpoint.

Testing Scenarios

Scenario Detail Scenario Amount
Success Response for a successfully executed e-wallet transaction Any amount not used as magic number
User Did Not Authorize End customer failed to authorize within 30 seconds 80002
Account Block Error Unable to process the transaction because the user account is blocked 80003
Sending Transaction Error There's an error when Instamoney sends a request to the e-wallet provider 80004
User Declined End customer declined the transaction 80005
Phone Number Not Registered The end user's phone number is not registered in the e-wallet provider 80006
eWallet APP Unreachable The e-wallet provider/server can't reach the end user's e-wallet app/phone. Common root cause is the e-wallet app is not installed or netowrk errors 80007
OVO Timeout Error There was a connection timeout from the OVO app to the OVO server 80008
Credentials Error The merchant is not registered in e-wallet provider system 80009
Account Authentication Error There is an error on the e-wallet provider side 80010
External Error There is an error on the e-wallet provider side 80011

Customers

Customers are your end-customers. This can be used to easily identify linked accounts for a specific end-customer in direct debit.

Create Customer

A customer object is required in order to link a payment method for direct debit. This allows you to easily link and track payment methods and transactions.

Endpoint: Create Customer

POST https://api.instamoney.co/customers

Create Customer - Request

Example Create Customer Request

curl https://api.instamoney.co/customers -X POST \
   -H 'Content-Type: application/json' \
   -u sk_test_OYCEfL5xgLL+l8ZvK7QaSGGVMN73oNEpk3yz+Rxn/2bS/LCgCQZ+gw==: \
   --data '
     {
      "external_id": "r-1234",
      "customer_type": "INDIVIDUAL",
      "given_name": "Ichwano",
      "surname": "Sembo",
      "address": {
          "country_code": "ID",
          "province": "DKI Jakarta",
          "city": "Jakarta Selatan",
          "line_1": "Jl. Senayan 1 No.15"
      },
      "date_of_birth": "11-01-1990",
      "identification": {
          "ktp_number": "0987654321320987",
          "npwp_number": "098765432132098"
      },
      "email": "ichwano@email.com",
      "mobile_number": "+628111555777",
      "phone_number": "+622199990000"
    }
   '
<?php
  $url = "https://api.instamoney.co/customers";
  $apiKey = "sk_test_OYCEfL5xgLL+l8ZvK7QaSGGVMN73oNEpk3yz+Rxn/2bS/LCgCQZ+gw==:";
  $headers = [];
  $headers[] = "Content-Type: application/json";
  $data = [
    "external_id" => "r-1234",
    "customer_type" => "INDIVIDUAL",
    "given_name" => "Ichwano",
    "surname" => "Sembo",
    "address" => [
      "country_code" => "ID",
      "province" => "DKI Jakarta",
      "city" => "Jakarta Selatan",
      "line_1" => "Jl. Senayan 1 No.15"
    ],
    "date_of_birth" => "11-01-1990",
    "identification" => [
      "ktp_number" => "0987654321320987",
      "npwp_number" => "098765432132098"
    ],
    "email" => "ichwano@email.com",
    "mobile_number" => "+628111555777",
    "phone_number" => "+622199990000"
  ];

  $curl = curl_init();

  $payload = json_encode($data);
  curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
  curl_setopt($curl, CURLOPT_USERPWD, $apiKey.":");
  curl_setopt($curl, CURLOPT_URL, $url);
  curl_setopt($curl, CURLOPT_POST, true);
  curl_setopt($curl, CURLOPT_POSTFIELDS, $payload);
  curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);

  $result = curl_exec($curl);
  echo $result;
Request Body Parameter Description
external_id
required
string Your unique id for this customer

Characters Special and alphanumeric
Maximum length 100 maximum characters
customer_type
required
string Legal entity.
Valid values: INDIVIDUAL or BUSINESS
given_name
conditionally required
string Given name(s). Required if customer_type is INDIVIDUAL. Only allowed if customer_type is INDIVIDUAL
surname
optional
string Surname of the customer
business_name
conditionally required
string Required if customer_type is BUSINESS. Only allowed if customer_type is BUSINESS
address
optional
object Customer's address
address.country_code
optional
string Customer’s country. 2-letter ISO 3166-2 country code. Refer to code standard here. If customer_type is BUSINESS, the country in which the corporate entity is registered. If customer_type is INDIVIDUAL, a country in which the customer holds nationality/td>
address.state
optional
string Customer’s state
address.province
optional
string Customer’s province
address.city
optional
string Customer’s city
address.suburb
optional
string Customer’s suburb
address.postal_code
optional
string Customer’s postal code
address.line_1
optional
string First line of customer’s address. Typically used for building name and / or apartment number
address.line_2
optional
string Second line of customer’s address. Typically used for street name and building number
date_of_birth
optional
string Date of Birth. Only allowed if customer_type is INDIVIDUAL. ISO 8601 format YYYY-MM-DD
date_of_registration
optional
string Date of Registration. Only allowed if customer_type is BUSINESS. ISO 8601 format YYYY-MM-DD
identification
optional
object A legal document that verifies the identity of the customer
identification.ktp_number
optional
string Kartu Tanda Penduduk (national identity card number) of the customer.
Only allowed if customer_type is INDIVIDUAL
Characters 16 characters
identification.npwp_number
optional
string Nomor Pokok Wajib Pajak (tax number) of the customer
Only allowed if customer_type is INDIVIDUAL
Characters 15 characters
identification.drivers_license
optional
string Surat Izin Mengemudi (driver’s licence) number of the customer
Only allowed if customer_type is INDIVIDUAL
Characters 14 characters
identification.passport_number
optional
string Passport number of the customer.
Only allowed if customer_type is INDIVIDUAL
If provided, should provide passport_country. In the case of multiple passports, please choose the passport of the country closest to Indonesia
identification.country
conditionally required
string Passport country of the customer.
Only allowed if customer_type is INDIVIDUAL. 2-letter ISO 3166-2 country code. Refer to code standard here.
Required if passport_number is provided.
identification.business_tax_id
optional
string Tax identification number of the business in its country of registration.
Examples:
- Nomor Pokok Wajib Pajak for indonesian businesses
- Business Registration number for Hong Kong businesses
- Unique Entity Number for Singaporean businesses
Only allowed if customer_type is BUSINESS. If provided, should provide business_tax_id_country.
identification.business_tax_id_country
conditionally required
string Country for tax identification number of the business.
Only allowed if customer_type is BUSINESS. 2-letter ISO 3166-2 country code. Refer to code standard here. Required if business_tax_id is provided
email
optional
string Customer’s email address. Recommended if you want to notify the customer of the transaction status
Should include the top-level domain name
Example: abc@email.com
mobile_number
optional
string Customer’s mobile number with international prefix. Recommended if you want to notify the customer of the transaction status
Example: +62812XXXXXX
phone_number
optional
string Customer’s land line or alternate phone number with international prefix
Example: +6221XXXXXXXX

Create Customer - Response

Example Create Customer Success Response

{
  "id": "5c1774e76966b43a5b8198fb",
  "external_id": "r-1234",
  "customer_type": "INDIVIDUAL",
  "given_name": "Ichwano",
  "surname": "Sembo",
  "address": {
      "country_code": "ID",
      "province": "DKI Jakarta",
      "city": "Jakarta Selatan",
      "line_1": "Jl. Senayan 1 No.15"
  },
  "date_of_birth": "11-01-1990",
  "identification": {
      "ktp_number": "0987654321320987",
      "npwp_number": "098765432132098"
  },
  "email": "ichwano@email.com",
  "mobile_number": "+628111555777",
  "phone_number": "+622199990000",
  "created": "2018-12-12T13:50:12.000Z",
  "updated": "2018-12-12T13:50:12.000Z"
}
Parameter Description
id string Unique ID generated by Instamoney for the particular end-customer
external_id string Identifier you provided during request
customer_type string Type of customer: INDIVIDUAL or BUSINESS
given_name string If customer_type is INDIVIDUAL: Primary of first name/s of the customer
surname string If customer_type is INDIVIDUAL: Surname of the customer
business_name string If customer_type is BUSINESS: Name of business
address object Object containing the specific customer's address information
date_of_birth string If customer_type is INDIVIDUAL: Date of birth of the customer in YYYY-MM-DD format
date_of_registration string If customer_type is INDIVIDUAL: Date of registration of the business in YYYY-MM-DD format
identification object A legal document that verifies the identity of the customer
mobile_number string Mobile number of the customer
email string Email address of the customer
phone_number string Alternate or landline phone number
created object Timestamp in ISO 8601 GMT+0 when the customer object was made
updated object Timestamp in ISO 8601 GMT+0 when the customer object was last updated

Create Customer - Errors

See other common errors here.

Error Code Description
API_VALIDATION_ERROR
400
Inputs are failing validation. The errors field contains details about which fields are violating validation
INVALID_JSON_FORMAT
400
The request body is not a valid JSON format
DUPLICATE_CUSTOMER_ERROR
400
The external_id entered has been used before. Please enter a unique external_id and try again

Update Customer

Updates an existing customer

Endpoint: Update Customer

PUT https://api.instamoney.co/customers/:id

Update Customer - Request

Example Update Customer Request

curl https://api.instamoney.co/customers/5c1774e76966b43a5b8198fb -X PUT \
   -H 'Content-Type: application/json' \
   -u sk_test_OYCEfL5xgLL+l8ZvK7QaSGGVMN73oNEpk3yz+Rxn/2bS/LCgCQZ+gw==: \
   --data '{
     {
      "given_name": "Ahmad",
      "surname": "Shahab",
      "phone_number": "+622199990000"
    }
   }'
Request Body Parameter Description
external_id
optional
string Your unique id for this customer

Characters Special and alphanumeric
Maximum length 100 maximum characters
given_name
optional
string Given name(s). Required if customer_type is INDIVIDUAL. Only allowed if customer_type is INDIVIDUAL
surname
optional
string Surname of the customer
business_name
optional
string Required if customer_type is BUSINESS. Only allowed if customer_type is BUSINESS
address
optional
object Customer's address
address.country_code
optional
string Customer’s country. 2-letter ISO 3166-2 country code. Refer to code standard here. If customer_type is BUSINESS, the country in which the corporate entity is registered. If customer_type is INDIVIDUAL, a country in which the customer holds nationality/td>
address.state
optional
string Customer’s state
address.province
optional
string Customer’s province
address.city
optional
string Customer’s city
address.suburb
optional
string Customer’s suburb
address.postal_code
optional
string Customer’s postal code
address.line_1
optional
string First line of customer’s address. Typically used for building name and / or apartment number
address.line_2
optional
string Second line of customer’s address. Typically used for street name and building number
date_of_birth
optional
string Date of Birth. Only allowed if customer_type is INDIVIDUAL. ISO 8601 format YYYY-MM-DD
date_of_registration
optional
string Date of Registration. Only allowed if customer_type is BUSINESS. ISO 8601 format YYYY-MM-DD
identification
optional
object A legal document that verifies the identity of the customer
identification.ktp_number
optional
string Kartu Tanda Penduduk (national identity card number) of the customer.
Only allowed if customer_type is INDIVIDUAL
Characters 16 characters
identification.npwp_number
optional
string Nomor Pokok Wajib Pajak (tax number) of the customer
Only allowed if customer_type is INDIVIDUAL
Characters 15 characters
identification.drivers_license
optional
string Surat Izin Mengemudi (driver’s licence) number of the customer
Only allowed if customer_type is INDIVIDUAL
Characters 14 characters
identification.passport_number
optional
string Passport number of the customer.
Only allowed if customer_type is INDIVIDUAL
If provided, should provide passport_country. In the case of multiple passports, please choose the passport of the country closest to Indonesia
identification.country
conditionally required
string Passport country of the customer.
Only allowed if customer_type is INDIVIDUAL. 2-letter ISO 3166-2 country code. Refer to code standard here.
Required if passport_number is provided.
identification.business_tax_id
optional
string Tax identification number of the business in its country of registration.
Examples:
- Nomor Pokok Wajib Pajak for indonesian businesses
- Business Registration number for Hong Kong businesses
- Unique Entity Number for Singaporean businesses
Only allowed if customer_type is BUSINESS. If provided, should provide business_tax_id_country.
identification.business_tax_id_country
conditionally required
string Country for tax identification number of the business.
Only allowed if customer_type is BUSINESS. 2-letter ISO 3166-2 country code. Refer to code standard here. Required if business_tax_id is provided
email
optional
string Customer’s email address. Recommended if you want to notify the customer of the transaction status
Should include the top-level domain name
Example: abc@email.com
mobile_number
optional
string Customer’s mobile number with international prefix. Recommended if you want to notify the customer of the transaction status
Example: +62812XXXXXX
phone_number
optional
string Customer’s land line or alternate phone number with international prefix
Example: +6221XXXXXXXX

Update Customer - Response

Example Update Customer Success Response

{
  "id": "5c1774e76966b43a5b8198fb",
  "external_id": "r-1234",
  "customer_type": "INDIVIDUAL",
  "given_name": "Ahmad",
  "surname": "Shahab",
  "address": {
      "country_code": "ID",
      "province": "DKI Jakarta",
      "city": "Jakarta Selatan",
      "line_1": "Jl. Senayan 1 No.15"
  },
  "date_of_birth": "11-01-1990",
  "identification": {
      "ktp_number": "0987654321320987",
      "npwp_number": "098765432132098"
  },
  "email": "ichwano@email.com",
  "mobile_number": "+628111555777",
  "phone_number": "+622199990000",
  "created": "2018-12-12T13:50:12.000Z",
  "updated": "2018-12-12T13:50:12.000Z"
}
Parameter Description
id string Unique ID generated by Instamoney for the particular end-customer
external_id string Identifier you provided during request
customer_type string Type of customer: INDIVIDUAL or BUSINESS
given_name string If customer_type is INDIVIDUAL: Primary of first name/s of the customer
surname string If customer_type is INDIVIDUAL: Surname of the customer
business_name string If customer_type is BUSINESS: Name of business
address object Object containing the specific customer's address information
date_of_birth string If customer_type is INDIVIDUAL: Date of birth of the customer in YYYY-MM-DD format
date_of_registration string If customer_type is INDIVIDUAL: Date of registration of the business in YYYY-MM-DD format
identification object A legal document that verifies the identity of the customer
mobile_number string Mobile number of the customer
email string Email address of the customer
phone_number string Alternate or landline phone number
created object Timestamp in ISO 8601 GMT+0 when the customer object was made
updated object Timestamp in ISO 8601 GMT+0 when the customer object was last updated

Update Customer - Errors

See other common errors here.

Error Code Description
API_VALIDATION_ERROR
400
Inputs are failing validation. The errors field contains details about which fields are violating validation
INVALID_JSON_FORMAT
400
The request body is not a valid JSON format
CUSTOMER_NOT_FOUND_ERROR
400
Could not find customer.
DUPLICATE_CUSTOMER_ERROR
400
The external_id entered has been used before. Please enter a unique external_id and try again

Get Customer by Reference ID

Returns an array with a single object which contains the customer corresponding to the unique external_id. Returns an empty array if there is no customer corresponding to the external_id.

Endpoint: Get Customer by Reference ID

GET https://api.instamoney.co/customers?external_id={external_id}

Get Customer by Reference ID - Request

Example Get Customer by Reference ID Request

curl https://api.instamoney.co/customers?external_id=72655 -X GET \
  -u sk_test_OYCEfL5xgLL+l8ZvK7QaSGGVMN73oNEpk3yz+Rxn/2bS/LCgCQZ+gw==:
<?php
  $url = "https://api.instamoney.co/customers";
  $apiKey = "sk_test_OYCEfL5xgLL+l8ZvK7QaSGGVMN73oNEpk3yz+Rxn/2bS/LCgCQZ+gw==:";
  $headers = [];
  $headers[] = "Content-Type: application/json";

  $queryString = "?external_id=72655";

  $curl = curl_init();

  $payload = json_encode($data);
  curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
  curl_setopt($curl, CURLOPT_USERPWD, $apiKey.":");
  curl_setopt($curl, CURLOPT_URL, $url.$queryString);
  curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "GET");
  curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);

  $result = curl_exec($curl);
  echo $result;
Query String Parameter Description
external_id
optional
string Unique ID you provided in the Create Customer request
The external_id must match the external_id used at customer creation precisely

Get Customer by External ID - Response

Example Get Customer by Reference ID Success Response

[{
  "id": "5c1774e76966b43a5b8198fb",
  "external_id": "r-1234",
  "customer_type": "INDIVIDUAL",
  "given_name": "Ichwano",
  "surname": "Sembo",
  "address": {
      "country_code": "ID",
      "province": "DKI Jakarta",
      "city": "Jakarta Selatan",
      "line_1": "Jl. Senayan 1 No.15"
  },
  "date_of_birth": "11-01-1990",
  "identification": {
      "ktp_number": "0987654321320987",
      "npwp_number": "098765432132098"
  },
  "email": "ichwano@email.com",
  "mobile_number": "+628111555777",
  "phone_number": "+622199990000",
  "created": "2018-12-12T13:50:12.000Z",
  "updated": "2018-12-12T13:50:12.000Z"
}]
Parameter Description
id string Unique ID generated by Instamoney for the particular end-customer
external_id string Identifier you provided during request
customer_type string Type of customer: INDIVIDUAL or BUSINESS
given_name string If customer_type is INDIVIDUAL: Primary of first name/s of the customer
surname string If customer_type is INDIVIDUAL: Surname of the customer
business_name string If customer_type is BUSINESS: Name of business
address object Object containing the specific customer's address information
date_of_birth string If customer_type is INDIVIDUAL: Date of birth of the customer in YYYY-MM-DD format
date_of_registration string If customer_type is INDIVIDUAL: Date of registration of the business in YYYY-MM-DD format
identification object A legal document that verifies the identity of the customer
mobile_number string Mobile number of the customer
email string Email address of the customer
phone_number string Alternate or landline phone number
created object Timestamp in ISO 8601 GMT+0 when the customer object was made
updated object Timestamp in ISO 8601 GMT+0 when the customer object was last updated

Get Customer by External ID - Errors

See other common errors here.

Direct Debit

Direct Debit enables merchants to pull payments directly from their end user’s account bank balance by linking their debit card.

Initialize Linked Account Tokenization

Account authorizations are represented by linked account tokens. This endpoint initializes the authorization process and linked account token creation.

Endpoint: Initialize Linked Account Tokenization

POST https://api.instamoney.co/linked_account_tokens/auth

Initialize Linked Account Tokenization - Request

Example Initialize Linked Account Tokenization Request

curl https://api.instamoney.co/linked_account_tokens/auth -X POST \
   -u sk_test_vynfjIxiKTiEIJXjeMuKWSmQFTAcmwpqdV7oUvpsYWkzd6oifq3vudl3O3pjlh0: \
   -H 'Content-Type: application/json' \
   --data-raw '{
    "customer_id": "ba830b92-4177-476e-b097-2ad5ae4d3e55",
    "channel_code": "DC_BRI",
    "properties": {
        "account_mobile_number": "62818555988",
        "card_last_four": "1234",
        "card_expiry": "06/24",
        "account_email": "email@email.com"
    }
}'
<?php
  $url = "https://api.instamoney.co/linked_account_tokens/auth";
  $apiKey = "sk_test_vynfjIxiKTiEIJXjeMuKWSmQFTAcmwpqdV7oUvpsYWkzd6oifq3vudl3O3pjlh0:";
  $headers = [];
  $headers[] = "Content-Type: application/json";
  $data = [
    "customer_id" => "ba830b92-4177-476e-b097-2ad5ae4d3e55",
    "channel_code" => "DC_BRI",
    "properties" => [
      "account_mobile_number" => "62818555988",
      "card_last_four" => "1234",
      "card_expiry" => "06/24",
      "account_email" => "email@email.com"
    ]
  ];

  $curl = curl_init();

  $payload = json_encode($data);
  curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
  curl_setopt($curl, CURLOPT_USERPWD, $apiKey.":");
  curl_setopt($curl, CURLOPT_URL, $url);
  curl_setopt($curl, CURLOPT_POST, true);
  curl_setopt($curl, CURLOPT_POSTFIELDS, $payload);
  curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);

  $result = curl_exec($curl);
  echo $result;
Request Body Parameter Description
customer_id
required
string ID of the customer object to which the account token will be linked to
channel_code
required
string Identifier for the specific channel of the account to be linked. Code must be in uppercase.

Supported channel codes: DC_BRI
properties
optional
object JSON that contains information needed to proceed with authorization. Values inside properties change based on type of account:

For Debit Card Linking (BRI):
Key Value
account_mobile_number
required
Mobile number of the customer registered to the partner channel
card_last_four
required
Last four digits of the debit card
card_expiry
required
Expiry month and year of the debit card (in MM/YY format)
account_email
required
Email address of the customer that is registered to the partner channel
metadata
optional
object A free-format JSON for additional information that you may use.

Initialize Linked Account Tokenization - Response

Example Initialize Linked Account Tokenization Success Response

{
    "id": "lat-aa620619-124f-41db-995b-66a52abe036a",
    "customer_id": "ba830b92-4177-476e-b097-2ad5ae4d3e55",
    "channel_code": "DC_BRI",
    "authorizer_url": null,
    "status": "PENDING",
    "metadata": null
}
Parameter Description
id string Unique ID generated by Instamoney for the particular linked account token authorization
customer_id string Customer object ID
channel_code string Code identifier for the channel
authorizer_url string URL of the authorization webpage to be rendered if linking via online banking access.
For debit card linking (BRI), this will always be null; proceed to the "Validate OTP for Linked Account Token" step instead.
status string Status of the authorization. Will always be PENDING for successful initiations.
metadata object A free-format JSON for additional information that you provded during request.

Initialize Linked Account Tokenization - Errors

See other common errors here.

Error Code Description
CHANNEL_CODE_NOT_SUPPORTED_ERROR
400
Provided channel_code is not supported or has not yet activated for this account.
CUSTOMER_NOT_FOUND_ERROR
400
Provided customer_id in the request does not exist or access is unauthorized
CHANNEL_UNAVAILABLE
503
The target channel is currently unavailable. This is possibly due to partner channel downtime or error.

Validate OTP for Linked Account Token

Account linking for debit cards requires an OTP to proceed. Upon successful initialization, the bank will send an OTP to the customer's registered mobile number directly. This endpoint validates the OTP with the bank.

Endpoint: Validate OTP for Linked Account Token

POST https://api.instamoney.co/linked_account_tokens/{linked_account_token_id}/validate_otp

Validate OTP for Linked Account Token - Request

Example Validate OTP for Linked Account Token Request

curl https://api.instamoney.co/linked_account_tokens/lat-aa620619-124f-41db-995b-66a52abe036a/validate_otp -X POST \
   -u sk_test_vynfjIxiKTiEIJXjeMuKWSmQFTAcmwpqdV7oUvpsYWkzd6oifq3vudl3O3pjlh0: \
   -H 'Content-Type: application/json' \
   --data-raw '{
    "otp_code":123456
}'
<?php
  $linkedAccountTokenId = "lat-aa620619-124f-41db-995b-66a52abe036a";
  $url = "https://api.instamoney.co/linked_account_tokens/" . $linkedAccountTokenId . "/validate_otp";
  $apiKey = "sk_test_vynfjIxiKTiEIJXjeMuKWSmQFTAcmwpqdV7oUvpsYWkzd6oifq3vudl3O3pjlh0:";
  $headers = [];
  $headers[] = "Content-Type: application/json";
  $data = [
    "otp_code" => "123456"
  ];

  $curl = curl_init();

  $payload = json_encode($data);
  curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
  curl_setopt($curl, CURLOPT_USERPWD, $apiKey.":");
  curl_setopt($curl, CURLOPT_URL, $url);
  curl_setopt($curl, CURLOPT_POST, true);
  curl_setopt($curl, CURLOPT_POSTFIELDS, $payload);
  curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);

  $result = curl_exec($curl);
  echo $result;
Path Parameter Description
linked_account_token_id
required
string Linked account token id received from Initialize Account Authorization. This has the lat- prefix.
Request Body Parameter Description
otp_code
required
string OTP received by the customer from the partner bank for account linking

Validate OTP for Linked Account Token - Response

Example Validate OTP for Linked Account Token Success Response

{
    "id": "lat-aa620619-124f-41db-995b-66a52abe036a",
    "customer_id": "239c16f4-866d-43e8-9341-7badafbc019f",
    "channel_code": "DC_BRI",
    "status": "SUCCESS"
}
Parameter Description
id string Unique ID generated by Instamoney for the particular linked account token authorization
customer_id string Customer object ID
channel_code string Code identifier for the channel
status string Status of the authorization - SUCCESS if the validation went through. Else, HTTP error will be be thrown

Validate OTP for Linked Account Token - Errors

See other common errors here.

Error Code Description
DATA_NOT_FOUND_ERROR
404
Provided linked_account_token_id is not supported or has not yet activated for this account.
INVALID_OTP_ERROR
400
The otp_code provided was incorrect.
EXPIRED_OTP_ERROR
400
The otp_code provided has expired.
MAX_OTP_ATTEMPTS_ERROR
400
Reached the channel’s allowed maximum attempts for OTP verification
ACCOUNT_LINKING_ALREADY_COMPLETED
409
The request is a duplicate of an already processed linked account token that has been successfully completed.
ACCOUNT_LINKING_ALREADY_FAILED
409
The request is a duplicate of an already processed linked account token that has failed.

Retrieve Accessible Accounts by Linked Account Token

This endpoint returns a list of bank accounts accessible by the linked account token. The response information from this endpoint is required for creation of payment method.

Endpoint: Get Accessible Accounts by Linked Account Token

GET https://api.instamoney.co/linked_account_tokens/{linked_account_token_id}/accounts

Retrieve Accessible Accounts by Linked Account Token - Request

Example Get Accessible Accounts by Linked Account Token Request

curl https://api.instamoney.co/linked_account_tokens/lat-aa620619-124f-41db-995b-66a52abe036a/accounts -X GET \
   -u sk_test_vynfjIxiKTiEIJXjeMuKWSmQFTAcmwpqdV7oUvpsYWkzd6oifq3vudl3O3pjlh0: 
<?php
  $linkedAccountTokenId = "lat-aa620619-124f-41db-995b-66a52abe036a";
  $url = "https://api.instamoney.co/linked_account_tokens/" . $linkedAccountTokenId . "/accounts";
  $apiKey = "sk_test_vynfjIxiKTiEIJXjeMuKWSmQFTAcmwpqdV7oUvpsYWkzd6oifq3vudl3O3pjlh0:";
  $headers = [];
  $headers[] = "Content-Type: application/json";

  $curl = curl_init();

  $payload = json_encode($data);
  curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
  curl_setopt($curl, CURLOPT_USERPWD, $apiKey.":");
  curl_setopt($curl, CURLOPT_URL, $url);
  curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "GET");
  curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);

  $result = curl_exec($curl);
  echo $result;
Path Parameter Description
linked_account_token_id
required
string Linked account token id received from Initialize Account Authorization. This has the lat- prefix.

Retrieve Accessible Accounts by Linked Account Token - Response

This endpoint returns an array of objects with the following properties:

Example Get Accessible Accounts by Linked Account Token Success Response

[{
    "id": "la-aa620619-124f-41db-995b-66a52abe036a",
    "channel_code": "DC_BRI",
    "type": "DEBIT_CARD",
    "properties": {
        "account_mobile_number": "62818555988",
        "card_last_four": "1234",
        "card_expiry": "06/24",
        "account_email": "email@email.com"
    }
}]
Parameter Description
id string Unique identifier for the bank account. This has a prefix of la-.
channel_code string Code identifier for the channel
type string Type of account that has been linked.
Expected value: DEBIT_CARD
properties object Object containing information regarding the account. The values inside properties change based on the type of account:


For type DEBIT_CARD (BRI):
Key Value
card_last_four stringLast four digits of the debit card
card_expiry stringExpiry month and year of the debit card (in MM/YY format)
currency stringCurrency of the account in ISO 4217
description stringDescription of the account (provided by the bank)

Retrieve Accessible Accounts by Linked Account Token - Errors

See other common errors here.

Error Code Description
DATA_NOT_FOUND_ERROR
404
Provided linked_account_token_id is not supported or has not yet activated for this account.

Create Payment Method

Payment methods enable you to abstract sources of funds and use them for making direct debit payments or recurring payments. Currently, only supports linked accounts.

Endpoint: Create Payment Method

POST https://api.instamoney.co/payment_methods

Create Payment Method - Request

Example Create Payment Method Request

curl https://api.instamoney.co/payment_methods -X POST \
   -u sk_test_vynfjIxiKTiEIJXjeMuKWSmQFTAcmwpqdV7oUvpsYWkzd6oifq3vudl3O3pjlh0: \
   -H 'Content-Type: application/json' \
   --data-raw '{
    "customer_id": "ba830b92-4177-476e-b097-2ad5ae4d3e55",
    "type": "DEBIT_CARD",
    "properties": {
        "id": "la-aa620619-124f-41db-995b-66a52abe036a"
    }
}'
<?php
  $url = "https://api.instamoney.co/payment_methods";
  $apiKey = "sk_test_vynfjIxiKTiEIJXjeMuKWSmQFTAcmwpqdV7oUvpsYWkzd6oifq3vudl3O3pjlh0:";
  $headers = [];
  $headers[] = "Content-Type: application/json";
  $data = [
    "customer_id" => "ba830b92-4177-476e-b097-2ad5ae4d3e55",
    "type" => "DEBIT_CARD",
    "properties" => [
      "id" => "la-aa620619-124f-41db-995b-66a52abe036a"
    ]
  ];

  $curl = curl_init();

  $payload = json_encode($data);
  curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
  curl_setopt($curl, CURLOPT_USERPWD, $apiKey.":");
  curl_setopt($curl, CURLOPT_URL, $url);
  curl_setopt($curl, CURLOPT_POST, true);
  curl_setopt($curl, CURLOPT_POSTFIELDS, $payload);
  curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);

  $result = curl_exec($curl);
  echo $result;
Request Body Parameter Description
customer_id
required
string ID of the customer object to which the account token will be linked to
type
required
string Type of payment method

Supported values: DEBIT_CARD
properties
required
object JSON that contains information that identifies the payment method:


For Debit Card Linking (BRI):
Key Value
id
required
ID of the account from which payments will be pulled from. You can retrieve account ID by using this API
metadata
optional
object A free-format JSON for additional information that you may use.

Create Payment Method - Response

Example Create Payment Method Success Response

{    
    "id": "pm-c30d4800-afe4-4e58-ad5f-cc006d169139",
    "type": "DEBIT_CARD",
    "properties": {
        "id": "la-aa620619-124f-41db-995b-66a52abe036a",
        "channel_code": "DC_BRI",
        "currency": "IDR",
        "card_last_four": "1234",
        "card_expiry": "06/24",
        "description": null,
    },
    "customer_id": "ba830b92-4177-476e-b097-2ad5ae4d3e55",
    "status": "ACTIVE",
    "created": "2020-03-19T05:34:55+0800",
    "updated": "2020-03-19T05:24:55+0800",
    "metadata": null  
}
Parameter Description
id string Unique identifier for the payment method. This has a prefix of pm-.
type string Type of account that has been linked.
Expected values: DEBIT_CARD
properties object Object containing information regarding the account. The values inside properties change based on the type of account:


For type DEBIT_CARD (BRI):
Key Value
card_last_four stringLast four digits of the debit card
card_expiry stringExpiry month and year of the debit card (in MM/YY format)
currency stringCurrency of the account in ISO 4217
description stringDescription of the account (provided by the bank)
customer_id string ID of the customer object in which this payment method is linked to
status
required
string Status of the payment method.
Will be equal to ACTIVE upon creation.
created string ISO 8601 timestamp when the payment method was created
updated string ISO 8601 timestamp when the payment method information was updated
metadata object A free-format JSON for additional information that you provded during request.

Create Payment Method - Errors

See other common errors here.

Error Code Description
LIINKED_ACCOUNT_NOT_FOUND_ERROR
400
Provided properties and type combination in the request does not exist or access is unauthorized
CUSTOMER_NOT_FOUND_ERROR
400
Provided customer_id in the request does not exist or access is unauthorized
DUPLICATE_ERROR
409
There is already an existing ACTIVE payment method that relates to the same account

Create Direct Debit Payment

Create a debit to pull funds from the end customer's account using an active payment method

Endpoint: Create Direct Debit Payment

POST https://api.instamoney.co/direct_debits

Create Direct Debit Payment - Request

Example Create Direct Debit Payment Request

curl https://api.instamoney.co/direct_debits -X POST \
   -u sk_test_vynfjIxiKTiEIJXjeMuKWSmQFTAcmwpqdV7oUvpsYWkzd6oifq3vudl3O3pjlh0: \
   -H 'Content-Type: application/json' \
   -H 'Idempotency-key: Test_Idempotent_Key'\
   --data-raw '{
    "reference_id": "customer_test_reference_id",
    "payment_method_id": "pm-c30d4800-afe4-4e58-ad5f-cc006d169139",
    "currency": "IDR",
    "amount": 1500,
    "enable_otp": true,
    "callback_url": "https://payment-callback-listener/"
}'
<?php
  $url = "https://api.instamoney.co/direct_debits";
  $apiKey = "sk_test_vynfjIxiKTiEIJXjeMuKWSmQFTAcmwpqdV7oUvpsYWkzd6oifq3vudl3O3pjlh0:";
  $headers = [
    "Content-Type" => "application/json",
    "Idempotency-key" => "Test_Idempotent_Key",
    ];
  $data = [
    "reference_id" => "customer_test_reference_id",
    "payment_method_id" => "pm-c30d4800-afe4-4e58-ad5f-cc006d169139",
    "currency" => "IDR",
    "amount" => 1500,
    "enable_otp" => true,
    "callback_url" => "https://payment-callback-listener/"
    ];

  $curl = curl_init();

  $payload = json_encode($data);
  curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
  curl_setopt($curl, CURLOPT_USERPWD, $apiKey.":");
  curl_setopt($curl, CURLOPT_URL, $url);
  curl_setopt($curl, CURLOPT_POST, true);
  curl_setopt($curl, CURLOPT_POSTFIELDS, $payload);
  curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);

  $result = curl_exec($curl);
  echo $result;
Header Description
Idempotency-key
required
string Provided by the merchant to prevent duplicate requests. May be equal to reference_id or any GUID.
Note: Max 100 characters
Request Body Parameter Description
reference_id
required
string Merchant-provided identifier for this transaction
Note: Max 255 characters
payment_method_id
required
string Instamoney’s identifier for specific payment method. You can create one using Create Payment Method API if you haven't already generated one. Use Get Payment Method API to retrieve the ID
currency
required
string Currency of amount to debit in ISO 4217. e.g. "IDR"
amount
required
number Amount to debit from the end-customer’s account
Note: Maximum amount that can be charged without OTP is 999,999
callback_url
required
string URL where payment notification will be sent after transaction process
Note: Max 255 characters
enable_otp
optional
boolean
true to charge end customer's account with OTP
false to charge end customer's account without OTP
description
optional
string Description for the direct debit transaction.
basket
optional
array Array of objects describing the item/s purchased using direct debit
Key Value
reference_id
required
stringMerchant’s identifier for specific product (ie. SKU)
name
required
stringName of product
market
required
string2-letter ISO 3166-2 country code indicating target merchant’s country of operations
type
required
stringType of product
description
optional
stringDescription of product
category
optional
stringMerchant category for item
sub-category
optional
stringMerchant sub-category for item
price
optional
stringPrice per unit in basket currency
url
optional
stringProduct URL with product details
metadata
optional
stringAdditional object that may be used for additional product attributes
quantity
optional
stringNumber of units of this item in the basket
metadata
optional
object Object of additional information the user may use. User defines the JSON properties and values. You can specify up to 50 keys, with key names up to 40 characters long and values up to 500 characters long

Create Payment - Response

Example Create Payment Success Response

{
    "id": "ddpy-623dca10-5dad-4916-b14d-81aaa76b5d14",
    "reference_id": "e17a0ac8-6fed-11ea-bc55-0242ac130003",
    "channel_code": "DC_BRI",
    "payment_method_id": "pm-c30d4800-afe4-4e58-ad5f-cc006d169139",
    "currency": "IDR",
    "amount": "10000",
    "description": null,
    "status": "PENDING",
    "basket": null,
    "failure_code": null,
    "is_otp_required": true,
    "otp_mobile_number": "+6287774441111",
    "otp_expiration_timestamp": null,
    "created": "2020-03-26T05:44:26+0800",
    "updated": null,
    "metadata": null
}
Parameter Description
id string Unique identifier for the transaction
reference_id string Reference ID provided by merchant
channel_code string Code identifier for the channel
payment_method_id string Payment method ID of end-customer source of funds
currency string Currency of the payment
amount number Amount to debit from the end-customer’s account
description string Description provided by merchant
status string Status of the payment - "PENDING", "COMPLETED", "FAILED"
failure_code string Reason if direct debit has failed. List of failure codes can be found here
is_otp_required boolean The flag for merchant to know whether OTP was enabled for the particular direct debit transaction
otp_mobile_number string Masked mobile number of the OTP recipient from the channel. Empty string if OTP was not enabled.
otp_expiration_timestamp string Timestamp until when the OTP is valid. Empty string if OTP was not enabled.
created string Timestamp in ISO 8601 when the request was made
updated string Timestamp in ISO 8601 when transaction information was updated
basket array Array of basket objects provided by merchant
metadata object Metadata provided by merchant

Create Payment - Errors

Example Create Payment Error Response

{
    "error_code" : "DUPLICATE_ERROR",
    "message" : "Idempotency key has been used before. Use a unique idempotency key and try again"
}
Error Code Description
DUPLICATE_ERROR
409
Idempotency key has been used before. Use a unique idempotency key and try again.
PAYMENT_METHOD_NOT_FOUND_ERROR
400
Provided payment_method_id is invalid, not found or access is unauthorized
INVALID_PAYMENT_METHOD_ERROR
503
The payment method has expired or has been invalidated.

Validate OTP for Direct Debit Payment

Validate OTP provided by end customer via this endpoint to complete the transaction when OTP is enabled.

Endpoint: Validate OTP for Direct Debit Payment

POST https://api.instamoney.co/direct_debits/:direct_debit_id/validate_otp/

Validate Direct Debit Payment OTP - Request

Example Validate Direct Debit Payment OTP Request

curl https://api.instamoney.co/direct_debits/ddpy-623dca10-5dad-4916-test/validate_otp/ -X GET \
   -u sk_test_vynfjIxiKTiEIJXjeMuKWSmQFTAcmwpqdV7oUvpsYWkzd6oifq3vudl3O3pjlh0: \
   --data-raw '{
    "otp_code": "111222"
    }'
<?php
  $direct_debit_id = "ddpy-623dca10-5dad-4916-test";
  $url = "https://api.instamoney.co/direct_debits/" . $direct_debit_id . "/validate_otp";
  $apiKey = "sk_test_vynfjIxiKTiEIJXjeMuKWSmQFTAcmwpqdV7oUvpsYWkzd6oifq3vudl3O3pjlh0:";
  $headers = [];
  $headers[] = "Content-Type: application/json";
  $data = [
    "otp_code" => "111222"
  ];

  $curl = curl_init();

  $payload = json_encode($data);
  curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
  curl_setopt($curl, CURLOPT_USERPWD, $apiKey.":");
  curl_setopt($curl, CURLOPT_URL, $url);
  curl_setopt($curl, CURLOPT_POST, true);
  curl_setopt($curl, CURLOPT_POSTFIELDS, $payload);
  curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);

  $result = curl_exec($curl);
  echo $result;
Path Parameter Description
direct_debit_id
required
string Merchant provided identifier for specified direct debit transaction
Request Body Parameter Description
otp_code
required
string One-time-password input from end customer

Validate Payment OTP - Response

Will return a successful 200 HTTP response as soon as the bank has validated the OTP, otherwise an error is returned.

Example Get Payment Status by ID Success Response

{
    "id": "ddpy-623dca10-5dad-4916-b14d-81aaa76b5d14",
    "reference_id": "e17a0ac8-6fed-11ea-bc55-0242ac130003",
    "channel_code": "DC_BRI",
    "payment_method_id": "pm-c30d4800-afe4-4e58-ad5f-cc006d169139",
    "currency": "IDR",
    "amount": "100000",
    "description": null,
    "status": "PENDING",
    "basket": null,
    "failure_code": null,
    "is_otp_required": true,
    "otp_mobile_number": "+62907XXXX123",
    "otp_expiration_timestamp": "2020-03-26T05:45:06+0800",
    "created": "2020-03-26T05:44:26+0800",
    "updated": "2020-03-26T05:44:46+0800",
    "metadata": null
}
Parameter Description
id string Unique identifier for the transaction
reference_id string Reference ID provided by merchant
channel_code string Code identifier for the channel
payment_method_id string Payment method ID of end-customer source of funds
currency string Currency of the payment
amount number Amount to debit from the end-customer’s account
description string Description provided by merchant
status string Status of the payment
failure_code string Reason if direct debit has failed
is_otp_required boolean The flag for merchant to know whether OTP was enabled for the particular direct debit transaction
otp_mobile_number string Masked mobile number of the OTP recipient from the channel. Empty string if OTP was not enabled.
otp_expiration_timestamp string Timestamp until when the OTP is valid. Empty string if OTP was not enabled.
created string Timestamp in ISO 8601 when the request was made
updated string Timestamp in ISO 8601 when transaction information was updated
basket array Array of basket objects provided by merchant
metadata object Metadata provided by merchant

Validate Payment OTP - Errors

Example Create Payment Error Response

{
    "error_code" : "DUPLICATE_ERROR",
    "message" : "Idempotency key has been used before. Use a unique idempotency key and try again"
}
Error Code Description
DATA_NOT_FOUND_ERROR
404
Provided direct_debit_id does not exist or access is unauthorized
INVALID_OTP_ERROR
400
OTP provided is invalid
EXPIRED_OTP_ERROR
400
OTP provided has expired
MAX_OTP_ATTEMPTS_ERROR
400
Payment method reached the channel’s allowed maximum attempts for OTP verification
DIRECT_DEBIT_ALREADY_COMPLETED
409
The request is a duplicate of an already processed linked account token that has been successfully completed.
DIRECT_DEBIT_ALREADY_FAILED
409
The request is a duplicate of an already processed linked account token that has failed.

Get Payment Methods by Customer ID

This endpoint returns an array of payment methods that are linked to the provided customer_id

Endpoint: Get Payment Methods by Customer ID

GET https://api.instamoney.co/payment_methods?customer_id={customer_id}

Get Payment Methods by Customer ID - Request

Example Get Payment Methods by Customer ID Request

curl https://api.instamoney.co/payment_methods?customer_id=ba830b92-4177-476e-b097-2ad5ae4d3e55 -X GET \
   -u sk_test_vynfjIxiKTiEIJXjeMuKWSmQFTAcmwpqdV7oUvpsYWkzd6oifq3vudl3O3pjlh0: 
<?php
  $url = "https://api.instamoney.co/payment_methods";
  $apiKey = "sk_test_vynfjIxiKTiEIJXjeMuKWSmQFTAcmwpqdV7oUvpsYWkzd6oifq3vudl3O3pjlh0:";
  $headers = [];
  $headers[] = "Content-Type: application/json";

  $queryString = "?customer_id=ba830b92-4177-476e-b097-2ad5ae4d3e55";

  $curl = curl_init();

  $payload = json_encode($data);
  curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
  curl_setopt($curl, CURLOPT_USERPWD, $apiKey.":");
  curl_setopt($curl, CURLOPT_URL, $url.$queryString);
  curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "GET");
  curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);

  $result = curl_exec($curl);
  echo $result;
Query String Parameter Description
customer_id
required
string Customer object ID of interest

Get Payment Methods by Customer ID - Response

This endpoint returns an array of matching objects with the following properties:

Example Get Payment Methods by Customer ID Success Response

[{    
    "id": "pm-c30d4800-afe4-4e58-ad5f-cc006d169139",
    "type": "DEBIT_CARD",
    "properties": {
        "id": "la-aa620619-124f-41db-995b-66a52abe036a",
        "channel_code": "DC_BRI",
        "currency": "IDR",
        "card_last_four": "1234",
        "card_expiry": "06/24",
        "description": null,
    },
    "customer_id": "ba830b92-4177-476e-b097-2ad5ae4d3e55",
    "status": "ACTIVE",
    "created": "2020-03-19T05:34:55+0800",
    "updated": "2020-03-19T05:24:55+0800",
    "metadata": null  
}]
Parameter Description
id string Unique identifier for the payment method. This has a prefix of pm-.
type string Type of account that has been linked.
Expected values: DEBIT_CARD
properties object Object containing information regarding the account. The values inside properties change based on the type of account:


For type DEBIT_CARD (BRI):
Key Value
card_last_four stringLast four digits of the debit card
card_expiry stringExpiry month and year of the debit card (in MM/YY format)
currency stringCurrency of the account in ISO 4217
description stringDescription of the account (provided by the bank)
customer_id string ID of the customer object in which this payment method is linked to
status string Status of the payment method.
Will be equal to ACTIVE upon creation.
created string ISO 8601 timestamp when the payment method was created
updated string ISO 8601 timestamp when the payment method information was updated
metadata object A free-format JSON for additional information that you provded during request.

Get Payment Methods by Customer ID - Errors

See other common errors here.

Get Direct Debit Payment Status by Reference ID

Retrieve the details of a direct debit payment by merchant provided transaction ID

Endpoint: Get Payment Staus by Reference ID

POST https://api.instamoney.co/direct_debits?reference_id={reference_id}

Get Payment Status by Reference ID - Request

Example Payment Status by Reference ID Request

curl https://api.instamoney.co/direct_debits?reference_id=test_merchant_reference_id/ -X GET \
   -u sk_test_vynfjIxiKTiEIJXjeMuKWSmQFTAcmwpqdV7oUvpsYWkzd6oifq3vudl3O3pjlh0: 
<?php
  $url = "https://api.instamoney.co/direct_debits/";
  $apiKey = "sk_test_vynfjIxiKTiEIJXjeMuKWSmQFTAcmwpqdV7oUvpsYWkzd6oifq3vudl3O3pjlh0:";
  $headers = [];
  $headers[] = "Content-Type: application/json";

  $queryString = "?reference_id=test_merchant_reference_id";

  $curl = curl_init();

  $payload = json_encode($data);
  curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
  curl_setopt($curl, CURLOPT_USERPWD, $apiKey.":");
  curl_setopt($curl, CURLOPT_URL, $url.$queryString);
  curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "GET");
  curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);

  $result = curl_exec($curl);
  echo $result;
Query String Parameter Description
reference_id
required
string Merchant provided identifier for specified direct debit transaction

Get Payment Status by ID - Response

Example Get Payment Status by ID Success Response

{
    "id": "ddpy-623dca10-5dad-4916-b14d-81aaa76b5d14",
    "reference_id": "e17a0ac8-6fed-11ea-bc55-0242ac130003",
    "channel_code": "DC_BRI",
    "payment_method_id": "pm-c30d4800-afe4-4e58-ad5f-cc006d169139",
    "currency": "IDR",
    "amount": "10000",
    "description": null,
    "status": "PENDING",
    "basket": null,
    "failure_code": null,
    "is_otp_required": true,
    "otp_mobile_number": null,
    "otp_expiration_timestamp": null,
    "created": "2020-03-26T05:44:26+0800",
    "updated": null,
    "metadata": null
}
Parameter Description
id string Unique identifier for the transaction
reference_id string Reference ID provided by merchant
channel_code string Code identifier for the channel
payment_method_id string Payment method ID of end-customer source of funds
currency string Currency of the payment
amount number Amount to debit from the end-customer’s account
description string Description provided by merchant
status string Status of the payment
failure_code string Reason if direct debit has failed
is_otp_required boolean The flag for merchant to know whether OTP was enabled for the particular direct debit transaction
otp_mobile_number string Masked mobile number of the OTP recipient from the channel. Empty string if OTP was not enabled.
otp_expiration_timestamp string Timestamp until when the OTP is valid. Empty string if OTP was not enabled.
created string Timestamp in ISO 8601 when the request was made
updated string Timestamp in ISO 8601 when transaction information was updated
basket array Array of basket objects provided by merchant
metadata object Metadata provided by merchant

Get Direct Debit Payment Status by ID

Retrieve the details of a direct debit payment by Instamoney transaction ID

Endpoint: Get Payment Staus by ID

POST https://api.instamoney.co/direct_debits/:direct_debit_id/

Get Payment Status by ID - Request

Example Payment Status by ID Request

curl https://api.instamoney.co/direct_debits/ddpy-623dca10-5dad-4916-test/ -X GET \
   -u sk_test_vynfjIxiKTiEIJXjeMuKWSmQFTAcmwpqdV7oUvpsYWkzd6oifq3vudl3O3pjlh0: 
<?php
  $direct_debit_id = "ddpy-623dca10-5dad-4916-test";
  $url = "https://api.instamoney.co/direct_debits/" . $direct_debit_id . "/";
  $apiKey = "sk_test_vynfjIxiKTiEIJXjeMuKWSmQFTAcmwpqdV7oUvpsYWkzd6oifq3vudl3O3pjlh0:";
  $headers = [];
  $headers[] = "Content-Type: application/json";

  $curl = curl_init();

  $payload = json_encode($data);
  curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
  curl_setopt($curl, CURLOPT_USERPWD, $apiKey.":");
  curl_setopt($curl, CURLOPT_URL, $url);
  curl_setopt($curl, CURLOPT_POST, true);
  curl_setopt($curl, CURLOPT_POSTFIELDS, $payload);
  curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);

  $result = curl_exec($curl);
  echo $result;
Path Parameter Description
direct_debit_id
required
string Instamoney identifier for specified direct debit transaction

Get Payment Status by ID - Response

Example Get Payment Status by ID Success Response

{
    "id": "ddpy-623dca10-5dad-4916-b14d-81aaa76b5d14",
    "reference_id": "e17a0ac8-6fed-11ea-bc55-0242ac130003",
    "channel_code": "DC_BRI",
    "payment_method_id": "pm-c30d4800-afe4-4e58-ad5f-cc006d169139",
    "currency": "IDR",
    "amount": "10000",
    "description": null,
    "status": "PENDING",
    "basket": null,
    "failure_code": null,
    "is_otp_required": true,
    "otp_mobile_number": null,
    "otp_expiration_timestamp": null,
    "created": "2020-03-26T05:44:26+0800",
    "updated": null,
    "metadata": null
}
Parameter Description
id string Unique identifier for the transaction
reference_id string Reference ID provided by merchant
channel_code string Code identifier for the channel
payment_method_id string Payment method ID of end-customer source of funds
currency string Currency of the payment
amount number Amount to debit from the end-customer’s account
description string Description provided by merchant
status string Status of the payment
failure_code string Reason if direct debit has failed
is_otp_required boolean The flag for merchant to know whether OTP was enabled for the particular direct debit transaction
otp_mobile_number string Masked mobile number of the OTP recipient from the channel. Empty string if OTP was not enabled.
otp_expiration_timestamp string Timestamp until when the OTP is valid. Empty string if OTP was not enabled.
created string Timestamp in ISO 8601 when the request was made
updated string Timestamp in ISO 8601 when transaction information was updated
basket array Array of basket objects provided by merchant
metadata object Metadata provided by merchant

Callback Notifications

In our direct debit flow, we will send callback to your system during Direct Debit Payment process. Merchants need to set up URL to receive callback notifications from our system.

Direct Debit Payment Callback

Payload

Example: Payload

{
    "event": "direct_debit.payment",
    "timestamp": "2020-03-26T05:44:26+0800",
    "id": "ddpy-623dca10-5dad-4916-b14d-81aaa76b5d14",
    "reference_id": "e17a0ac8-6fed-11ea-bc55-0242ac130003",
    "channel_code": "DC_BRI",
    "payment_method_id": "pm-c30d4800-afe4-4e58-ad5f-cc006d169139",
    "currency": "IDR",
    "amount": "1000.00",
    "description": null,
    "status": "COMPLETED",
    "failure_code": null,
    "metadata": null
}
Parameter Description
event string Identifier of the event - "direct_debit.payment"
timestamp string ISO 8601 timestamp of the event. Timezone is UTC+0
id string Unique identifier for the transaction
reference_id string Reference ID provided by merchant
channel_code string Code identifier for the channel
payment_method_id string Payment method ID of end-customer source of funds
currency string Currency of the payment
amount number Amount to debited from the end-customer’s account
description string Description provided by merchant
status string Status of the payment - "PENDING", "COMPLETED", "FAILED"
failure_code string Reason if direct debit has failed. List of failure codes can be found here
metadata object Metadata provided by merchant

Payment Status Callback - Failure Reasons

Example: Payment Status Failure Examples

{
    "event": "direct_debit.payment",
    "timestamp": "2020-03-26T05:44:26+0800",
    "id": "ddpy-623dca10-5dad-4916-b14d-81aaa76b5d14",
    "reference_id": "e17a0ac8-6fed-11ea-bc55-0242ac130003",
    "channel_code": "DC_BRI",
    "payment_method_id": "pm-c30d4800-afe4-4e58-ad5f-cc006d169139",
    "currency": "IDR",
    "amount": "1000.00",
    "description": null,
    "status": "FAILED",
    "failure_code": "INSUFFICIENT_BALANCE",
    "metadata": null
}
Failure Code Description
MAX_AMOUNT_LIMIT_ERROR End customer's daily limit has been reached, unable to process debit request. End user required to increase daily limit or retry another day
INSUFFICIENT_BALANCE End customer has insufficient balance, unable to process debit request. End user required to top up balance
CHANNEL_UNAVAILABLE Bank service for direct debit is currently unavailable, unable to process debit request.
ACCOUNT_ACCESS_BLOCKED End customer bank account has been blocked, end user should contact the bank for resolution.

Callback

Instamoney uses callback to notify your application any time an event happens on your account. Set up callback for events that Instamoney doesn't already notify you of, like when a disbursement has been completed, a Virtual Account has been created and paid, or your disbursement has completed.

Setup

You need to provide an endpoint in your system to receive callback from us. The callback notification will be sent over POST request to your callback URL that you have set. Setup your callback URL in Configuration settings. You can use a tool like ngrok to make your endpoint available for receiving callback during testing.

Delivery Attempts and Retries

Understand how to view delivery attempts and retry logic when callback events aren't acknowledged

View events

When viewing information about a specific event through the Dashboard's Callback tab, you can check how many times Instamoney attempted to send an event to the endpoint. This shows the latest response from your endpoint, a list of all attempted callback, and the respective HTTP status codes Instamoney received.

Retry logic

Instamoney attempts to deliver your callback three times and will stop retrying until we have received response from your server or there is still no response yet.

Receive callback statistics via email

You can also receive summary of your callback statistics (number of success and failed callback) via email every 6 hours. You can enable this feature in Configuration settings

Event Handling

Handling callback events correctly is crucial to making sure your integration's business logic works as expected

Acknowledge events immediately

If your callback script performs complex logic, or makes network calls, it's possible that the script would time out before Instamoney sees its complete execution. Ideally, your callback handler code (acknowledging receipt of an event by returning a 2xx status code) is separate of any other logic you do for that event.

Handle duplicate events

Callback endpoints might occasionally receive the same event more than once. We advise you to guard against duplicated event receipts by making your event processing idempotent. One way of doing this is logging the events you've processed, and then not processing already-logged events.

Order of events

Instamoney does not guarantee delivery of events in the order in which they are generated. Your endpoint should not expect delivery of these events in this order and should handle this accordingly. You can also use the API to fetch any missing objects.

Security

Keeping your endpoints secure is critical to protecting your customers' information. Instamoney provides several ways for you to verify events are coming from Instamoney in a secure manner.

Receive events with an HTTPS server

If you use an HTTPS URL for your callback endpoint, Instamoney will validate that the connection to your server is secure before sending your callback data. For this to work, your server must be correctly configured to support HTTPS with a valid server certificate.

Verify events are sent from Instamoney

Instamoney can optionally sign the callback events it sends to your endpoints. We do so by including a token in each event's x-callback-token header. This allows you to verify that the events were sent by Instamoney, not by a third party.

Header Parameter Description
x-callback-token
string Your Instamoney unique callback token to verify the origin of the callback

Before you can verify tokens, you need to retrieve your callback token from Dashboard's Security settings. Each secret is unique to each environments.

Test Scenarios

This section includes test scenarios and other information to make sure your integration works as planned. Use it to trigger different flows in your integration and ensure they are handled accordingly

Checklists

Instamoney has designed its live and test modes to function as similarly as possible. Flipping the switch is mostly a matter of swapping your API keys.

If you are a developer, or had a developer perform an integration for you, you should also consider the following items before going live.

Handle Edge Cases

We have created several test cases you can use to replicate various states and responses. Beyond these options, perform your due diligence, testing your integration with:

We also recommend you have someone else test your integration, especially if that other person is not a developer themselves.

Review Error Handling

Once you have gone live is an unfortunate time to discover you have not properly written your code to handle every possible error type, including those that should "never" happen. Be certain your code is defensive, handling not just the common errors, but all possibilities.

When testing your error handling, especially watch what information is shown to your users. A disbursement being failed (i.e., INVALID_DESTINATION) is a different concern than an error on your backend (e.g., an API_VALIDATION_ERROR).

Review Your Logging

Instamoney logs every request made with you API keys. We recommend that you log all important data on your end, too, despite the apparent redundancy. Your own logs will be a life-saver if your server has a problem contacting Instamoney or there's an issue with your API keys--both cases would prevent us from logging your request.

Regularly examine your logs to ensure they're storing all the information you may need and they are not storing anything of a sensitive nature (e.g., personally identifiable information).

Independent From Test Mode Objects

Instamoney objects created in test mode--such as virtual accounts, retail outlets, etc---are not usable in live mode. This prevents your test data from being inadvertently used in your production code. When recreating necessary objects in live mode, be certain to use the same ID values (e.g. the same Virtual Account external ID) to guarantee your code will continue to work without issue

Register Live Callback URL

Your Instamoney account can have both test and live callback URLs. If you are using callback, make sure you have defined live endpoints in your Instamoney account. Then confirm that the live endpoint functions exactly the same as your test endpoint.

While examining your callback status, also take a moment to check that your live endpoint:

Secure Your API keys

As a security measure, we recommend change your API keys on a regular basis, and also just before going live. This is in case they have been saved somewhere outside of your codebase during development. Make sure your workflow doesn't result in your API keys being represented or stored in multiple places--this leads to bugs--or even ending up in your version control software.

Changelog

Version 1.4.11 (February 1, 2021)

Update maximum disbursement amount to Other Banks from Rp 50,000,000 to Rp 100,000,000

Version 1.4.10 (September 11, 2020)

Version 1.4.9 (August 19, 2020)

Version 1.4.8 (August 18, 2020)

Version 1.4.7 (August 7, 2020)

Version 1.4.6 (August 3, 2020)

Version 1.4.5 (June 18, 2020)

Version 1.4.4 (May 6, 2020)

Version 1.4.3 (March 14, 2020)

Version 1.4.2 (February 3, 2020)

Version 1.4.1 (January 30, 2020)

Version 1.4.0 (December 20, 2019)

Version 1.3.4 (December 15, 2019)