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 inusername
and leave thepassword
empty
Basic Auth format
{{username}}:{{password}}
Following the format (with colon)
sk_test_PYGIfL5y0uHx5ZhLbUdSzCRb9ajpdl6lyXmRxn2zQbWlBEUQWE9218vfR0jg:
Encode
Basic Auth
format above intoBase64
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:
- Generate secret API key from Dashboard
- Obtain your secret API key
- Select Basic Access Authentication or
BASIC AUTH
authentication BASIC AUTH
format will be{{username}}:{{password}}
- Input Secret API key as
username
and leave thepassword
empty. Make sure to include:
at the end - Encode the value above into Base64 format
- 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:
- Bank Transfer via Virtual Accounts
- Disbursements
Here are the steps to use Instamoney PHP library:
- Download PHP package here
- Include
InstamoneyPHPClient.php
in your code - Create
InstamoneyPHPClient
object with secret API key as parameter - 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:
- Content errors occur because the content in the API request was invalid in some way. They return an HTTP response with a
4xx
error code. For example, the API servers might return a401
if an invalid API key was provided, or a400
if a required parameter was missing - Network errors occur as a result of intermittent communication problems between client and server. They return low-level errors, like socket or timeout exceptions. For example, a client might time out while trying to read from Instamoney's servers, or an API response might never be received because a connection terminates prematurely. Note that a network errors wouldn't necessarily have otherwise been a successful request --- it can also be another type of error that's been cloaked by an intermittent problem
- Server errors occur because of a problem on Instamoney's servers. Server errors return an HTTP response with a
5xx
error code. Instamoney works to make these errors as rare as posslble, but integrations should be able to handle them when they do arise
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 |
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:
- Use an algorithm that generates a token with good randomness, like UUID v4
- Derive the key from a user-attached object like the ID of a shopping cart. This provides a relatively easy way to protect against double submissions
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.
Rate Limit
API Rate Limit is a feature that limits the number of requests that a user or account can make to an API within a specific time period. This is often used to prevent excessive or abusive usage of an API, and to ensure that all users have fair access to the resources provided by the API.
Instamoney uses the Sliding Window algorithm to implement API Rate Limit. This algorithm divides a specific time period (such as an hour or a day) into smaller windows, and tracks the number of requests made within each window. For example, if the rate limit is 50 requests per second (RPS), and the window size is one minute, the algorithm will allow up to 3000 requests in each one-minute window.
In general, API Rate Limit is set 3000 requests per minute (RPM) per endpoint per account in Test mode. In Live mode, the rate limit is set to 6000 requests per minute (RPM) per endpoint per account. The Rate Limit value can be different per endpoint when stated otherwise in each API section in API Reference. We return the following headers in API response to let you check Rate Limit details:
Response Header | Example Value | Description |
---|---|---|
Rate-Limit-Limit | 6000 | Containing the requests quota in the time window |
Rate-Limit-Remaining | 5839 | Containing the remaining requests quota in the current window |
Rate-Limit-Reset | 58.379 | Containing the time remaining in the current window, specified in seconds |
If you exceed the rate limit for an endpoint, you will receive an HTTP status code of 429 (Too Many Requests) with the error code RATE_LIMIT_EXCEEDED
. It is important to handle this error and throttle your requests until the rate limit quota replenishes.
Here are some best practices for handling API Rate Limit gracefully as a client:
- Implement rate limiting in your application: As a client, it is important to implement rate limiting in your own application to ensure that you do not exceed the API's rate limits. This can be done by tracking the number of requests made and the time at which they were made, and comparing this to the API's rate limit policies.
- Handle rate limit errors: When you receive an HTTP status code of 429 (Too Many Requests) with the error code
RATE_LIMIT_EXCEEDED
, it is important to handle this error gracefully in your application. One way to do this is to retry the request after a certain amount of time has passed, to give the rate limit quota a chance to replenish. - Use exponential backoff: When retrying a request after a rate limit error, it can be helpful to use exponential backoff. This means that you should increase the amount of time you wait between retries by a factor of two (or some other multiplier) each time you receive a rate limit error. For example, you might retry the request after 1 second, then 2 seconds, then 4 seconds, and so on. This helps to reduce the risk of overwhelming the API with too many retries in a short period of time.
- Use caching: Caching the results of API requests can help to reduce the number of requests made to the API, and can also improve the performance of your application. By storing the results of API requests locally and reusing them until they become stale, you can reduce the need to make frequent requests to the API.
By following these best practices, you can help to ensure that your application handles rate limits gracefully and provides a reliable and consistent experience for your users.
We may reduce limits to prevent abuse, or increase limits to enable high-traffic applications. To increase the rate limit for your account, you can contact us 4 weeks in advance via email api.instamoney.co by providing your Business ID. We will review your request and may be able to increase the limit based on the needs of your application and the overall usage of the API.
Overall, it is important to carefully manage your API usage to ensure that you do not exceed the rate limits and disrupt the service for other users. By implementing proper rate limiting and error handling in your application, you can ensure that your users have a reliable and consistent experience when accessing the API.
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
This endpoint can be used to get all available banks that Instamoney supports (may have difference with your activated bank channel).
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",
"is_activated":true
}
Parameter | Description |
---|---|
name | Full name of the bank |
code | Code of the bank, relevant during creation of virtual accounts |
is_activated | Activation status 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
|
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). BNI VA name will be included a prefix "XDT-" in the response. This prefix is mandatory from BNI. |
virtual_account_numberoptional |
string The virtual account number you want to assign. If you do not send one, one will be picked at random |
suggested_amountoptional |
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_closedoptional |
boolean When set to true , the virtual account will be closed and will only accept the amount specified in expected_amount |
expected_amountoptional |
number The amount that the virtual account will expect if is_closed is set to true |
expiration_dateoptional |
ISO Date The time when the virtual account will be expired |
is_single_useoptional |
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": "PENDING"
}
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_ERROR400 |
Inputs are failing validation. The errors field contains details about which fields are violating validation. |
INVALID_JSON_FORMAT400 |
The request body is not a valid JSON format. |
VIRTUAL_ACCOUNT400 |
The virtual account number you want is outside your range. |
BANK_NOT_SUPPORTED400 |
The bank code is not currently supported. |
EXPIRATION_DATE400 |
Custom expiration date for the fixed virtual account is not currently supported. |
EXPIRATION_DATE400 |
Invalid custom expiration date because it's earlier than current time. |
SUGGESTED_AMOUNT400 |
The suggested amount for the fixed virtual account is not currently supported. |
EXPECTED_AMOUNT400 |
The expected amount is required when is_closed is set to true . |
CLOSED_VA_NOT400 |
The closed option for this virtual account is not currently supported. |
DUPLICATE_CALLBACK400 |
The account number that you want to create is already exist |
MINIMUM_EXPECTED400 |
The expected amount can only be more than zero |
MAXIMUM_EXPECTED400 |
The expected amount can only be less than Rp.1000000000 |
CALLBACK_VIRTUAL_ACCOUNT_NAME_NOT_ALLOWED400 |
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_amountoptional |
number The amount that the virtual account will expect if is_closed is set to true
|
expiration_dateoptional |
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_useoptional |
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": "PENDING"
}
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_ERROR400 |
Inputs are failing validation. The errors field contains details about which fields are violating validation. |
INVALID_JSON_FORMAT400 |
The request body is not a valid JSON format. |
VIRTUAL_ACCOUNT400 |
The virtual account number you want is outside your range. |
BANK_NOT_SUPPORTED400 |
The bank code is not currently supported. |
SUGGESTED_AMOUNT400 |
The suggested amount for the fixed virtual account is not currently supported. |
EXPECTED_AMOUNT400 |
The expected amount is required when is_closed is set to true . |
CLOSED_VA_NOT400 |
The closed option for this virtual account is not currently supported. |
INACTIVE_VIRTUAL_ACCOUNT_ERROR400 |
Account number that you want to update is inactive. |
MINIMUM_EXPECTED400 |
The expected amount can only be more than zero |
MAXIMUM_EXPECTED400 |
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'
Header Parameter | Description |
---|---|
x-callback-token | Your Instamoney unique callback token to verify the origin of the callback |
webhook-id | A unique identifier of every webhook to help you to handle double callback by implementing idempotency. When you receive the same webhook-id twice, treat the subsequent request as duplicate and reject the webhook accordingly to prevent double webhook |
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_ERROR404 |
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": "PENDING",
"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_ERROR404 |
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 (Barcode included). 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 Characters: alphanumeric Special Characters: # / . " - , ' _ @ ( ) & ] [ : |
expected_amountrequired |
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_codeoptional |
string The fixed payment code that you want to assign. If you do not send one, one will be picked at random |
expiration_dateoptional |
ISO Date The time when the fixed payment code will be expired |
is_single_useoptional |
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 or show via barcode page. You can append payment_code into the barcode page URL (barcode page currently only supports Alfamart): |
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_ERROR400 |
Inputs are failing validation. The errors field contains details about which fields are violating validation. |
INVALID_JSON_FORMAT400 |
The request body is not a valid JSON format. |
PAYMENT_CODE400 |
The fixed payment code you want is outside your range. |
RETAIL_OUTLET_NOT400 |
The Retail Outlets is not currently supported. |
DUPLICATE_PAYMENT400 |
The payment code that you want to create is already exist |
EXPIRATION_DATE400 |
Invalid custom expiration date because it's earlier than current time. |
MINIMUM_EXPECTED400 |
The expected amount can only be more than or equal Rp 10,0000 |
MAXIMUM_EXPECTED400 |
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_amountoptional |
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_dateoptional |
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_ERROR400 |
Inputs are failing validation. The errors field contains details about which fields are violating validation. |
INVALID_JSON_FORMAT400 |
The request body is not a valid JSON format. |
PAYMENT_CODE400 |
The fixed payment code you want is outside your range. |
INACTIVE_FIXED_PAYMENT_CODE_ERROR400 |
Account number that you want to update is inactive. |
MINIMUM_EXPECTED400 |
The expected amount can only be more than or equal Rp 10,000 |
MAXIMUM_EXPECTED400 |
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_ERROR404 |
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 SETTLING means that transaction already PAID but still waiting for settlement time COMPLETED means that transaction already PAID and SETTLED |
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.
Get Payments By Fixed Payment Code ID
Endpoint: Get Payments By Fixed Payment Code ID(FPC)
GET https://api.instamoney.co/fixed_payment_code/{fixed_payment_code_id}/payments
Example Get Payments By Fixed Payment Code ID(FPC) Request
curl https://api.instamoney.co/fixed_payment_code/{fixed_payment_code_id}/payments -X GET \
-u sk_test_OYCEfL5xgLL+l8ZvK7QaSGGVMN73oNEpk3yz+Rxn/2bS/LCgCQZ+gw==:
Sometimes, you need to know the payments made for your fixed payment code. This endpoint can be used to retrieve all payments that were made into a particular fixed payment code.
Get Fixed Payment Code Request
Path Parameter | Description |
---|---|
fixed_payment_code_id required |
string ID of the fixed payment code to retrieve |
Query Parameter | Description |
---|---|
limit optionaldefault: 10 |
number A limit on the number of invoice objects to be returned. Limit can range between 1 and 100. |
after_id optional |
string Id of the immediately previous item. Use this with links on the response for pagination. |
Get Fixed Payment Code Response
Example Get Payments By Fixed Payment Code ID(FPC)
{
"data": [
{
"id": "61e660dfa5cebe7ec4fabe42",
"external_id": "FPC-1642488014",
"owner_id": "5fac8c146f67f74049fb828e",
"fixed_payment_code_id": "61e660cf84949196d94e6431",
"fixed_payment_code_payment_id": "61e660df0f61fe962baa18bf",
"retail_outlet_name": "ALFAMART",
"prefix": "TEST",
"payment_code": "TEST404373",
"amount": 25000,
"name": "JOHN DOE",
"status": "SETTLING",
"payment_id": "1642488031655",
"transaction_timestamp": "2022-01-18T06:40:31.655Z",
}
],
"has_more": true,
"links": {
"href": "https://api.instamoney.co/fixed_payment_code/61e660cf84949196d94e6431/payments?limit=1&after_id=61e660dfa5cebe7ec4fabe42",
"rel": "next",
"method": "GET"
}
}
Parameter | Description |
---|---|
data | Returns an array of Payment Object. Returns empty array when there is no result. |
has_more | Indicates whether there are more items to be queried with after_id of the last item from the current result. Use the links to follow to the next result. |
links | The links to the next page based on HATEOAS if there is next result. The HATEOAS format are: href: URI of target, this will be to the next link. rel: The relationship between source and target. The value will be next. method: The HTTP method, the value will be GET. |
Payment Object | Description |
---|---|
id | Unique ID for the payment that generated randomly by system |
external_id | An ID of your choice which you provided upon request |
owner_id | Unique user ID of the merchant |
fixed_payment_code_id | Unique ID for the fixed payment code which you provided upon request |
fixed_payment_code_payment_id | Unique ID for the payment paid by end-cusotmer with provided payment code |
retail_outlet_name | The name of the Retail Outlets e.g. ALFAMART and INDOMARET |
prefix | 3-6 characters that differentiate your fixed payment code from the others |
payment_code | The code given to end-customer for making payments |
amount | The amount that is paid by end customer |
name | Name for the fixed payment code |
status | Status of payment. Possible value(s): SETTLING or COMPLETED SETTLING means that transaction already PAID but still waiting for settlement time COMPLETED means that transaction already PAID and SETTLED |
payment_id | Our internal system’s payment ID that can be used as payment reference |
transaction_timestamp | Date time that the fixed payment code was paid |
Get Fixed Payment Code Errors
Error Code | Description |
---|---|
API_VALIDATION_ERROR400 |
Inputs are failing validation. The errors field contains details about which fields are violating validation. |
REQUEST_FORBIDDEN_ERROR403 |
API key in use does not have necessary permissions to perform the request. |
DATA_NOT_FOUND404 |
Could not find fixed payment code. |
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-KEYoptional |
string A unique key to prevent processing duplicate requests. Can be your external_id or any GUID. Must be unique across development & production environments.
|
Parameter | Description |
---|---|
external_idrequired |
string ID of the disbursement in your system, used to reconcile disbursements after they have been completed.
|
bank_coderequired |
string Code of the destination bankThe bank code must match the bank codes here precisely |
account_holder_namerequired |
string Name of account holder as per the bank's or e-wallet's records. Used for verification and error/customer support scenarios.
|
account_numberrequired |
string Destination bank account number. If disbursing to an e-wallet, phone number registered with the e-wallet account.
|
descriptionrequired |
string Description to send with the disbursement
|
amountrequired |
number Amount to disburse
|
email_tooptional |
string[] Email addresses that get notified of disbursement details after the disbursement is completed.Maximum 3 email addresses accepted. |
email_ccoptional |
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_bccoptional |
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 |
---|---|
idrequired |
string Unique disbursement ID |
user_idrequired |
string Your Instamoney Business ID |
external_idrequired |
string Custom ID of your choice to identify the transaction. Our customers often use a phone number, email address, or transaction/order ID |
amountrequired |
number Amount to disburse |
bank_coderequired |
string Bank code of destination bank or e-wallet. See bank codes |
account_holder_namerequired |
string Name of account holder as per the bank's or e-wallet’s records. Used for verification and error/customer support scenarios |
disbursement_descriptionrequired |
This is the description you give us :) |
statusrequired |
string PENDING Transfer is initiated but not yet completed by bank. |
email_tooptional |
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_ccoptional |
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_bccoptional |
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_ERROR400 |
Inputs are failing validation. The errors field contains details about which fields are violating validation. |
INVALID_JSON_FORMAT400 |
The request body is not a valid JSON format. |
DISBURSEMENT400 |
Disbursement description is not set in Dashboard > Configuration > Disbursement. Add a default description before retrying. |
DIRECT_DISBURSEMENT400 |
Not enough balance to disburse. Add more balance before retrying. |
DUPLICATE_TRANSACTION400 |
Idempotency key has been used before. Use a unique idempotency key and try again. |
BANK_CODE_NOT400 |
Destination bank code is not supported. |
RECIPIENT400 |
For transfers to BCA, account_number input needs to be 10 digits. Check the account number length before retrying. |
RECIPIENT400 |
The transfer amount requested is lower than the prescribed minimum for the chosen destination bank. Amend the transfer amount before retrying. |
MAXIMUM400 |
The transfer amount requested is higher than the prescribed maximum for the chosen destination bank. Amend the transfer amount before retrying. |
INVALID400 |
The account number is unable to processed. Use different account number to retry. |
SERVER_ERROR500 |
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_idrequired |
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 |
---|---|
id | Unique disbursement ID |
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. |
failure_code (optional) |
INSUFFICIENT_BALANCE The balance in your account is insufficient to make the disbursement in the desired amountUNKNOWN_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 hoursINVALID_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 accountSWITCHING_NETWORK_ERROR At least one of the switching networks is encountering an issue. Please retry the disbursement in 1-3 hoursREJECTED_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 informationTEMPORARY_TRANSFER_ERROR We’ve encountered a temporary issue while processing this disbursement. Please retry the disbursement in 1-2 hours |
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_FORMAT400 |
The request body is not a valid JSON format. |
INVALID_PERMISSION403 |
Could not access that disbursement. |
DIRECT_DISBURSEMENT404 |
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_idrequired |
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 |
---|---|
id | Unique disbursement ID |
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. |
failure_code (optional) |
INSUFFICIENT_BALANCE The balance in your account is insufficient to make the disbursement in the desired amountUNKNOWN_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 hoursINVALID_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 accountSWITCHING_NETWORK_ERROR At least one of the switching networks is encountering an issue. Please retry the disbursement in 1-3 hoursREJECTED_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 informationTEMPORARY_TRANSFER_ERROR We’ve encountered a temporary issue while processing this disbursement. Please retry the disbursement in 1-2 hours |
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_DISBURSEMENT404 |
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'
Header Parameter | Description |
---|---|
x-callback-token | Your Instamoney unique callback token to verify the origin of the callback |
webhook-id | A unique identifier of every webhook to help you to handle double callback by implementing idempotency. When you receive the same webhook-id twice, treat the subsequent request as duplicate and reject the webhook accordingly to prevent double webhook |
Parameter | Description |
---|---|
id | Unique disbursement ID |
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 amountUNKNOWN_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 hoursINVALID_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 accountSWITCHING_NETWORK_ERROR At least one of the switching networks is encountering an issue. Please retry the disbursement in 1-3 hoursREJECTED_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 informationTEMPORARY_TRANSFER_ERROR We’ve encountered a temporary issue while processing this disbursement. Please retry the disbursement in 1-2 hours |
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. |
is_instant | Indicates whether the disbursement is being disbursed instantly |
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
Our eWallet API allows you to seamlessly charge and receive payments directly from top ewallets providers in SEA. With one integration, get access to all our available eWallets and upcoming eWallets integrations as well. To date, we've processed millions of eWallet transactions and support various business use cases
Create eWallet Charge
Endpoint: Create eWallet Charge Request
POST https://api.instamoney.co/ewallets/charges
Version
You are currently viewing the newest version of our eWallets API. In this API version, integrate once to get access to all available eWallets and future eWallets in Instamoney! This API will also be used to support tokenized payment flow and auth/capture payment flow in the near future. Click here to view older versions.
Version | Changelog |
---|---|
2021-01-25 Latest |
New simple and consistent eWallets API to support top eWallets providers in Indonesia No API Versioning is required. You can access the new API easily by calling POST /ewallets/charges |
2020-02-01 | Implemented the asynchronous flow for OVO payment callbacks. |
2019-02-04 | Returns a response immediately without any callbacks returned. |
eWallet
Request Parameters
Example: Create eWallet Charge Request
curl https://api.instamoney.co/ewallets/charges -X POST \
--user xnd_development_LoReMIPman+ZPGT+ZZ9b3ooF4w3Dn+R1k+LoReMIPman: \
--header 'content-type: application/json' \
--data '{
"reference_id": "order-id-123",
"currency": "IDR",
"amount": 25000,
"checkout_method": "ONE_TIME_PAYMENT",
"channel_code": "ID_SHOPEEPAY",
"channel_properties": {
"success_redirect_url": "https://redirect.me/payment"
},
"metadata": {
"branch_area": "PLUIT",
"branch_city": "JAKARTA"
}
}' \
try {
Instamoney.apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
Map<String, String> channelProperties = new HashMap<>();
channelProperties.put("success_redirect_url", "https://dashboard.instamoney.co/register/1");
Map<String, String> metadata = new HashMap<>();
metadata.put("branch_code", "tree_branch");
Map<String, Object> params = new HashMap<>();
params.put("reference_id", "test-reference-id");
params.put("currency", "IDR");
params.put("amount", 1000);
params.put("checkout_method", "ONE_TIME_PAYMENT");
params.put("channel_code", "ID_SHOPEEPAY");
params.put("channel_properties", channelProperties);
params.put("metadata", metadata);
EWalletCharge charge = EWalletCharge.createEWalletCharge(params);
} catch (InstamoneyException e) {
e.printStackTrace();
}
<?php
use Instamoney\Instamoney;
require 'vendor/autoload.php';
Instamoney::setApiKey('xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==');
$params = [
'reference_id' => 'test-reference-id',
'currency' => 'IDR',
'amount' => 1000,
'checkout_method' => 'ONE_TIME_PAYMENT',
'channel_code' => 'ID_SHOPEEPAY',
'channel_properties' => [
'success_redirect_url' => 'https://dashboard.instamoney.co/register/1',
],
'metadata' => [
'branch_code' => 'tree_branch'
]
];
$createEWalletCharge = \Instamoney\EWallets::createEWalletCharge($ewalletChargeParams);
var_dump($createEWalletCharge);
?>
from instamoney import EWallet
ewallet_charge = EWallet.create_ewallet_charge(
reference_id="test-reference-id",
currency="IDR",
amount=1000,
checkout_method="ONE_TIME_PAYMENT",
channel_code="ID_SHOPEEPAY",
channel_properties={
"success_redirect_url": "https://dashboard.instamoney.co/register/1",
},
metadata={
"branch_code": "tree_branch",
},
)
instamoney.Opt.SecretKey = "xnd_development_P4qDfOss0OCpl8RtKrRuIruiRuiQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
data := ewallet.CreateEWalletChargeParams{
ReferenceID: "test-reference-id",
Currency: "IDR",
Amount: 1000,
CheckoutMethod: "ONE_TIME_PAYMENT",
ChannelCode: "ID_SHOPEEPAY",
ChannelProperties: map[string]string{
"success_redirect_url": "https://dashboard.instamoney.co/register/1",
},
Metadata: map[string]interface{}{
"branch_code": "tree_branch",
},
}
charge, chargeErr := ewallet.CreateEWalletCharge(&data)
if chargeErr != nil {
log.Fatal(chargeErr)
}
fmt.Printf("created e-wallet charge: %+v\n", charge)
const x = new require("instamoney-node")({
secretKey:
"xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==",
});
const { EWallet } = x;
const ewalletSpecificOptions = {};
const ew = new EWallet(ewalletSpecificOptions);
const resp = await ew.createEWalletCharge({
referenceID: 'test-reference-id',
currency: 'IDR',
amount: 1000,
checkoutMethod: 'ONE_TIME_PAYMENT',
channelCode: 'ID_SHOPEEPAY',
channelProperties: {
successRedirectURL: 'https://dashboard.instamoney.co/register/1',
},
metadata: {
branch_code: 'tree_branch'
}
});
console.log(resp);
Body Parameter | Type | Description | ||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
reference_idrequired |
string |
Reference ID provided by merchant (255 characters) Note: It has to be unique per charge request |
||||||||||||||||||||||||
currencyrequired |
string |
Currency used for the transaction in ISO4217 format - IDR |
||||||||||||||||||||||||
amountrequired |
number |
Transaction amount to be paid Min - 100 IDR Max - based on eWallet holding limit |
||||||||||||||||||||||||
checkout_methodrequired |
string |
Checkout method determines the payment flow used to process the transactionONE_TIME_PAYMENT is used for single guest checkoutsTOKENIZED_PAYMENT can be used for recurring payment |
||||||||||||||||||||||||
channel_coderequired if checkout_method =
|
string |
Channel Code specifies which eWallet will be used to process the transaction - ID_OVO , ID_DANA , ID_LINKAJA , ID_SHOPEEPAY |
||||||||||||||||||||||||
channel_propertiesrequired if checkout_method =
|
object |
Channel specific information required for the transaction to be initiated OVO required fields
DANA, LINKAJA, SHOPEEPAY required fields
|
||||||||||||||||||||||||
payment_method_idrequired if checkout_method =
|
string |
ID of the payment method | ||||||||||||||||||||||||
customer_idoptional |
string |
ID of the customer object to which the account token will be linked to | ||||||||||||||||||||||||
basketoptional |
array |
Array of objects describing the item(s) purchased Object parameters details
|
||||||||||||||||||||||||
metadataoptional |
object |
Object of additional information the user may use. Users define 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. This will only be used by the user and not Instamoney. |
Response Parameters
Example: Create eWallet Charge Request API Success Response
{
"id": "ewc_bb8c3po-c3po-r2d2-c3po-r2d2c3por2d2",
"business_id": "5f218745736e619164dc8608",
"reference_id": "test-reference-id",
"status": "PENDING",
"currency": "IDR",
"charge_amount": 1000,
"capture_amount": 1000,
"checkout_method": "ONE_TIME_PAYMENT",
"channel_code": "ID_SHOPEEPAY",
"channel_properties": {
"success_redirect_url": "https://dashboard.instamoney.co/register/1"
},
"actions": {
"desktop_web_checkout_url": null,
"mobile_web_checkout_url": null,
"mobile_deeplink_checkout_url": "https://deeplinkcheckout.this/",
"qr_checkout_string": "ID123InstamoneyQRTest321DI"
},
"is_redirect_required": true,
"callback_url": "https://calling-back.com/instamoney/shopeepay",
"created": "2017-07-21T17:32:28Z",
"updated": "2017-07-21T17:32:28Z",
"voided_at": null,
"capture_now": true,
"customer_id": null,
"payment_method_id": null,
"failure_code": null,
"basket": null,
"metadata": {
"branch_code": "tree_branch"
}
}
Body Parameter | Type | Description | ||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
idrequired |
string |
Unique identifier for charge request transaction. It will always have the prefix of 'ewc_', followed by a UUIDv4 | ||||||||||||||||||||||||||||||
business_idrequired |
string |
Business ID of the merchant | ||||||||||||||||||||||||||||||
reference_idrequired |
string |
Reference ID provided by merchant Note: It has to be unique per payment request. |
||||||||||||||||||||||||||||||
statusrequired |
string |
Status of charge request
|
||||||||||||||||||||||||||||||
currencyrequired |
string |
Currency used for the transaction in ISO4217 format - IDR |
||||||||||||||||||||||||||||||
charge_amountrequired |
number |
Requested charge amount from merchant | ||||||||||||||||||||||||||||||
capture_amountoptional |
number |
Requested capture amount from merchant. In requests where checkout_method = ONE_TIME_PAYMENT, capture_amount will always be the same as charge_amount | ||||||||||||||||||||||||||||||
checkout_methodrequired |
string |
Checkout method determines the payment flow used to process the transactionONE_TIME_PAYMENT is used for single guest checkouts |
||||||||||||||||||||||||||||||
channel_coderequired |
string |
Channel Code specifies which eWallet will be used to process the transaction - ID_OVO , ID_DANA , ID_LINKAJA , ID_SHOPEEPAY |
||||||||||||||||||||||||||||||
channel_propertiesoptional |
object |
Channel specific information required for the transaction to be initiated OVO required fields
DANA, LINKAJA, SHOPEEPAY required fields
|
||||||||||||||||||||||||||||||
actionsoptional |
string |
Redirection actions to be taken when is_redirect_required returned in response is true . Merchants should choose one of the available options based on the ideal experience for their payment flows
Channels with redirection required
|
||||||||||||||||||||||||||||||
is_redirect_requiredrequired |
boolean |
Flag which indicates whether redirection is required for end user to complete payment When True, merchants should redirect the end user to the url given in the “actions” field. When False, there is no need for redirection for payment process to continue |
||||||||||||||||||||||||||||||
callback_urlrequired |
string |
Callback URL which payment notifications will be sent | ||||||||||||||||||||||||||||||
createdrequired |
string |
ISO 8601 Timestamp for charge object creation. Timezone UTC+0 | ||||||||||||||||||||||||||||||
updatedrequired |
string |
ISO 8601 Timestamp for latest charge object update. Timezone UTC+0 | ||||||||||||||||||||||||||||||
voided_atoptional |
string |
ISO 8601 Timestamp when transaction was voided. Timezone UTC+0 | ||||||||||||||||||||||||||||||
capture_nowrequired |
string |
Default: true . Field not in use currently |
||||||||||||||||||||||||||||||
customer_idoptional |
string |
ID of the customer object created with Instamoney. ID to will be linked to the transaction | ||||||||||||||||||||||||||||||
payment_method_idoptional |
string |
Instamoney’s identifier for end user payment tokens binded with merchant. Only used for channels which support tokenized payments | ||||||||||||||||||||||||||||||
failure_codeoptional |
string |
The failure_code is notified to the merchant in the payment callback or GET payment status after transaction is attempted by end user | ||||||||||||||||||||||||||||||
basketoptional |
array |
Array of objects describing the item(s) purchased Object parameters details
|
||||||||||||||||||||||||||||||
metadataoptional |
object |
User defined object with JSON properties and values passed in during charge creation. Object can be up to 50 keys, with key names up to 40 characters long and values up to 500 characters long. |
Error Codes
Example: Create eWallet Charge Request API Error Response
{
"error_code": "UNSUPPORTED_CURRENCY",
"message": "The payment currency request is not supported for this payment channel. Please refer to our API reference or docs to pick available currencies"
}
Error Code | Description |
---|---|
DUPLICATE_PAYMENT_REQUEST_ERROR400 |
The charge with the same reference_id has already been created before |
API_VALIDATION_ERROR400 |
There is invalid input in one of the required request fields |
UNSUPPORTED_CURRENCY400 |
The payment currency request is not supported for this payment channel. Please refer to our API reference or docs to pick available currencies |
INVALID_API_KEY401 |
API key format is invalid |
INVALID_MERCHANT_CREDENTIALS401 |
Merchant credentials met with an error with the eWallet provider. Please contact Instamoney customer support to resolve this issue |
REQUEST_FORBIDDEN_ERROR403 |
The API key is forbidden to perform this request |
CHANNEL_NOT_ACTIVATED403 |
Payment request failed because this specific payment channel has not been activated through Instamoney. Please activate via Instamoney dashboard or our customer service |
CALLBACK_URL_NOT_FOUND404 |
Payment request failed because there was no input of callback url in Instamoney Dashboard or request headers. Please save your callback url in Instamoney Dashboard |
UNSUPPORTED_CONTENT_TYPE403 |
The content type requested is not supported |
SERVER_ERROR500 |
An unexpected error occured, our team has been notified and will troubleshoot the issue |
CHANNEL_UNAVAILABLE503 |
The payment channel requested is currently experiencing unexpected issues. The eWallet provider will be notified to resolve this issue |
Get eWallet Charge Status
Endpoint: Get eWallet Charge Status
GET https://api.instamoney.co/ewallets/charges/{id}
This endpoint is used to get payment status of a charge request. You need to specify the id
in the response body when hitting create eWallet charge request
Version
You are currently viewing the newest version of our eWallets API. Click here to view older versions.
Request Parameters
Example: Check eWallet Charge Status Request
curl 'https://api.instamoney.co/ewallets/charges/ewc_bb8c3po-c3po-r2d2-c3po-r2d2c3por2d2' \
-X GET \
-u xnd_development_LoReMIPman+ZPGT+ZZ9b3ooF4w3Dn+R1k+LoReMIPman:
try {
Instamoney.apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
EWalletCharge charge = EWalletCharge.getEWalletChargeStatus("ewc_bb8c3po-c3po-r2d2-c3po-r2d2c3por2d2");
} catch (InstamoneyException e) {
e.printStackTrace();
}
<?php
use Instamoney\Instamoney;
require 'vendor/autoload.php';
Instamoney::setApiKey('xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==');
$charge_id = 'ewc_bb8c3po-c3po-r2d2-c3po-r2d2c3por2d2';
$getEWalletChargeStatus = \Instamoney\EWallets::getEWalletChargeStatus($charge_id);
var_dump($getEWalletChargeStatus);
?>
from instamoney import EWallet
ewallet_charge = EWallet.get_ewallet_charge_status(
charge_id="ewc_bb8c3po-c3po-r2d2-c3po-r2d2c3por2d2",
)
instamoney.Opt.SecretKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
data := ewallet.GetEWalletChargeStatusParams{
ChargeID: "ewc_bb8c3po-c3po-r2d2-c3po-r2d2c3por2d2",
}
charge, chargeErr := ewallet.GetEWalletChargeStatus(&data)
if chargeErr != nil {
log.Fatal(chargeErr)
}
fmt.Printf("retrieved e-wallet charge: %+v\n", charge)
const x = new require("instamoney-node")({
secretKey:
"xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==",
});
const { EWallet } = x;
const ewalletSpecificOptions = {};
const ew = new EWallet(ewalletSpecificOptions);
const resp = await ew.getEWalletChargeStatus({
chargeID: 'ewc_bb8c3po-c3po-r2d2-c3po-r2d2c3por2d2',
});
console.log(resp);
Query Parameter | Type | Description |
---|---|---|
charge_id required |
string |
You need to specify the id in the response body when hitting create eWallet charge request |
Example: Check eWallet Charge Status Success Responses
Check eWallet Charge Status Success Responses
{
"id": "ewc_bb8c3po-c3po-r2d2-c3po-r2d2c3por2d2",
"business_id": "5f218745736e619164dc8608",
"reference_id": "test-reference-id",
"status": "PENDING",
"currency": "IDR",
"charge_amount": 1000,
"capture_amount": 1000,
"checkout_method": "ONE_TIME_PAYMENT",
"channel_code": "ID_SHOPEEPAY",
"channel_properties": {
"success_redirect_url": "https://dashboard.instamoney.co/register/1"
},
"actions": {
"desktop_web_checkout_url": null,
"mobile_web_checkout_url": null,
"mobile_deeplink_checkout_url": "https://deeplinkcheckout.this/",
"qr_checkout_string": "ID123InstamoneyQRTest321DI"
},
"is_redirect_required": true,
"callback_url": "https://calling-back.com/instamoney/shopeepay",
"created": "2017-07-21T17:32:28Z",
"updated": "2017-07-21T17:32:28Z",
"voided_at": null,
"capture_now": true,
"customer_id": null,
"payment_method_id": null,
"failure_code": null,
"basket": null,
"metadata": {
"branch_code": "tree_branch"
}
}
Body Parameter | Type | Description | ||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
idrequired |
string |
Unique identifier for charge request transaction. It will always have the prefix of 'ewc_', followed by a UUIDv4 | ||||||||||||||||||||||||
business_idrequired |
string |
Business ID of the merchant | ||||||||||||||||||||||||
reference_idrequired |
string |
Reference ID provided by merchant Note: It has to be unique per payment request. |
||||||||||||||||||||||||
statusrequired |
string |
Status of charge request
|
||||||||||||||||||||||||
currencyrequired |
string |
Currency used for the transaction in ISO4217 format - IDR |
||||||||||||||||||||||||
charge_amountrequired |
number |
Requested charge amount from merchant | ||||||||||||||||||||||||
capture_amountoptional |
number |
Requested capture amount from merchant. In requests where checkout_method = ONE_TIME_PAYMENT, capture_amount will always be the same as charge_amount | ||||||||||||||||||||||||
checkout_methodrequired |
string |
Checkout method determines the payment flow used to process the transactionONE_TIME_PAYMENT is used for single guest checkoutsTOKENIZED_PAYMENT can be used for recurring payment |
||||||||||||||||||||||||
channel_coderequired |
string |
Channel Code specifies which eWallet will be used to process the transaction - ID_OVO , ID_DANA , ID_LINKAJA , ID_SHOPEEPAY |
||||||||||||||||||||||||
channel_propertiesoptional |
object |
Channel specific information required for the transaction to be initiated OVO required fields
DANA, LINKAJA, SHOPEEPAY required fields
|
||||||||||||||||||||||||
actionsoptional |
string |
Redirection actions to be taken when is_redirect_required returned in response is true . Merchants should choose one of the available options ased on the ideal experience for their payment flows
|
||||||||||||||||||||||||
is_redirect_requiredrequired |
boolean |
Flag which indicates whether redirection is required for end user to complete payment When True, merchants should redirect the end user to the url given in the “actions” field. When False, there is no need for redirection for payment process to continue |
||||||||||||||||||||||||
callback_urlrequired |
string |
Callback URL which payment notifications will be sent | ||||||||||||||||||||||||
createdrequired |
string |
ISO 8601 Timestamp for charge object creation. Timezone UTC+0 | ||||||||||||||||||||||||
updatedrequired |
string |
ISO 8601 Timestamp for latest charge object update. Timezone UTC+0 | ||||||||||||||||||||||||
voided_atoptional |
string |
ISO 8601 Timestamp when transaction was voided. Timezone UTC+0 | ||||||||||||||||||||||||
capture_nowrequired |
string |
Default: true . Field not in use currently |
||||||||||||||||||||||||
customer_idoptional |
string |
ID of the customer object created with Instamoney. ID to will be linked to the transaction | ||||||||||||||||||||||||
payment_method_idoptional |
string |
ID of the payment method. Only used for channels which support tokenized payments | ||||||||||||||||||||||||
failure_codeoptional |
string |
Reason for failure of payment by end user or eWallet issuer. The failure_code is notified to the merchant in the payment callback or GET payment status after transaction is attempted by end user | ||||||||||||||||||||||||
basketoptional |
array |
Array of objects describing the item(s) purchased Object parameters details
|
||||||||||||||||||||||||
metadataoptional |
object |
User defined object with JSON properties and values passed in during charge creation. Object can be up to 50 keys, with key names up to 40 characters long and values up to 500 characters long. |
Error Codes
Example: Create eWallet Charge Request API Error Response
{
"error_code": "INVALID_API_KEY",
"message": "API key format is invalid"
}
Error Code | Description |
---|---|
API_VALIDATION_ERROR400 |
There is invalid input in one of the required request fields |
INVALID_API_KEY401 |
API key format is invalid |
INVALID_MERCHANT_CREDENTIALS401 |
Merchant credentials met with an error with the eWallet provider. Please contact Instamoney customer support to resolve this issue |
DATA_NOT_FOUND404 |
Charge ID specified was not found. Please check your query again. |
SERVER_ERROR500 |
An unexpected error occured, our team has been notified and will troubleshoot the issue |
Payment Status Callback
You need to provide an endpoint your system to receive all payment callback notification from our system. You will receive the callback when end-customer attempted payments for available eWallets. Please specify this endpoint in Instamoney dashboard callback url page under eWallets paid
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 and will not attempt to retry the notification.
Callback Payload
Example: Success Payment Callback Payload
{
"event": "ewallet.capture",
"business_id": "5abe2389ewpejrt238",
"created": "2020-04-20T16:25:52Z",
"data": {
"id": "ewc_bb8c3po-c3po-r2d2-c3po-r2d2c3por2d2",
"business_id": "5f218745736e619164dc8608",
"reference_id": "test-reference-id",
"status": "SUCCEEDED",
"currency": "IDR",
"charge_amount": 1000,
"capture_amount": 1000,
"checkout_method": "ONE_TIME_PAYMENT",
"channel_code": "ID_SHOPEEPAY",
"channel_properties": {
"success_redirect_url": "https://dashboard.instamoney.co/register/1"
},
"actions": {
"desktop_web_checkout_url": null,
"mobile_web_checkout_url": null,
"mobile_deeplink_checkout_url": "https://deeplinkcheckout.this/",
"qr_checkout_string": "ID123InstamoneyQRTest321DI"
},
"is_redirect_required": true,
"callback_url": "https://calling-back.com/instamoney/shopeepay",
"created": "2017-07-21T17:32:28Z",
"updated": "2017-07-21T17:32:28Z",
"voided_at": null,
"capture_now": true,
"customer_id": null,
"payment_method_id": null,
"failure_code": null,
"basket": null,
"metadata": {
"branch_code": "tree_branch"
}
}
}
Header Parameter | Description |
---|---|
x-callback-token |
string Your Instamoney unique callback token to verify the origin of the callback |
webhook-id |
string A unique identifier of every webhook to help you to handle double callback by implementing idempotency. When you receive the same webhook-id twice, treat the subsequent request as duplicate and reject the webhook accordingly to prevent double webhook |
Body Parameter | Type | Description | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
eventrequired |
string |
Identifies the event triggering a notification to merchant. ewallet.capture occurs when eWallet issuer confirms the payment status of a transaction |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
business_idrequired |
string |
Business ID of the merchant | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
createdrequired |
string |
ISO 8601 Timestamp for callback notification creation. Timezone UTC+0. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
dataoptional |
object |
eWallets charge object will be nested in this parameter. See here for full definitions Data fields
|
Failure Codes
Example: Failed Payment Callback Payload
{
"event": "ewallet.capture",
"business_id": "5abe2389ewpejrt238",
"created": "2020-04-20T16:25:52Z",
"data": {
"id": "ewc_bb8c3po-c3po-r2d2-c3po-r2d2c3por2d2",
"business_id": "5f218745736e619164dc8608",
"reference_id": "test-reference-id",
"status": "FAILED",
"currency": "IDR",
"charge_amount": 1000,
"capture_amount": 1000,
"checkout_method": "ONE_TIME_PAYMENT",
"channel_code": "ID_SHOPEEPAY",
"channel_properties": {
"success_redirect_url": "https://dashboard.instamoney.co/register/1"
},
"actions": {
"desktop_web_checkout_url": null,
"mobile_web_checkout_url": null,
"mobile_deeplink_checkout_url": "https://deeplinkcheckout.this/",
"qr_checkout_string": "ID123InstamoneyQRTest321DI"
},
"is_redirect_required": true,
"callback_url": "https://calling-back.com/instamoney/shopeepay",
"created": "2017-07-21T17:32:28Z",
"updated": "2017-07-21T17:32:28Z",
"voided_at": null,
"capture_now": true,
"customer_id": null,
"payment_method_id": null,
"failure_code": "USER_DID_NOT_AUTHORIZE_THE_PAYMENT",
"basket": null,
"metadata": {
"branch_code": "tree_branch"
}
}
}
Failure Code | Failure Message |
---|---|
ACCOUNT_ACCESS_BLOCKED |
End user’s account cannot be accessed as it has been restricted by the eWallet provider. End user should contact the provider for resolution. |
INVALID_MERCHANT_CREDENTIALS |
Merchant credentials met with an error with the eWallet provider. Please contact Instamoney customer support to resolve this issue. |
USER_DECLINED_PAYMENT |
End user declined the payment request. |
INVALID_ACCOUNT_DETAILS |
End user provided incorrect information for this transaction. |
MAXIMUM_LIMIT_REACHED |
Accumulated value of payment requested for this end user went above the maximum transaction limit set by end user or eWallets. Payment can be retried when the transaction limit is reset. |
USER_UNREACHABLE |
End user’s device cannot be reached at this moment. Common reasons include unstable network, device error or jailbroken device. |
CHANNEL_UNAVAILABLE |
The payment channel requested is currently experiencing unexpected issues. The eWallet provider will be notified to resolve this issue. |
INSUFFICIENT_BALANCE |
End user has insufficient balance to complete the transaction. |
ACCOUNT_NOT_ACTIVATED |
End user’s account cannot be accessed as it has not been activated. End user should set up their account and ensure there is sufficient balance before retrying. |
INVALID_TOKEN |
Binding for this end user has expired. Please reinitiate binding before retrying. |
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
|
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.cityoptional |
string Customer’s city |
address.suburboptional |
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
|
identification.npwp_number optional |
string Nomor Pokok Wajib Pajak (tax number) of the customerOnly allowed if customer_type is INDIVIDUAL
|
identification.drivers_license optional |
string Surat Izin Mengemudi (driver’s licence) number of the customerOnly allowed if customer_type is INDIVIDUAL
|
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 statusShould 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 statusExample: +62812XXXXXX |
phone_number optional |
string Customer’s land line or alternate phone number with international prefixExample: +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 |
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
|
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.cityoptional |
string Customer’s city |
address.suburboptional |
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
|
identification.npwp_number optional |
string Nomor Pokok Wajib Pajak (tax number) of the customerOnly allowed if customer_type is INDIVIDUAL
|
identification.drivers_license optional |
string Surat Izin Mengemudi (driver’s licence) number of the customerOnly allowed if customer_type is INDIVIDUAL
|
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 statusShould 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 statusExample: +62812XXXXXX |
phone_number optional |
string Customer’s land line or alternate phone number with international prefixExample: +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 |
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 |
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):
|
||||||||||
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):
|
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):
|
||||
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):
|
||||||||||
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 OTPfalse 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
|
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):
|
||||||||||
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
}
Header Parameter | Description |
---|---|
x-callback-token |
string Your Instamoney unique callback token to verify the origin of the callback |
webhook-id |
string A unique identifier of every webhook to help you to handle double callback by implementing idempotency. When you receive the same webhook-id twice, treat the subsequent request as duplicate and reject the webhook accordingly to prevent double webhook |
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 six times with exponential backoff between each interval and will stop retrying until we have received response from your server or there is still no response yet
Retry Number | Interval (relative to last retry) | Interval (relative to original attempt) |
---|---|---|
1 | 15m | 15m |
2 | 45m | 1h |
3 | 2h | 3h |
4 | 3h | 6h |
5 | 6h | 12h |
6 | 12h | 24h |
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.
Reports
Report Object
Report Object Example
{
"id": "report_5c1b34a2-6ceb-4c24-aba9-c836bac82b28",
"type": "BALANCE_HISTORY",
"status": "COMPLETED",
"filter": {
"from": "2021-06-23T04:01:55.574Z",
"to": "2021-06-24T04:01:55.574Z"
},
"format": "CSV",
"url": "https://transaction-report-files.s3-us-west-2.amazonaws.com/{report_name}",
"currency": "IDR",
"business_id": "5f34f60535ba7c1c0eed846a",
"created": "2021-06-24T04:01:55.570Z",
"updated": "2021-06-24T04:01:55.570Z"
}
Body Parameter | Type | Description | ||||||||
---|---|---|---|---|---|---|---|---|---|---|
id required |
string |
The unique id of report. It will have report_ as prefix. |
||||||||
type required |
string |
The type of report. Available types:
| ||||||||
filter required |
object |
Filtering that are applied to report.Filter Parameter
|
||||||||
format required |
string |
The format of the report. Available format is CSV . |
||||||||
status required |
string |
The status of the report. The status will be PENDING when you hit generate the report and will change after that.
|
||||||||
url optional |
string |
URL to download after report is completed. The file to download will only be accessible for 24 hours. When the url is expired, you will need to send a new request to generate the report. |
||||||||
currency required |
string |
The currency inside the report. |
||||||||
business_id required |
string |
The id of business where this transaction belong to. | ||||||||
created required |
string (ISO 8601 |
The time when the report request is created at UTC+0. | ||||||||
updated required |
string (ISO 8601 |
The time when the report is updated at UTC+0. |
Generate Report
Endpoint: Generate Report
POST https://api.instamoney.co/reports
Request this endpoint to generate the report. You can specify the type and filter the content of the report. The flow of this endpoint is asynchronous. It means Instamoney will send callbacks to you after the report is done. See report callback for more information. Alternatively, you can use the get report endpoint to get the report status and its detail.
Request Parameters
Example Generate Report Request
curl https://api.instamoney.co/reports -X POST \
-u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==: \
-d type=BALANCE_HISTORY \
-d currency=IDR
Example Generate Report Response
{
"id": "report_5c1b34a2-6ceb-4c24-aba9-c836bac82b28",
"type": "BALANCE_HISTORY",
"status": "PENDING",
"filter": {
"from": "2021-06-23T04:01:55.574Z",
"to": "2021-06-24T04:01:55.574Z"
},
"format": "CSV",
"currency": "IDR",
"business_id": "5f34f60535ba7c1c0eed846a",
"created": "2021-06-24T04:01:55.570Z",
"updated": "2021-06-24T04:01:55.570Z"
}
Body Parameter | Type | Description | ||||||||
---|---|---|---|---|---|---|---|---|---|---|
type required |
string |
The type of report that will be generated. Available types:
| ||||||||
filter required |
object |
Filtering that are applied to report. Filter Parameter
The combination of from and to must be less than 31 days. |
||||||||
format optionaldefault:
|
string |
The format of the report. Available format is CSV . |
||||||||
currency optionaldefault:
|
string |
The currency to filter. |
||||||||
report_version optional |
string |
Report version indicates which version of report you need. This parameter is only applicable to Transaction Report. Default value: VERSION_0 Version value <> changelog: |
Response Parameters
Return Report Object with status code 201
Error Codes
See other common errors here.
Error Code | Description |
---|---|
FEATURE_NOT_AVAILABLE400 |
During this beta, some of customer may encounter this error. Please contact our customer support to enable this feature. |
INVALID_DATE_RANGE400 |
The from and to filter range is too huge. Please reduce the range according to limit on the request parameter. |
Get Report
Endpoint: Get Report
GET https://api.instamoney.co/reports/{report_id}
Request this endpoint to get single specific report details by report id. You can use this endpoint as alternative compared to using the report callback.
Request Parameters
Example Get Report
curl https://api.instamoney.co/transactions/report_5c1b34a2-6ceb-4c24-aba9-c836bac82b28 -X GET \
-u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:
Example Get Report Response
{
"id": "report_5c1b34a2-6ceb-4c24-aba9-c836bac82b28",
"type": "BALANCE_HISTORY",
"status": "COMPLETED",
"filter": {
"from": "2021-06-23T04:01:55.574Z",
"to": "2021-06-24T04:01:55.574Z"
},
"format": "CSV",
"url": "https://transaction-report-files.s3-us-west-2.amazonaws.com/{report_name}",
"currency": "IDR",
"business_id": "5f34f60535ba7c1c0eed846a",
"created": "2021-06-24T04:01:55.570Z",
"updated": "2021-06-24T04:01:55.570Z"
}
Path Parameter | Type | Description |
---|---|---|
report_id required |
string |
The id of report. |
Response Parameters
Return Report Object with status code 200
Error Codes
See other common errors here.
Error Code | Description |
---|---|
TRANSACTION_NOT_FOUND404 |
Report the id is not found. |
FEATURE_NOT_AVAILABLE400 |
During this beta, some of customer may encounter this error. Please contact our customer support to enable this feature. |
Report Webhook
Endpoint: Report Webhook
POST https://yourcompany.com/report_webhook_url
Instamoney notifies your system upon the completed or failed report via webhook. You need to provide an URL to receive webhook. Please specify your URL in Webhook Settings in Instamoney Dashboard.
The notification will be sent as POST request to the URL you set. Instamoney attach x-callback-token
header that you can validate against Verification Token in Webhook Settings to verify message authenticity.
Please response back with status 200 immediately. Instamoney marks webhook event as failed if there is no response within 30s. When events failed, automatic retry will kick-off for the next 24h. Alternatively, you can resend any event in Webhook tab at anytime. You can also receive notification via email every 6h to check your webhook health.
Webhook Payload
Example Report Webhook Request for Successful Report
curl --include \
--request POST \
--header "x-callback-token: MuaJALKJSDK12LASHD123kSAKSDHzjahwUWjkasJSDSA12KSNAK21n==" \
--header "Content-Type: application/json" \
--data-binary "{
\"id\": \"report_5c1b34a2-6ceb-4c24-aba9-c836bac82b28\",
\"type\": \"BALANCE_HISTORY\",
\"status\": \"PENDING\",
\"filter\": {
\"from\": \"2021-06-23T04:01:55.574Z\",
\"to\": \"2021-06-24T04:01:55.574Z\"
},
\"format\": \"CSV\",
\"currency\": \"IDR\",
\"business_id\": \"5f34f60535ba7c1c0eed846a\",
\"created\": \"2021-06-24T04:01:55.570Z\",
\"updated\": \"2021-06-24T04:01:55.570Z\"
}}" \
'{{your_company_domain}}/{{webhook_url}}'
Header Parameter | Type | Description |
---|---|---|
x-callback-token |
string |
Your Instamoney unique webhook token to verify the origin of the webhook |
webhook-id |
string |
A unique identifier of every webhook to help you to handle double webhooks by implementing idempotency. When you receive the same webhook-id twice, treat the subsequent request as duplicate and reject the webhook accordingly to prevent double webhooks |
Body Parameter | Type | Description | ||||||
---|---|---|---|---|---|---|---|---|
event required |
string |
The type of the event. The available types are:
| ||||||
Report Object |
The rest of parameter is the same as report object. |
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:
- Incomplete data
- Invalid data
- Duplicate data (e.g., retry the same request to see what happens)
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:
- Gracefully handles delayed callback notifications
- Gracefully handles duplicate callback notifications
- Does not require event notifications to occur in a specific order
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.6.6 (Nov 02, 2021)
- Add status explanation on callback RO ID
Version 1.6.5 (Oct 18, 2021)
- Add new error code 'INVALID_DESTINATION' in Create Disbursement
Version 1.6.4 (Sep 22, 2021)
- Add Characters and Special Characters for FPC RO
Version 1.6.3 (Aug 25, 2021)
- Add BNI VA Name Prefix
- Add is_activated parameter in Get VA Bank Endpoint
Version 1.6.2 (Jul 30, 2021)
- Update disbursement amount limits to SAHABAT_SAMPOERNA
Version 1.6.1 (Jul 12, 2021)
- Add information about barcode in Retail Outlet
- Add BNI_SYARIAH and ARTAJASA for the supported banks in Virtual Account
Version 1.5.1 (May 6, 2021)
- New eWallets endpoint with OVO, DANA, LINKAJA and SHOPEEPAY
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)
- Update Retail Outlet Alfamart maximum expected amount, from Rp 5,000,000 to Rp 2,500,000
Version 1.4.9 (August 19, 2020)
- Add Update Fixed Virtual Account Request to Postman
- Add Get Fixed Virtual Account Payment Request to Postman
- Add Update Fixed Virtual Account Details Request to Postman
- Add Update Fixed Payment Code Request to Postman
- Add Get Fixed Payment Code Request to Postman
Version 1.4.8 (August 18, 2020)
- Change RO maximum external_id length from 1000 to 950
- Change VA maximum external_id length from 1000 to 950
Version 1.4.7 (August 7, 2020)
- Added feedback component
Version 1.4.6 (August 3, 2020)
- Added Customers Endpoints
- Added Direct Debit Endpoints
Version 1.4.5 (June 18, 2020)
- Added SAHABAT_SAMPOERNA and PERMATA for Virtual Accounts
- Added sender_name field for Virtual Account callback response
Version 1.4.4 (May 6, 2020)
- Edited OVO magic number and scenarios
Version 1.4.3 (March 14, 2020)
- Add PERMATA in no limit amount in disburse funds section
Version 1.4.2 (February 3, 2020)
- Add CIMB and CIMB_UUS in no limit amount in disburse funds section
Version 1.4.1 (January 30, 2020)
- Add BRI in no limit amount in disburse funds section
Version 1.4.0 (December 20, 2019)
- New Authentication section
- New Libraries/SDKs section
- New Errors section
- Introduce new error code
REQUEST_FORBIDDEN_ERROR
with HTTP status code403
in Errors section - New Callback section
- New Test scenarios section
- New Checklists section
- New Changelog section
Version 1.3.4 (December 15, 2019)
- Update Disbursement amount limits