Select Language

curl dart go java javascript php python

Introduction

Welcome to OY! API Documentation. Our API services are organized around REST, accepts form-encoded request bodies and returns JSON-encoded responses.

Definition

For the purpose of standardization and to prevent any misunderstanding, below our the terms we are going to use in this documentation:

Business Flow

Signup for Trial

After partner has acquired access to OY! API Services, then:

  1. Partner can topup OY! Account Deposit via Virtual Accounts
  2. Once Deposit balance is active, Partner can use the API services provided

Postman

Postman is a free web testing service that provides an easy, fast, and solid software for developers to learn and maintain a web service contract from both the provider and consumer. As such, Postman has become a widely used tool for contract testing and reference due to its User Experience.

To streamline development and integration with OY!, we have created a Postman Collection at your disposal. Get started by installing Postman here.

Prerequisites: You must have received an authorization Username and API Key from us to access our feature. Contact us at partner@oyindonesia.com to receive your authorization information now.

Getting Started

The easiest way to get started using our API is to use our Postman Collection. Postman is a free client application that enables you to make calls using API easily. To make integrating with our API easier, we have created Postman Collection of all our endpoints so that you can test our APIs more easily.

The following is an outline of actions to get started with Postman

Run in Postman

You’ll need to create a OY! indonesia account to access OY! APIs via Postman Collection

API Authorization

header

header_result

Create a Postman Variable Environment

The Postman Variable Environment provides you with the capabilities to save authorization configurations. You can use these saved configurations for all your Postman Requests. This step is optional.

header

header

header

You just set your authorization value header with environment variable which already configured.

Test one of our API Calls

header

If you were able to complete all these steps, your environment is working perfectly and is on the right track. Feel free to test out our other API products or contact us at partner@oyindonesia.com if you encountered any difficulties testing our Postman Collection.

Authentication

OY! API uses pair of API Key and IP Address to authenticate a partner request. Partner needs to register a unique IP Address which will be used as originating request for the API Services.

HTTPS Request

Disbursement API can be requested through HTTPS Request to OY! API Base URL endpoint. The HTTPS Header has to be used to allow proper authentication, additionally HTTPS Request should only be made from IP Address which has been registered in OY! System.

API Base URL

Production Environment: https://partner.oyindonesia.com

HTTPS Header

Use following HTTPS Headers when you make a call to OY! API

Header Type Description
Content-Type application/json The Content-Type field indicates that JSON type is acceptable to send to the recipient
Accept application/json The Accept field is used to specify that JSON type is acceptable for the response
X-OY-Username String(64) Partner Username to access OY! API services
X-Api-Key String(255) Partner API Key to access OY! API services

Account Inquiry

Account Inquiry APIs allow you to get beneficiary account details.

Invoice will be created on the first API hit of the day with status INITIATED. The next day, invoice will be updated with status UNPAID. The inquiry service can still be used if there are UNPAID invoices within the agreed grace period.

A scheduler will run every day to check if there is UNPAID invoice that needs to be paid to prevent the inquiry service to be blocked by our system and the invoice status will be updated to PAID. In the event that there is insufficient balance when the scheduler runs, it is the partner responsibility to ensure the invoice is paid accordingly via the payment endpoint or the business portal.

Account Inquiry

curl -X \
POST https://partner.oyindonesia.com/api/account-inquiry \
-H 'content-type: application/json' \
-H 'accept: application/json' \
-H 'x-oy-username:myuser' \
-H 'x-api-key:987654' \
-d '{
    "bank_code": "014", 
    "account_number": "1239812390"
}'
var headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json',
  'x-oy-username': '{{username}}',
  'x-api-key': '{{api-key}}'
};
var request = http.Request('POST', Uri.parse('{{base_url}}/api/account-inquiry'));
request.body = json.encode({
  "bank_code": "014",
  "account_number": "1280259361"
});
request.headers.addAll(headers);

http.StreamedResponse response = await request.send();

if (response.statusCode == 200) {
  print(await response.stream.bytesToString());
}
else {
  print(response.reasonPhrase);
}
package main

import (
  "fmt"
  "strings"
  "net/http"
  "io/ioutil"
)

func main() {

  url := "%7B%7Bbase_url%7D%7D/api/account-inquiry"
  method := "POST"

  payload := strings.NewReader(`{
    "bank_code": "014",
    "account_number": "1280259361"
}`)

  client := &http.Client {
  }
  req, err := http.NewRequest(method, url, payload)

  if err != nil {
    fmt.Println(err)
    return
  }
  req.Header.Add("Content-Type", "application/json")
  req.Header.Add("Accept", "application/json")
  req.Header.Add("x-oy-username", "{{username}}")
  req.Header.Add("x-api-key", "{{api-key}}")

  res, err := client.Do(req)
  if err != nil {
    fmt.Println(err)
    return
  }
  defer res.Body.Close()

  body, err := ioutil.ReadAll(res.Body)
  if err != nil {
    fmt.Println(err)
    return
  }
  fmt.Println(string(body))
}
OkHttpClient client = new OkHttpClient().newBuilder()
  .build();
MediaType mediaType = MediaType.parse("application/json");
RequestBody body = RequestBody.create(mediaType, "{\n    \"bank_code\": \"014\",\n    \"account_number\": \"1280259361\"\n}");
Request request = new Request.Builder()
  .url("{{base_url}}/api/account-inquiry")
  .method("POST", body)
  .addHeader("Content-Type", "application/json")
  .addHeader("Accept", "application/json")
  .addHeader("x-oy-username", "{{username}}")
  .addHeader("x-api-key", "{{api-key}}")
  .build();
Response response = client.newCall(request).execute();
var data = JSON.stringify({
  "bank_code": "014",
  "account_number": "1280259361"
});

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function() {
  if(this.readyState === 4) {
    console.log(this.responseText);
  }
});

xhr.open("POST", "%7B%7Bbase_url%7D%7D/api/account-inquiry");
xhr.setRequestHeader("Content-Type", "application/json");
xhr.setRequestHeader("Accept", "application/json");
xhr.setRequestHeader("x-oy-username", "{{username}}");
xhr.setRequestHeader("x-api-key", "{{api-key}}");

xhr.send(data);
<?php
require_once 'HTTP/Request2.php';
$request = new HTTP_Request2();
$request->setUrl('{{base_url}}/api/account-inquiry');
$request->setMethod(HTTP_Request2::METHOD_POST);
$request->setConfig(array(
  'follow_redirects' => TRUE
));
$request->setHeader(array(
  'Content-Type' => 'application/json',
  'Accept' => 'application/json',
  'x-oy-username' => '{{username}}',
  'x-api-key' => '{{api-key}}'
));
$request->setBody('{\n    "bank_code": "014",\n    "account_number": "1280259361"\n}');
try {
  $response = $request->send();
  if ($response->getStatus() == 200) {
    echo $response->getBody();
  }
  else {
    echo 'Unexpected HTTP status: ' . $response->getStatus() . ' ' .
    $response->getReasonPhrase();
  }
}
catch(HTTP_Request2_Exception $e) {
  echo 'Error: ' . $e->getMessage();
}
import http.client
import json

conn = http.client.HTTPSConnection("{{base_url}}")
payload = json.dumps({
  "bank_code": "014",
  "account_number": "1280259361"
})
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json',
  'x-oy-username': '{{username}}',
  'x-api-key': '{{api-key}}'
}
conn.request("POST", "/api/account-inquiry", payload, headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))

The above command returns JSON structured similar like this:

{
    "status": {
        "code": "000",
        "message": "Success"
    },
    "bank_code": "014",
    "account_number": "1239812390",
    "account_name": "John Doe",
    "timestamp": "2020-11-19T17:01:17",
    "id": "59e11245-4b36-4ed7-97be-0c501b8ae3c8",
    "invoice_id": "c0503fa6-a5b3-4816-bc07-241473357f58"
}

Use this API to get beneficiary account details.

HTTPS Request

[Production] POST https://partner.oyindonesia.com/api/account-inquiry
[Staging] POST https://api-stg.oyindonesia.com/api/account-inquiry

Request Parameters

Parameter Type Required Description
bank_code String(255) TRUE Bank Code of the Beneficiary account, see Disbursement Bank Codes
account_number String(255) TRUE Beneficiary account number

Response Parameters

Parameter Type Description
status Object Status of inquiry {code: <status_code>, message: <status_message>}
bank_code String Bank Code of the Beneficiary account, see Disbursement Bank Codes
account_number String Account Number of the Beneficiary Account
account_name String Account Name of the Beneficiary Account
id String Unique ID of the inquiry. ID will be provided only for 000 or 209 status. Otherwise, the ID will be null.
invoice_id String ID of the invoice related to the inquiry result.
timestamp Timestamp UTC Timestamp api hit (Format: yyyy-MM-ddTHH:mm:ss)

Get Account Inquiry Invoices

curl -X \
GET https://partner.oyindonesia.com/api/account-inquiry/invoices \
-H 'content-type: application/json' \
-H 'accept: application/json' \
-H 'x-oy-username:myuser' \ 
-H 'x-api-key:987654'

The above command returns JSON structured similar like this:

{
    "total": 3,
    "status": {
        "code": "000",
        "message": "Success"
    },
    "timestamp": "2020-12-03T17:01:17",
    "data": [
        {
            "invoice_id": "e972bfcb-fcc4-4732-8887-91a589a0b54a",
            "tx_date": "2020-12-03",
            "amount": 2000.0000,
            "total_inquiry": 2,
            "paid_at": null,
            "invoice_status": "INITIATED",
            "due_at": "2020-12-04T16:59:59"
        }, {
            "invoice_id": "53f48b8a-1f53-4f56-aa91-7b32414a7513",
            "tx_date": "2020-12-02",
            "amount": 10000.0000,
            "total_inquiry": 10,
            "paid_at": null,
            "invoice_status": "UNPAID",
            "due_at": "2020-12-03T16:59:59"
        }, {
            "invoice_id": "53f48b8a-1f53-4f56-aa91-7b32414a7513",
            "tx_date": "2020-12-01",
            "amount": 10000.0000,
            "total_inquiry": 10,
            "paid_at": "2020-12-02T08:00:00",
            "invoice_status": "PAID",
            "due_at": "2020-12-02T16:59:59"
        }
    ]
}

Use this API to get inquiry invoices.

HTTPS Request

[Production] GET https://partner.oyindonesia.com/api/account-inquiry/invoices?offset=<offset>&limit=<limit>&status=<status>
[Staging] GET https://api-stg.oyindonesia.com/api/account-inquiry/invoices?offset=<offset>&limit=<limit>&status=<status>

Request Parameters

Parameter Type Required Default Description
offset Integer FALSE 0 start offset, default is 0, if empty will used default value
limit Integer FALSE 10 max item to fetch, default is 10, if empty will used default value
status String FALSE invoice status to fetch. If empty will fetch invoice regardless of the status

Response Parameters

Parameter Type Description
total Integer Total number of invoices per username
status Object Status of inquiry {code: <status_code>, message: <status_message>}
timestamp Timestamp UTC Timestamp api hit (Format: yyyy-MM-ddTHH:mm:ss)
data Array of objects List of objects {"invoice_id": <invoice_id>, "tx_date": <tx_date>, "amount": <amount>,"total_inquiry": <total_inquiry>, "paid_at": <paid-at>,"invoice_status": <invoice-status>,"due_at": <due-date>}
- invoice_id invoice ID
- tx_date the UTC+7 date of inquiry transaction from 00:00 UTC+7 until 23:59 UTC+7
- amount amount of the invoice
- total_inquiry the number of inquiries
- paid_at UTC invoice payment timestamp
- invoice_status status of the invoice: INITIATED, UNPAID, or PAID
- due_at UTC due timestamp for the invoice

Get Account Inquiry Invoice by ID

curl -X \
GET https://partner.oyindonesia.com/api/account-inquiry/invoices/e972bfcb-fcc4-4732-8887-91a589a0b54a \
-H 'content-type: application/json' \
-H 'accept: application/json' \
-H 'x-oy-username:myuser' \
-H 'x-api-key:987654'

The above command returns JSON structured similar like this:

{
    "status": {
        "code": "000",
        "message": "Success"
    },
    "invoice_id": "e972bfcb-fcc4-4732-8887-91a589a0b54a",
    "tx_date": "2020-12-03",
    "amount": 2000.0000,
    "total_inquiry": 2,
    "paid_at": null,
    "invoice_status": "INITIATED",
    "due_at": "2020-12-04T16:59:59",
    "timestamp": "2020-12-03T17:01:17"
}

Use this API to get inquiry invoice by ID.

HTTPS Request

[Production] GET https://partner.oyindonesia.com/api/account-inquiry/invoices/<id>
[Staging] GET https://api-stg.oyindonesia.com/api/account-inquiry/invoices/<id>

Request Parameters

Parameter Type Required Default Description
id String TRUE Invoice ID

Response Parameters

Parameter Type Description
status Object Status of inquiry {code: <status_code>, message: <status_message>}
invoice_id String invoice ID
tx_date String the UTC+7 date of inquiry transaction from 00:00 UTC+7 until 23:59 UTC+7
amount String amount of the invoice
total_inquiry Integer the number of inquiries
paid_at String UTC invoice payment timestamp
invoice_status String status of the invoice: INITIATED, UNPAID, or PAID
due_at String UTC due timestamp for the invoice

Pay Account Inquiry Invoice

curl -X \
GET https://partner.oyindonesia.com/api/account-inquiry/invoices/pay \
-H 'content-type: application/json' \
-H 'accept: application/json' \
-H 'x-oy-username:myuser' \
-H 'x-api-key:987654' \
-d '{
    "invoice_id": "53f48b8a-1f53-4f56-aa91-7b32414a7513"
}'

The above command returns JSON structured similar like this:

{
    "status": {
        "code": "000",
        "message": "Success"
    },
    "invoice_id": "53f48b8a-1f53-4f56-aa91-7b32414a7513",
    "tx_date": "2020-12-02",
    "amount": 10000.0000,
    "total_inquiry": 10,
    "paid_at": "2020-12-03T01:01:18",
    "invoice_status": "PAID",
    "due_at": "2020-12-03T17:01:00",
    "timestamp": "2020-12-03T01:01:17"
}

Use this API to pay inquiry invoice.

HTTPS Request

[Production] POST https://partner.oyindonesia.com/api/account-inquiry/invoices/pay
[Staging] POST https://api-stg.oyindonesia.com/api/account-inquiry/invoices/pay

Request Parameters

Parameter Type Required Default Description
invoice_id String TRUE Invoice ID

Response Parameters

Parameter Type Description
status Object Status of inquiry {code: <status_code>, message: <status_message>}
invoice_id String invoice ID
tx_date String the UTC+7 date of inquiry transaction from 00:00 UTC+7 until 23:59 UTC+7
amount String amount of the invoice
total_inquiry Integer the number of inquiries
paid_at String UTC invoice payment timestamp
invoice_status String status of the invoice: INITIATED, UNPAID, or PAID
due_at String UTC due timestamp for the invoice

Account Inquiry Response Codes

These are the list of possible status codes for account inquiry:

Status Meaning
000 Inquiry is success
201 Request is Rejected (User ID is not Found)
202 Request is Rejected (User ID/product is not active)
204 Request is Rejected (Invoice ID is not found)
205 Request is Rejected (Beneficiary Bank Code is Not Supported)
206 Failed doing payment (Balance is not enough)
207 Request is Rejected (Request IP Address is not Registered)
208 Request is Rejected (API Key is not Valid)
209 Request is Rejected (Bank Account is not found)
232 Request is Rejected (User has unpaid invoices)
300 Failed doing payment (invoice is not on UNPAID status)
429 Request Rejected (Too Many Request to specific endpoint)
990 Request is Rejected (Request Parameter is not Valid)
999 Internal server error

Fund Disbursement

Disbursement APIs allow you to send fund to any bank accounts in Indonesia easily and real-time.

Create Disbursement

curl -X \
POST https://partner.oyindonesia.com/api/remit \
-H 'content-type: application/json' \
-H 'accept: application/json' \
-H 'x-oy-username:myuser' \
-H 'x-api-key:987654' \
-d '{
  "recipient_bank": "014", 
  "recipient_account": "1239812390", 
  "amount":125000, 
  "note":"Split lunch bill", 
  "partner_trx_id":"1234-asdf",
  "email" :"napoleon@email.com test@email.com",
  "additional_data": {
      "partner_merchant_id": "merchant_abcd123"
  }
}'
var headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json',
  'x-oy-username': '{{username}}',
  'x-api-key': '{{api-key}}'
};
var request = http.Request('POST', Uri.parse('{{base_url}}/api/remit'));
request.body = json.encode({
  "recipient_bank": "008",
  "recipient_account": "0201245681",
  "amount": 15000,
  "note": "Test API Disburse",
  "partner_trx_id": "OYON0000064",
  "email": "business.support@oyindonesia.com",
  "additional_data": {
      "partner_merchant_id": "merchant_abcd123"
  }
});
request.headers.addAll(headers);

http.StreamedResponse response = await request.send();

if (response.statusCode == 200) {
  print(await response.stream.bytesToString());
}
else {
  print(response.reasonPhrase);
}
package main

import (
  "fmt"
  "strings"
  "net/http"
  "io/ioutil"
)

func main() {

  url := "%7B%7Bbase_url%7D%7D/api/remit"
  method := "POST"

  payload := strings.NewReader(`{
    "recipient_bank": "008",
    "recipient_account": "0201245681",
    "amount": 15000,
    "note": "Test API Disburse",
    "partner_trx_id": "OYON0000064",
    "email": "business.support@oyindonesia.com",
  "additional_data": {
      "partner_merchant_id": "merchant_abcd123"
  }
}`)

  client := &http.Client {
  }
  req, err := http.NewRequest(method, url, payload)

  if err != nil {
    fmt.Println(err)
    return
  }
  req.Header.Add("Content-Type", "application/json")
  req.Header.Add("Accept", "application/json")
  req.Header.Add("x-oy-username", "{{username}}")
  req.Header.Add("x-api-key", "{{api-key}}")

  res, err := client.Do(req)
  if err != nil {
    fmt.Println(err)
    return
  }
  defer res.Body.Close()

  body, err := ioutil.ReadAll(res.Body)
  if err != nil {
    fmt.Println(err)
    return
  }
  fmt.Println(string(body))
}
OkHttpClient client = new OkHttpClient().newBuilder()
  .build();
MediaType mediaType = MediaType.parse("application/json");
RequestBody body = RequestBody.create(mediaType, "{\n\t\"recipient_bank\": \"008\",\n\t\"recipient_account\": \"0201245681\",\n\t\"amount\": 15000,\n\t\"note\": \"Test API Disburse\",\n\t\"partner_trx_id\": \"OYON0000064\",\n\t\"email\": \"business.support@oyindonesia.com\",\n  \"additional_data\": {\n      \"partner_merchant_id\": \"merchant_abcd123\"\n  }\n}");
Request request = new Request.Builder()
  .url("{{base_url}}/api/remit")
  .method("POST", body)
  .addHeader("Content-Type", "application/json")
  .addHeader("Accept", "application/json")
  .addHeader("x-oy-username", "{{username}}")
  .addHeader("x-api-key", "{{api-key}}")
  .build();
Response response = client.newCall(request).execute();
var data = JSON.stringify({
  "recipient_bank": "008",
  "recipient_account": "0201245681",
  "amount": 15000,
  "note": "Test API Disburse",
  "partner_trx_id": "OYON0000064",
  "email": "business.support@oyindonesia.com",
  "additional_data": {
      "partner_merchant_id": "merchant_abcd123"
  }
});

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function() {
  if(this.readyState === 4) {
    console.log(this.responseText);
  }
});

xhr.open("POST", "%7B%7Bbase_url%7D%7D/api/remit");
xhr.setRequestHeader("Content-Type", "application/json");
xhr.setRequestHeader("Accept", "application/json");
xhr.setRequestHeader("x-oy-username", "{{username}}");
xhr.setRequestHeader("x-api-key", "{{api-key}}");

xhr.send(data);
<?php
require_once 'HTTP/Request2.php';
$request = new HTTP_Request2();
$request->setUrl('{{base_url}}/api/remit');
$request->setMethod(HTTP_Request2::METHOD_POST);
$request->setConfig(array(
  'follow_redirects' => TRUE
));
$request->setHeader(array(
  'Content-Type' => 'application/json',
  'Accept' => 'application/json',
  'x-oy-username' => '{{username}}',
  'x-api-key' => '{{api-key}}'
));
$request->setBody('{\n\t\"recipient_bank\": \"008\",\n\t\"recipient_account\": \"0201245681\",\n\t\"amount\": 15000,\n\t\"note\": \"Test API Disburse\",\n\t\"partner_trx_id\": \"OYON0000064\",\n\t\"email\": \"business.support@oyindonesia.com\",\n  \"additional_data\": {\n      \"partner_merchant_id\": \"merchant_abcd123\"\n  }\n}');
try {
  $response = $request->send();
  if ($response->getStatus() == 200) {
    echo $response->getBody();
  }
  else {
    echo 'Unexpected HTTP status: ' . $response->getStatus() . ' ' .
    $response->getReasonPhrase();
  }
}
catch(HTTP_Request2_Exception $e) {
  echo 'Error: ' . $e->getMessage();
}
import http.client
import json

conn = http.client.HTTPSConnection("{{base_url}}")
payload = json.dumps({
  "recipient_bank": "008",
  "recipient_account": "0201245681",
  "amount": 15000,
  "note": "Test API Disburse",
  "partner_trx_id": "OYON0000064",
  "email": "business.support@oyindonesia.com",
  "additional_data": {
      "partner_merchant_id": "merchant_abcd123"
  }
})
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json',
  'x-oy-username': '{{username}}',
  'x-api-key': '{{api-key}}'
}
conn.request("POST", "/api/remit", payload, headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))

Response for valid request (transaction will processed in the OY! system):

{
  "status": {
    "code": "101",
    "message": "Request is Processed"
  },
  "amount": 10000,
  "recipient_bank": "014",
  "recipient_account": "12341234",
  "trx_id": "d23ed68a-2a31-43a8-ac6f-15c0b45565c9",
  "partner_trx_id": "TRX-20231211-007",
  "timestamp": "11-12-2023 05:06:16"
}

Response for invalid request (transaction will rejected & not processed in the OY! system):

{
  "status": {
    "code": "264",
    "message": "The suggested routing from the client is not valid"
  },
  "amount": 10000,
  "recipient_bank": "014",
  "recipient_account": "12341234",
  "trx_id": "",
  "partner_trx_id": "TRX-20231211-007",
  "timestamp": "11-12-2023 05:06:16"
}

Use this API to start disbursing money to a specific beneficiary account.

HTTPS Request

[Production] POST https://partner.oyindonesia.com/api/remit
[Staging] POST https://api-stg.oyindonesia.com/api/remit

Request Parameters

Parameter Type Required Description
recipient_bank String(255) TRUE Please refer to the Disbursement Bank Codes to find the bank code for the recipient's bank account.
recipient_account String(255) TRUE Recipient bank account number, numeric only.
amount BigInteger TRUE Amount of disbursement, the minimum amount for bank is Rp10.000 and e-wallet is Rp100.
note String(255) FALSE The transaction's message may or may not be reflected in the recipient's bank account statement, based on the bank's capabilities. Using alphanumeric characters and some common symbols (e.g. -, *, . )
partner_trx_id String(255) TRUE Unique disbursement ID for a specific request, generated by partner.
email String(255) FALSE Multiple emails allowed, max. 5, separated by space. E.g. john.doe@example.com budi@example.com stark@example.com
child_balance String(255) FALSE If the Multi Account Management configuration is active, the disbursement will use the balance of child (sub-entity) account. Otherwise, the partner's own balance will be used by default.
additonal_data Object FALSE Object that includes the additional parameter for partner’s needs. This object contain partner_merchant_id String(64) (Unique ID for each of partner’s merchant)

Response Parameters

Parameter Type Description
status Object Status of Disbursement in Object {code: <status_code>, message: <status_message>}
amount BigInteger Amount to disburse.
recipient_bank String(255) Bank or Ewallet code of the recipient’s account, please refer to Disbursement Bank Codes
recipient_account String(255) Recipient bank account number.
trx_id String(36) Unique disbursement ID from OY!, partners can use this ID for reconciliation.
partner_trx_id String(255) Unique disbursement ID which partner put on the request.
timestamp String(19) Creation time of disbursement transaction in OY! system, using the format "dd-mm-yyyy hh:mm:ss" in UTC time.

Response Code: API Create Disbursement

Below is the list of response codes that show the request status for API Create Disbursement:

Response Code State State Details Description
101 Non-Final Transaction In Progress Transaction is processed.
201 Final Transaction Not Created Request is Rejected (User ID is not Found)
202 Final Transaction Not Created Request is Rejected (User ID is not Active)
203 Final Transaction Not Created Request is Rejected (Duplicate Partner Tx ID)
205 Final Transaction Not Created Request is Rejected (Beneficiary Bank Code is Not Supported)
207 Final Transaction Not Created Request is Rejected (Request IP Address is not Registered)
208 Final Transaction Not Created Request is Rejected (API Key is not Valid)
209 Final Transaction Not Created Request is Rejected (Bank Account is not found)
210 Final Transaction Not Created Request is Rejected (Amount is not valid)
257 Final Transaction Not Created Request is Rejected (Disbursement with the same Partner Tx ID is still in process)
264 Final Transaction Not Created Request is rejected (The suggested routing from the partner is not valid)
300 Final Transaction Failed Transaction is failed.
301 Non-Final Transaction Pending Pending (when there is an unclear answer from bank network)
429 Final Transaction Not Created Request Rejected (Too Many Request to specific endpoint)
504 Non-Final Transaction Unknown Disbursement Submission Timed Out. Note: the transaction status is uncertain, it may or may not have been successfully submitted, so we suggest resubmitting using the same partner_trx_id. Please check your dashboard or contact our business representative.
990 Final Transaction Not Created Request is Rejected (Invalid Format)
999 Non-Final Transaction Unknown Internal Server Error. Please check your dashboard or contact our business representative

Column State Details: Response Code API Create Disbursement

Below is the list of Explanation for column state details that show on response code API Create Disbursement:

State Details Description
Transaction Failed Transaction is failed to disburse.
Transaction In Progress Transaction is still in progress.
Transaction Pending Transaction has an unclear status from the banks.
Transaction Unknown Transaction status is uncertain, please wait the callback or hit check status API to make sure the status of transaction. Please check to your dashboard or contact our business representative.
Transaction Not Created Transaction is not created in the OY! system due to not valid disbursement request.

Disbursement Callback

Response for successful callback:

{
  "status":{
    "code":"000",
    "message":"Success"
  },
  "amount":10000,
  "recipient_name":"John Doe",
  "recipient_bank":"014",
  "recipient_account":"12341234",
  "trx_id": "d23ed68a-2a31-43a8-ac6f-15c0b45565c9",
  "partner_trx_id": "TRX-20231211-007",
  "timestamp": "11-12-2023 05:07:20",
  "created_date": "11-12-2023 05:06:20",
  "last_updated_date": "11-12-2023 05:07:00"
}

Response for failed callback:

{
  "status":{
    "code":"300",
    "message":"Failed"
  },
  "tx_status_description":"Your transaction amount exceeds maximum routing limit. Please adjust the routing and try again",
  "amount":10000,
  "recipient_name":"John Doe",
  "recipient_bank":"014",
  "recipient_account":"12341234",
  "trx_id": "d23ed68a-2a31-43a8-ac6f-15c0b45565c9",
  "partner_trx_id": "TRX-20231211-007",
  "timestamp": "11-12-2023 05:07:20",
  "created_date": "11-12-2023 05:06:20",
  "last_updated_date": "11-12-2023 05:07:00"
}

Once a disbursement request is finished, our system will make a callback status of that disbursement request to your system.

You can set your own callback URL in OY Business dashboard setting. You can Open “Settings” tab, choose “Developer Option”, Choose “Callback Configuration”, and Fill your callback URL in the API Disbursement field.

We also have a resend callback feature which you can read about here.

Callback Parameters

Parameter Type Description
status Object Status of Disbursement in Object {code: <status_code>, message: <status_message>}
tx_status_description String(255) Additional information regarding status code, especially for Failed transactions, Force Credit transactions, and Queued transactions.

For example: “Account is blocked. Please create a new transaction with a different recipient account number.” Note: This parameter will not appear in the response body for transactions with a Success status. amount | BigInteger | Amount to disburse. recipient_name | String(255) | Account holder name of recipient bank account. recipient_bank | String(255) | Bank or Ewallet code of the recipient’s account, please refer to Disbursement Bank Codes recipient_account | String(255) | Recipient bank account number. trx_id | String(36) | Unique disbursement ID from OY!, partners can use this ID for reconciliation. partner_trx_id | String(255) | Unique disbursement ID which partner put on the request. timestamp | String(19) | Time of API get disbursement status called by partner ("dd-MM-yyyy HH:mm:ss in UTC time zone"). created_date | String(19) | Execution time of disbursement in OY! system ("dd-MM-yyyy HH:mm:ss in UTC time zone"). last_updated_date | String(19) | Latest status change of a disbursement. Example from 'Pending' to 'Success' ("dd-MM-yyyy HH:mm:ss in UTC Time zone")

Transaction Status: API Disbursement

Below is the list of response codes that show the transaction status for Disbursement Callback:

Response Code State Description
000 Final Transaction has been completed (success)
300 Final Transaction is FAILED
301 Non-Final Pending (When there is an unclear answer from Banks Network)

Get Disbursement Status

curl -X \
POST https://partner.oyindonesia.com/api/remit-status \
-H 'content-type: application/json' \
-H 'accept: application/json' \
-H 'x-oy-username:myuser' \
-H 'x-api-key:987654' \
-d '{
  "partner_trx_id": "1234-asde", 
  "send_callback": "true"
}'
var headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json',
  'x-oy-username': '{{username}}',
  'x-api-key': '{{api-key}}'
};
var request = http.Request('POST', Uri.parse('{{base_url}}/api/remit-status'));
request.body = json.encode({
  "partner_trx_id": "OYON0000056"
});
request.headers.addAll(headers);

http.StreamedResponse response = await request.send();

if (response.statusCode == 200) {
  print(await response.stream.bytesToString());
}
else {
  print(response.reasonPhrase);
}
package main

import (
  "fmt"
  "strings"
  "net/http"
  "io/ioutil"
)

func main() {

  url := "%7B%7Bbase_url%7D%7D/api/remit-status"
  method := "POST"

  payload := strings.NewReader(`{
    "partner_trx_id": "OYON0000056"
}`)

  client := &http.Client {
  }
  req, err := http.NewRequest(method, url, payload)

  if err != nil {
    fmt.Println(err)
    return
  }
  req.Header.Add("Content-Type", "application/json")
  req.Header.Add("Accept", "application/json")
  req.Header.Add("x-oy-username", "{{username}}")
  req.Header.Add("x-api-key", "{{api-key}}")

  res, err := client.Do(req)
  if err != nil {
    fmt.Println(err)
    return
  }
  defer res.Body.Close()

  body, err := ioutil.ReadAll(res.Body)
  if err != nil {
    fmt.Println(err)
    return
  }
  fmt.Println(string(body))
}
OkHttpClient client = new OkHttpClient().newBuilder()
  .build();
MediaType mediaType = MediaType.parse("application/json");
RequestBody body = RequestBody.create(mediaType, "{\n\t\"partner_trx_id\": \"OYON0000056\"\n}");
Request request = new Request.Builder()
  .url("{{base_url}}/api/remit-status")
  .method("POST", body)
  .addHeader("Content-Type", "application/json")
  .addHeader("Accept", "application/json")
  .addHeader("x-oy-username", "{{username}}")
  .addHeader("x-api-key", "{{api-key}}")
  .build();
Response response = client.newCall(request).execute();
var data = JSON.stringify({
  "partner_trx_id": "OYON0000056"
});

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function() {
  if(this.readyState === 4) {
    console.log(this.responseText);
  }
});

xhr.open("POST", "%7B%7Bbase_url%7D%7D/api/remit-status");
xhr.setRequestHeader("Content-Type", "application/json");
xhr.setRequestHeader("Accept", "application/json");
xhr.setRequestHeader("x-oy-username", "{{username}}");
xhr.setRequestHeader("x-api-key", "{{api-key}}");

xhr.send(data);
<?php
require_once 'HTTP/Request2.php';
$request = new HTTP_Request2();
$request->setUrl('{{base_url}}/api/remit-status');
$request->setMethod(HTTP_Request2::METHOD_POST);
$request->setConfig(array(
  'follow_redirects' => TRUE
));
$request->setHeader(array(
  'Content-Type' => 'application/json',
  'Accept' => 'application/json',
  'x-oy-username' => '{{username}}',
  'x-api-key' => '{{api-key}}'
));
$request->setBody('{\n  "partner_trx_id": "OYON0000056"\n}');
try {
  $response = $request->send();
  if ($response->getStatus() == 200) {
    echo $response->getBody();
  }
  else {
    echo 'Unexpected HTTP status: ' . $response->getStatus() . ' ' .
    $response->getReasonPhrase();
  }
}
catch(HTTP_Request2_Exception $e) {
  echo 'Error: ' . $e->getMessage();
}
import http.client
import json

conn = http.client.HTTPSConnection("{{base_url}}")
payload = json.dumps({
  "partner_trx_id": "OYON0000056"
})
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json',
  'x-oy-username': '{{username}}',
  'x-api-key': '{{api-key}}'
}
conn.request("POST", "/api/remit-status", payload, headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))

Response for success transaction status:

{
  "status":{
    "code":"000",
    "message":"Success"
  },
  "tx_status_description":"",
  "amount":10000,
  "recipient_name":"John Doe",
  "recipient_bank":"014",
  "recipient_account":"12341234",
  "trx_id": "d23ed68a-2a31-43a8-ac6f-15c0b45565c9",
  "partner_trx_id": "TRX-20231211-007",
  "timestamp": "11-12-2023 05:07:20",
  "created_date": "11-12-2023 05:06:20",
  "last_updated_date": "11-12-2023 05:07:00"
}

Response for failed transaction status:

{
  "status":{
    "code":"300",
    "message":"Failed"
  },
  "tx_status_description":"Your transaction amount exceeds maximum routing limit. Please adjust the routing and try again",
  "amount":10000,
  "recipient_name":"John Doe",
  "recipient_bank":"014",
  "recipient_account":"12341234",
  "trx_id": "d23ed68a-2a31-43a8-ac6f-15c0b45565c9",
  "partner_trx_id": "TRX-20231211-007",
  "timestamp": "11-12-2023 05:07:20",
  "created_date": "11-12-2023 05:06:20",
  "last_updated_date": "11-12-2023 05:07:00"
}

To get status of a disbursement request, you can call this API. You may need to call this API few times until getting a final status (success/failed). We suggest to check the status after the remit API timed out or 60 seconds after the disbursement requested

This API offers an option to send you a callback status of the disbursement request to a specific URL. You can set your own callback URL in OY Business dashboard setting. You can Open “Settings” tab, choose “Developer Option”, Choose “Callback Configuration”, and Fill your callback URL in the API Disbursement field.

HTTPS Request

[Production] POST https://partner.oyindonesia.com/api/remit-status
[Staging] POST https://api-stg.oyindonesia.com/api/remit-status

Request Parameters

Parameter Type Required Description
partner_trx_id String(255) TRUE Unique Disbursement ID for a specific request, generated by partner
send_callback Boolean FALSE A flag to indiciate if the status of the disbursement request need to be re-sent as a callback or not

Response Parameters

Parameter Type Description
status Object Status of Disbursement in Object {code: <status_code>, message: <status_message>}
tx_status_description String(255) Additional information of status code, especially for failed status. E.g. Account is blocked. Please create a new transaction with a different recipient account number.
amount BigInteger Amount to disburse.
recipient_name String(255) Account holder name of recipient bank account.
recipient_bank String(255) Bank or Ewallet code of the recipient’s account, please refer to Disbursement Bank Codes
recipient_account String(255) Recipient bank account number.
trx_id String(36) Unique disbursement ID from OY!, partners can use this ID for reconciliation.
partner_trx_id String(255) Unique disbursement ID which partner put on the request.
timestamp String(19) Time of API get disbursement status called by partner ("dd-MM-yyyy HH:mm:ss in UTC time zone").
created_date String(19) Execution time of disbursement in OY! system ("dd-MM-yyyy HH:mm:ss in UTC time zone").
last_updated_date String(19) Latest status change of a disbursement. Example from 'Pending' to 'Success' ("dd-MM-yyyy HH:mm:ss in UTC Time zone")

Response Code: API Get Disbursement Status

Below is the list of response codes that show the request status for API Get Disbursement Status:

Response Code State State Details Description
000 Final Transaction Success Transaction has been completed.
101 Non-Final Transaction In Progress Transaction is processed.
102 Non-Final Transaction In Progress Transaction is in progress.
201 Non-Final Transaction Unknown Request for Get Disbursement Status is rejected (user ID is not found)
202 Non-Final Transaction Unknown Request for Get Disbursement Status is rejected (user ID is not active)
204 Final Transaction Not Created Transaction do not exist (Partner Tx ID is Not Found)
206 Final Transaction Failed Transaction is failed (partner deposit balance is not enough)
207 Non-Final Transaction Unknown Request for Get Disbursement Status is rejected (request IP Address is not registered)
208 Non-Final Transaction Unknown Request for Get Disbursement Status is rejected (API key is not valid)
225 Final Transaction Failed Transaction is failed (Transaction amount exceeds the maximum limit)
300 Final Transaction Failed Transaction is failed.
301 Non-Final Transaction Pending Pending (when there is an unclear answer from bank network)
429 Non-Final Transaction Unknown Request for Get Disbursement Status is rejected (too many requests to specific endpoint)
990 Final Transaction Unknown Request for Get Disbursement Status is rejected (invalid format)
999 Non-Final Transaction Unknown Internal Server Error

Column State Details: Response Code API Get Disbursement Status

Below is the list of Explanation for column state details that show on response code API Get Disbursement Status:

State Details Description
Transaction Success Transaction has been completed & successfully received on the recipient account
Transaction Failed Transaction is failed to disburse.
Transaction In Progress Transaction is still in progress.
Transaction Pending Transaction has an unclear status from the banks.
Transaction Unknown Transaction status is uncertain, please wait the callback or hit check status API to make sure the status of transaction. Please check to your dashboard or contact our business representative.
Transaction Not Created Transaction is not created in the OY! system due to not valid disbursement request.

Mock Data in Demo Environment

Request body mock data in demo environment:

{
    "recipient_bank": "014",
    "recipient_account": "2100000",
    "amount": 10000,
    "note": "Test Expose Route",
    "partner_trx_id": "TRX-20231211-007",
    "email": "yono@oyindonesia.com"
}

Response body mock data in demo environment:

{
    "status": {
        "code": "210",
        "message": "Request is Rejected (Amount is not valid)"
    },
    "amount": 10000,
    "recipient_bank": "014",
    "recipient_account": "2100000",
    "trx_id": "",
    "partner_trx_id": "TRX-20231211-007",
    "timestamp": "11-12-2023 05:06:16"
}

You can replicate final error response codes based on the Response Code by filling in the recipient_account value using this format: <desired response code>0000. You can input 4 to 15 characters consisting only of the digit 0 at the end of the response code. Any value that doesn’t follow this format as default will be processed as a Successful transaction.

For example, if you want to get the "Request is Rejected (Amount is not valid)” error, you can trigger the response code “210” by formatting the recipient_account as "2100000".

Test Scenario

To test out all scenarios of API Disbursement and ensure the flows in your integration are handled correctly, please visit this link.

Disbursement Failed Reasons

If you receive a failed disbursement in the callback or check status response, this means that we tried processing the disbursement and failed.

We return failed reasons description in our callback & check status response in the tx_status_description parameter. Partners need to understand each failed reason to decide the appropriate action to take. Below is a list of the failed reasons that partners may receive:

Explanation: Disbursement Failed Reasons

Failed Reason Explanation Should I retry?
Account is blocked. Please create a new transaction with a different recipient account number. Recipient account number is blocked by the bank & disbursement cannot proceed to this account. If you retry with the same request, most likely it will return the same response. Please confirm to the recipient that the account number details are correct and can receive funds. After that, you can revise the request to the correct account number before trying again.
Account has exceeded the maximum amount for receiving money. Please contact the account owner. Recipient account number has reached the balance limit amount that is set by the corresponding bank/e-wallet. If you retry with the same request, most likely it will return the same response. Please confirm to the recipient that the account number details can receive funds for that amount. After that, you can revise the request to the correct account number and amount before trying again.
Account is no longer active. Please create a new transaction with a different recipient account number. Recipient account number is no longer active in the bank & disbursement cannot proceed to this account. If you retry with the same request, most likely it will return the same response. Please confirm to the recipient that the account number details are correct and can receive funds. After that, you can revise the request to the correct account number before trying again.
Account not found. Please create a new transaction with a different recipient account number. Recipient account number is not found for the bank selected & disbursement cannot proceed to this account. If you retry with the same request, most likely it will return the same response. Please confirm to the recipient that the account number details and the selected bank are correct and can receive funds. After that, you can revise the request to the correct account number before trying again.
The bank/e-wallet provider system is under maintenance. Please try again in a moment. The bank/e-wallet is in downtime so there will be disturbances in the disbursement process. Please ensure the information of the bank maintenance schedule to our customer service. If there is any clear information about the maintenance schedule from the banks, you can retry the transaction after the maintenance schedule is over.
The bank/e-wallet system encounters an error while disbursing the money. Try again in a moment. The bank/e-wallet has an issue in their system to process the disbursement. There may be intermittent issues in the bank system that are unpredictable. You can retry the disbursement in the next few minutes. If you need any further information regarding the issue, you can contact our customer service.
System encounters an error while disbursing the money. Please try again in a moment. There is an issue in the process of the disbursement. There may be intermittent issues that are unpredictable. You can retry the disbursement in the next few minutes. If you need any further information regarding the issue, you can contact our customer service.
Your transaction exceeds the maximum limit amount. Please adjust the amount and try again. The transaction has an amount that exceeds the maximum limit that is already set in the OY! system. If you retry with the same request, it will return the same response. Please adjust the transaction amount according to the maximum limit that OY! gives to you. If you need any further information regarding the limit amount, you can contact our business representative.
Not enough balance to disburse the money, please top up your balance. Insufficient partner’s deposit balance to process the disbursement transaction. Please top up your deposit balance in the OY! dashboard. You can retry the disbursement transaction after ensuring that you have sufficient balance in your account.

Get Balance

curl -X \
GET https://partner.oyindonesia.com/api/balance \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'X-OY-Username: janedoe' \
-H 'X-Api-Key: 7654321'
var headers = {
  'x-oy-username': '{{username}}',
  'x-api-key': '{{api-key}}',
  'Content-Type': 'application/json',
  'Accept': 'application/json'
};
var request = http.Request('GET', Uri.parse('{{base_url}}/api/balance'));

request.headers.addAll(headers);

http.StreamedResponse response = await request.send();

if (response.statusCode == 200) {
  print(await response.stream.bytesToString());
}
else {
  print(response.reasonPhrase);
}
package main

import (
  "fmt"
  "net/http"
  "io/ioutil"
)

func main() {

  url := "%7B%7Bbase_url%7D%7D/api/balance"
  method := "GET"

  client := &http.Client {
  }
  req, err := http.NewRequest(method, url, nil)

  if err != nil {
    fmt.Println(err)
    return
  }
  req.Header.Add("x-oy-username", "{{username}}")
  req.Header.Add("x-api-key", "{{api-key}}")
  req.Header.Add("Content-Type", "application/json")
  req.Header.Add("Accept", "application/json")

  res, err := client.Do(req)
  if err != nil {
    fmt.Println(err)
    return
  }
  defer res.Body.Close()

  body, err := ioutil.ReadAll(res.Body)
  if err != nil {
    fmt.Println(err)
    return
  }
  fmt.Println(string(body))
}
OkHttpClient client = new OkHttpClient().newBuilder()
  .build();
Request request = new Request.Builder()
  .url("{{base_url}}/api/balance")
  .method("GET", null)
  .addHeader("x-oy-username", "{{username}}")
  .addHeader("x-api-key", "{{api-key}}")
  .addHeader("Content-Type", "application/json")
  .addHeader("Accept", "application/json")
  .build();
Response response = client.newCall(request).execute();

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function() {
  if(this.readyState === 4) {
    console.log(this.responseText);
  }
});

xhr.open("GET", "%7B%7Bbase_url%7D%7D/api/balance");
xhr.setRequestHeader("x-oy-username", "{{username}}");
xhr.setRequestHeader("x-api-key", "{{api-key}}");
xhr.setRequestHeader("Content-Type", "application/json");
xhr.setRequestHeader("Accept", "application/json");

xhr.send();
<?php
require_once 'HTTP/Request2.php';
$request = new HTTP_Request2();
$request->setUrl('{{base_url}}/api/balance');
$request->setMethod(HTTP_Request2::METHOD_GET);
$request->setConfig(array(
  'follow_redirects' => TRUE
));
$request->setHeader(array(
  'x-oy-username' => '{{username}}',
  'x-api-key' => '{{api-key}}',
  'Content-Type' => 'application/json',
  'Accept' => 'application/json'
));
try {
  $response = $request->send();
  if ($response->getStatus() == 200) {
    echo $response->getBody();
  }
  else {
    echo 'Unexpected HTTP status: ' . $response->getStatus() . ' ' .
    $response->getReasonPhrase();
  }
}
catch(HTTP_Request2_Exception $e) {
  echo 'Error: ' . $e->getMessage();
}
import http.client
import json

conn = http.client.HTTPSConnection("{{base_url}}")
payload = ''
headers = {
  'x-oy-username': '{{username}}',
  'x-api-key': '{{api-key}}',
  'Content-Type': 'application/json',
  'Accept': 'application/json'
}
conn.request("GET", "/api/balance", payload, headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))

The above command returns JSON structured similar like this:

{
  "status":{
    "code":"000",
    "message":"Success"
  },
  "balance":100000000.0000,
  "overdraftBalance":500000.0000,
  "overbookingBalance":200000.0000,
  "pendingBalance":2000000.0000,
  "availableBalance":98500000.0000,
  "timestamp":"10-12-2019 12:15:37"
}

Use this API to get partner balance.

HTTPS Request

[Production] GET https://partner.oyindonesia.com/api/balance
[Staging] GET https://api-stg.oyindonesia.com/api/balance

Response Parameters

Parameter Type Description
status Object Status of Disbursement in Object {code: <status_code>, message: <status_message>}
balance BigDecimal Remaining balance (Accept non fraction number)
overdraftBalance BigDecimal Remaining overdraft balance (Accept non fraction number)
overbookingBalance BigDecimal Remaining overbooking balance (Accept non fraction number)
pendingBalance BigDecimal The cumulative balance of your pending transactions.
availableBalance BigDecimal The total cumulative money of Balance + Available Overdraft - Pending Balance that you can use for disbursement.
timestamp String(19) Execution time of Disbursement in OY! system ("dd-MM-yyyy HH:mm:ss in UTC Time zone").

Request Status: API Get Balance

Below is the list of response codes that show the request status for API Get Balance:

Response Code Description Notes
000 Request get balance is success -
207 Request is Rejected (Request IP Address is not Registered) Request check balance rejected.
208 Request is Rejected (API Key is not Valid) Request check balance rejected.
999 Internal Server Error Request check balance rejected.
201 Request is Rejected (User ID is not Found) Request check balance rejected.
202 Request is Rejected (User ID is not Active) Request check balance rejected.
429 Request Rejected (Too Many Request to specific endpoint) Request check balance rejected.
900 Request is Rejected (Invalid Format) Request check balance rejected.

Disbursement Bank Codes

Supported Bank Codes to be used in the Disbursement Request:

Bank Codes Bank Name
002 BRI
008 Bank Mandiri
009 Bank Negara Indonesia
011 Bank Danamon
013 Bank Permata
014 BCA
016 BII Maybank
019 Bank Panin
022 CIMB Niaga
023 Bank UOB Indonesia
028 Bank OCBC NISP
031 Citibank
032 JPMorgan Chase Bank
036 Bank China Construction Bank Indonesia
037 Bank Artha Graha Internasional
042 MUFG Bank
046 Bank DBS Indonesia
050 Standard Chartered
054 Bank Capital Indonesia
061 ANZ Indonesia
067 Deutsche Bank AG
069 Bank OF China
076 Bank Bumi Arta
087 Bank HSBC Indonesia
088 Bank Antardaerah
089 Bank Rabobank
095 Bank Jtrust Indonesia
097 Bank Mayapada International
110 BJB
111 Bank DKI
112 Bank DIY
112S Bank DIY Syariah
113 Bank Jateng
114 Bank Jatim
114S Bank Jatim Syariah
115 Bank Jambi
115S Bank Jambi Syariah
116 Bank Aceh
117 Bank Sumut
117S Bank Sumut Syariah
118 Bank Nagari
118S Bank Nagari Syariah
119 Bank Riau
120 Bank Sumsel Babel
120S Bank Sumsel Babel Syariah
121 Bank Lampung
122 Bank Kalsel
122S Bank Kalsel Syariah
123 Bank Kalbar
123S Bank Kalbar Syariah
124 Bank Kaltim
124S Bank Kaltim Syariah
125 Bank Kalteng
126 Bank Sulselbar
126S Bank Sulselbar Syariah
127 Bank Sulut
128 Bank NTB
129 Bank Bali
130 Bank NTT
131 Bank Maluku
132 Bank Papua
133 Bank Bengkulu
134 Bank Sulteng
135 Bank Sultra
137 Bank Banten
145 Bank Nusantara Parahyangan
146 Bank Of India Indonesia
147 Bank Muamalat
151 Bank Mestika
152 Bank Shinhan
153 Bank Sinarmas
157 Bank Maspion Indonesia
161 Bank Ganesha
164 Bank ICBC Indonesia
167 Bank QNB Indonesia
200 BTN
200S BTN Syariah
212 Bank Woori Saudara
213 Bank BTPN
405 Bank Victoria Syariah
425 BJB Syariah
426 Bank Mega
441 Bank Bukopin
451 Bank Syariah Indonesia
472 Bank Jasa Jakarta
484 Bank KEB Hana
485 Bank MNC
490 Bank Neo Commerce
494 Bank Raya Indonesia
498 Bank SBI Indonesia
501 BCA Digital
503 Bank National Nobu
506 Bank Mega Syariah
513 Bank INA
517 Bank Panin Syariah
520 Bank Prima
521 Bank Syariah Bukopin
523 Bank Sahabat Sampoerna
526 Bank Oke Indonesia
535 Bank Seabank Indonesia
536 Bank BCA Syariah
542 Bank Jago
542S Bank Jago Syariah
547 Bank BTPN Syariah
548 Bank Multiarta Sentosa
553 Bank Hibank Indonesia
555 Bank Index
559 Bank CNB
562 Superbank
564 Bank Mandiri Taspen
566 Bank Victoria International
567 Allo Bank
600 ATMB LSB
688 BPR KS
724 Bank DKI Syariah
725 Bank Jateng Syariah
734 Bank Sinarmas Syariah
777 Finnet
867 Bank Eka
945 Bank IBK Indonesia
949 Bank CTBC Indonesia
950 Bank Commonwealth
987 ATMB Plus
dana DANA
gopay GoPay
linkaja LinkAja
ovo OVO
shopeepay Shopeepay

VA Aggregator

API VA aggregator allows you to create a unique Virtual Account (VA) number as a payment method for your customers.

VA Aggregator API Base URL

[Production Base URL]: https://partner.oyindonesia.com
[Staging Base URL]: https://api-stg.oyindonesia.com

Create VA

Use this API to create new VA number

curl -X \
POST https://partner.oyindonesia.com/api/generate-static-va
-H 'content-type: application/json' \
-H 'accept: application/json' \
-H 'x-oy-username: username' \
-H 'x-api-key: apikey' \
-d '{
    "partner_user_id":"51200021",
    "bank_code": "002",
    "amount": 0,
    "is_open": true,
    "is_single_use" : false,
    "is_lifetime": false,
    "expiration_time": 5,
    "username_display": "va name",
    "email": "email@mail.com",
    "trx_expiration_time": 5,
    "partner_trx_id": "TRX0001",
    "trx_counter" : 1
}'
var headers = {
  'Content-Type': 'application/json',
  'X-Oy-Username': '{{username}}',
  'X-Api-Key': '{{api-key}}'
};
var request = http.Request('POST', Uri.parse('{{base_url}}/api/generate-static-va'));
request.body = json.encode({
   "partner_user_id":"51200021",
   "bank_code": "002",
   "amount": 0,
   "is_open": true,
   "is_single_use" : false,
   "is_lifetime": false,
   "expiration_time": 5,
   "username_display": "va name",
   "email": "email@mail.com",
   "trx_expiration_time": 5,
   "partner_trx_id": "TRX0001",
   "trx_counter" : 1
});
request.headers.addAll(headers);

http.StreamedResponse response = await request.send();

if (response.statusCode == 200) {
  print(await response.stream.bytesToString());
}
else {
  print(response.reasonPhrase);
}
package main

import (
  "fmt"
  "strings"
  "net/http"
  "io/ioutil"
)

func main() {

  url := "%7B%7Bbase_url%7D%7D/api/generate-static-va"
  method := "POST"

  payload := strings.NewReader(`{
    "partner_user_id":"51200021",
  "bank_code": "002",
  "amount": 0,
  "is_open": true,
  "is_single_use" : false,
  "is_lifetime": false,
  "expiration_time": 5,
  "username_display": "va name",
  "email": "email@mail.com",
  "trx_expiration_time": 5,
  "partner_trx_id": "TRX0001",
  "trx_counter" : 1
}`)

  client := &http.Client {
  }
  req, err := http.NewRequest(method, url, payload)

  if err != nil {
    fmt.Println(err)
    return
  }
  req.Header.Add("Content-Type", "application/json")
  req.Header.Add("X-Oy-Username", "{{username}}")
  req.Header.Add("X-Api-Key", "{{api-key}}")

  res, err := client.Do(req)
  if err != nil {
    fmt.Println(err)
    return
  }
  defer res.Body.Close()

  body, err := ioutil.ReadAll(res.Body)
  if err != nil {
    fmt.Println(err)
    return
  }
  fmt.Println(string(body))
}
OkHttpClient client = new OkHttpClient().newBuilder()
  .build();
MediaType mediaType = MediaType.parse("application/json");
RequestBody body = RequestBody.create(mediaType, "{\n\"partner_user_id\":\"51200021\",\n\"bank_code\": \"002\",\n\"amount\": 0,\n\"is_open\": true,\n\"is_single_use\" : false,\n\"is_lifetime\": false,\n\"expiration_time\": 5,\n\"username_display\": \"va name\",\n\"email\": \"email@mail.com\",\n\"trx_expiration_time\": 5,\n\"partner_trx_id\": \"TRX0001\",\n\"trx_counter\" : 1\n}");
Request request = new Request.Builder()
  .url("{{base_url}}/api/generate-static-va")
  .method("POST", body)
  .addHeader("Content-Type", "application/json")
  .addHeader("X-Oy-Username", "{{username}}")
  .addHeader("X-Api-Key", "{{api-key}}")
  .build();
Response response = client.newCall(request).execute();
var data = JSON.stringify({
  "partner_user_id":"51200021",
  "bank_code": "002",
  "amount": 0,
  "is_open": true,
  "is_single_use" : false,
  "is_lifetime": false,
  "expiration_time": 5,
  "username_display": "va name",
  "email": "email@mail.com",
  "trx_expiration_time": 5,
  "partner_trx_id": "TRX0001",
  "trx_counter" : 1
});

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function() {
  if(this.readyState === 4) {
    console.log(this.responseText);
  }
});

xhr.open("POST", "%7B%7Bbase_url%7D%7D/api/generate-static-va");
xhr.setRequestHeader("Content-Type", "application/json");
xhr.setRequestHeader("X-Oy-Username", "{{username}}");
xhr.setRequestHeader("X-Api-Key", "{{api-key}}");

xhr.send(data);
<?php
require_once 'HTTP/Request2.php';
$request = new HTTP_Request2();
$request->setUrl('{{base_url}}/api/generate-static-va');
$request->setMethod(HTTP_Request2::METHOD_POST);
$request->setConfig(array(
  'follow_redirects' => TRUE
));
$request->setHeader(array(
  'Content-Type' => 'application/json',
  'X-Oy-Username' => '{{username}}',
  'X-Api-Key' => '{{api-key}}'
));
$request->setBody('"{\n\"partner_user_id\":\"51200021\",\n\"bank_code\": \"002\",\n\"amount\": 0,\n\"is_open\": true,\n\"is_single_use\" : false,\n\"is_lifetime\": false,\n\"expiration_time\": 5,\n\"username_display\": \"va name\",\n\"email\": \"email@mail.com\",\n\"trx_expiration_time\": 5,\n\"partner_trx_id\": \"TRX0001\",\n\"trx_counter\" : 1\n}"');
try {
  $response = $request->send();
  if ($response->getStatus() == 200) {
    echo $response->getBody();
  }
  else {
    echo 'Unexpected HTTP status: ' . $response->getStatus() . ' ' .
    $response->getReasonPhrase();
  }
}
catch(HTTP_Request2_Exception $e) {
  echo 'Error: ' . $e->getMessage();
}
import http.client
import json

conn = http.client.HTTPSConnection("{{base_url}}")
payload = json.dumps({
  "partner_user_id":"51200021",
  "bank_code": "002",
  "amount": 0,
  "is_open": true,
  "is_single_use" : false,
  "is_lifetime": false,
  "expiration_time": 5,
  "username_display": "va name",
  "email": "email@mail.com",
  "trx_expiration_time": 5,
  "partner_trx_id": "TRX0001",
  "trx_counter" : 1
})
headers = {
  'Content-Type': 'application/json',
  'X-Oy-Username': '{{username}}',
  'X-Api-Key': '{{api-key}}'
}
conn.request("POST", "/api/generate-static-va", payload, headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))

The above command returns JSON structured similar like this:

{
    "id": "12345b1-23be-45670-a123-5ca678f12b3e",
    "status": {
        "code": "000",
        "message": "Success"
    },
    "amount": 0,
    "va_number": "123456789182827272",
    "bank_code": "002",
    "is_open": true,
    "is_single_use": false,
    "expiration_time": 1582783668175,
    "va_status": "WAITING_PAYMENT",
    "username_display": "va name",
    "partner_user_id" : "51200021",
    "counter_incoming_payment": 0,
    "partner_trx_id": "TRX0001",
    "trx_expiration_time": 1582783668175,
    "trx_counter": 1
}

HTTPS Request

[Production] POST https://partner.oyindonesia.com/api/generate-static-va
[Staging] POST https://api-stg.oyindonesia.com/api/generate-static-va

Request Parameters

Parameter Type Required Default Description
partner_user_id String(255) TRUE - Partner unique ID for specific user
bank_code String(3) TRUE - Bank code which the VA number will be generated. Refer to VA Bank Code
amount BigDecimal FALSE 0 Amount your user must paid to complete the transaction, if is_open is false, amount is required.
is_open Boolean FALSE true If set true means VA number can accept any amount, field amount can be optional, if set false means VA number only accept the specified amount in the field amount. When you set is_open to false, you must specify amount field.
is_single_use Boolean FALSE false True means that this VA should be closed once there is a successful payment that is being made to this VA.
expiration_time Long FALSE - Expiration time of the VA in minutes, e.g If VA want to be expired after 5 minutes, you just have to set expiration_time to 5. If empty VA will be expired in 24 hour
is_lifetime Boolean FALSE FALSE If it is set to FALSE (default) then VA will expire based on the expiration time. Otherwise, it will remain active.
username_display String(255) FALSE username Customizable VA display name that will be seen by user, If empty willl be using partner username
email String(255) CONDITIONAL (Required by some banks) - Email of user, using email standard format. Required by Mandiri(008), Permata(013) and CIMB(022).
full_name String(255) CONDITIONAL (Required by some banks) - Fill with the name of end-user that will pay this transaction. Required by Mandiri(008), Permata(013) and CIMB(022).
trx_expiration_time Long FALSE - Transaction expiration time in minutes, e.g If Transaction want to be expired after 5 minutes, you just have to set expiration_time to 5. If empty transaction expiration time will be the same with va expiration time
partner_trx_id String(255) FALSE - Partner unique Transaction ID of a VA
trx_counter Int FALSE -1/1 Transaction counter to limit number of transaction that can be receive by va number, if empty will be use default value -1 for multiple use va, and 1 for single use va. If counter reach zero, va cannot be inquiry or accept payment.

Response Parameters

Parameter Type Nullable Description
status Object FALSE Status of response in Object {code: <status_code>, message: <status_message>}
amount BigDecimal FALSE Amount of VA transaction
va_number String(20) FALSE Generated VA number
id String(36) FALSE Unique VA ID
partner_user_id String(255) FALSE Your unique ID for specific user
bank_code String(3) FALSE Bank code for VA, see VA Bank Code
is_open Boolean FALSE True means VA number can accept any amount, False means VA number only accept the specified amount in the field amount
is_single_use Boolean FALSE True means that this VA should be closed/complete once there is a successful payment that is being made to this VA.
expiration_time Long FALSE Expiration time of VA on Unix timestamp in milliseconds, -1 means no expiration time.
va_status String(16) FALSE Status of VA, see VA Status
username_display String(255) FALSE Customizable VA display name that will be seen by user, If empty willl be using partner username
trx_expiration_time Long FALSE Transaction expiration time on Unix timestamp in milliseconds, -1 means no expiration time.
partner_trx_id String(255) TRUE Partner unique Transaction ID of a VA. This parameter will only be sent if end user fill the data
trx_counter Int FALSE Transaction counter to limit number of transaction that can be receive by va number, if empty will be use default value -1 for multiple use va, and 1 for single use va. If counter reach zero, va cannot be inquiry or accept payment.
counter_incoming_payment Integer FALSE Count total incoming payment of VA
full_name String(255) TRUE If full_name is needed when creating the transaction, the inputted full_name value at creation will be shown here. This parameter will only be sent if the value inputted in creation request. Only some VA banks required this parameter.

Get VA Info

Get VA info using Unique VA id.

curl -X \
GET https://partner.oyindonesia.com/api/static-virtual-account/1414255-12121-21212121-212121
-H 'content-type: application/json' \
-H 'accept: application/json' \
-H 'x-oy-username: username' \
-H 'x-api-key: apikey'
var headers = {
  'Content-Type': 'application/json',
  'X-Oy-Username': '{{username}}',
  'X-Api-Key': '{{api_key}}'
};
var request = http.Request('GET', Uri.parse('{{base_url}}/api/static-virtual-account/2c26f23d-2dfa-44d1-9202-f8c1f907a983'));

request.headers.addAll(headers);

http.StreamedResponse response = await request.send();

if (response.statusCode == 200) {
  print(await response.stream.bytesToString());
}
else {
  print(response.reasonPhrase);
}
package main

import (
  "fmt"
  "net/http"
  "io/ioutil"
)

func main() {

  url := "%7B%7Bbase_url%7D%7D/api/static-virtual-account/2c26f23d-2dfa-44d1-9202-f8c1f907a983"
  method := "GET"

  client := &http.Client {
  }
  req, err := http.NewRequest(method, url, nil)

  if err != nil {
    fmt.Println(err)
    return
  }
  req.Header.Add("Content-Type", "application/json")
  req.Header.Add("X-Oy-Username", "{{username}}")
  req.Header.Add("X-Api-Key", "{{api_key}}")

  res, err := client.Do(req)
  if err != nil {
    fmt.Println(err)
    return
  }
  defer res.Body.Close()

  body, err := ioutil.ReadAll(res.Body)
  if err != nil {
    fmt.Println(err)
    return
  }
  fmt.Println(string(body))
}
OkHttpClient client = new OkHttpClient().newBuilder()
  .build();
Request request = new Request.Builder()
  .url("{{base_url}}/api/static-virtual-account/2c26f23d-2dfa-44d1-9202-f8c1f907a983")
  .method("GET", null)
  .addHeader("Content-Type", "application/json")
  .addHeader("X-Oy-Username", "{{username}}")
  .addHeader("X-Api-Key", "{{api_key}}")
  .build();
Response response = client.newCall(request).execute();

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function() {
  if(this.readyState === 4) {
    console.log(this.responseText);
  }
});

xhr.open("GET", "%7B%7Bbase_url%7D%7D/api/static-virtual-account/2c26f23d-2dfa-44d1-9202-f8c1f907a983");
xhr.setRequestHeader("Content-Type", "application/json");
xhr.setRequestHeader("X-Oy-Username", "{{username}}");
xhr.setRequestHeader("X-Api-Key", "{{api_key}}");

xhr.send();
<?php
require_once 'HTTP/Request2.php';
$request = new HTTP_Request2();
$request->setUrl('{{base_url}}/api/static-virtual-account/2c26f23d-2dfa-44d1-9202-f8c1f907a983');
$request->setMethod(HTTP_Request2::METHOD_GET);
$request->setConfig(array(
  'follow_redirects' => TRUE
));
$request->setHeader(array(
  'Content-Type' => 'application/json',
  'X-Oy-Username' => '{{username}}',
  'X-Api-Key' => '{{api_key}}'
));
try {
  $response = $request->send();
  if ($response->getStatus() == 200) {
    echo $response->getBody();
  }
  else {
    echo 'Unexpected HTTP status: ' . $response->getStatus() . ' ' .
    $response->getReasonPhrase();
  }
}
catch(HTTP_Request2_Exception $e) {
  echo 'Error: ' . $e->getMessage();
}
import http.client
import json

conn = http.client.HTTPSConnection("{{base_url}}")
payload = ''
headers = {
  'Content-Type': 'application/json',
  'X-Oy-Username': '{{username}}',
  'X-Api-Key': '{{api_key}}'
}
conn.request("GET", "/api/static-virtual-account/2c26f23d-2dfa-44d1-9202-f8c1f907a983", payload, headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))

The above command returns JSON structured similar like this:

{
    "id": "1414255-12121-21212121-212121",
    "status": {
        "code": "000",
        "message": "Success"
    },
    "amount": 10000.0000,
    "va_number": "1233456000000000001",
    "bank_code": "002",
    "bank_name": "Bank BRI",
    "is_open": true,
    "is_single_use": false,
    "expiration_time": 1582790250609,
    "va_status": "WAITING_PAYMENT",
    "username_display": "username",
    "amount_detected": 0,
    "partner_user_id": "123456",
    "created": 1613545965167,
    "counter_incoming_payment": 0,
    "trx_expiration_time": 1582790250609,
    "partner_trx_id": "TRX0001",
    "trx_counter": -1,
    "email": "budi@gmal.com",
    "full_name": "budi budiman"
}

HTTPS Request

[Production] GET https://partner.oyindonesia.com/api/static-virtual-account/<ID>
[Staging] GET https://api-stg.oyindonesia.com/api/static-virtual-account/<ID>

URL Parameters

Parameter Type Required Default Description
ID String(255) TRUE - Unique VA id, you can get this once you success created VA

Response Parameters

Parameter Type Nullable Description
id String FALSE Unique VA id
status Object FALSE Status of response in Object {code: <status_code>, message: <status_message>}
amount BigDecimal FALSE Amount of VA transaction
va_number String(20) FALSE Generated VA number
bank_code String(3) FALSE Bank code for VA, see VA Bank Code
bank_name String(10) FALSE Bank name of the VA
is_open Boolean FALSE True means VA number can accept any amount, False means VA number only accept the specified amount in the field amount
is_single_use Boolean FALSE True means that this VA should be closed once there is a successful payment that is being made to this VA.
expiration_time Long FALSE Expiration time of VA on Unix timestamp in milliseconds, -1 means no expiration time.
va_status String(16) FALSE Status of VA, see VA Status
username_display String(255) FALSE Customizable VA display name that will be seen by user, If empty willl be using partner username
partner_user_id String(255) FALSE Partner unique ID for specific user
created Long FALSE Unix timestamp in milliseconds when VA created
counter_incoming_payment Integer FALSE Count total incoming payment of VA
trx_expiration_time Long FALSE Transaction expiration time on Unix timestamp in milliseconds, -1 means no expiration time.
partner_trx_id String(255) TRUE Partner unique Transaction ID of a VA. This parameter will only be sent if end user fill the data in creation process
trx_counter Int FALSE Transaction counter to limit number of transaction that can be receive by va number, if empty will be use default value -1 for multiple use va, and 1 for single use va. If counter reach zero, va cannot be inquiry or accept payment.
email String(255) TRUE This parameter will only be sent if the value inputted in creation request.
full_name String(255) TRUE If full_name is needed when creating the transaction, the inputted value at creation will be shown here. This parameter will only be sent if the value inputted in creation request. Only some VA banks required this parameter.

Update VA

Update VA using unique VA id.

curl -X \
PUT https://partner.oyindonesia.com/api/static-virtual-account/1414255-12121-21212121-212121
-H 'content-type: application/json' \
-H 'accept: application/json' \
-H 'x-oy-username: username' \
-H 'x-api-key: apikey' \
-d '{
    "amount": 50000,
    "is_single_use": false,
    "expiration_time": 30,
    "username_display": "test",
    "is_lifetime": false,
    "email": "email@domain.com",
    "trx_expiration_time":5,
    "partner_trx_id":"TRX0002",
    "trx_counter": 1
}'
var headers = {
  'Content-Type': 'application/json',
  'X-Oy-Username': '{{username}}',
  'X-Api-Key': '{{api-key}}'
};
var request = http.Request('PUT', Uri.parse('{{base_url}}/api/static-virtual-account/2701b82a-89f8-4343-81a2-fa0c92edca09'));
request.body = json.encode({
  "amount": 50000,
  "is_single_use": false,
  "expiration_time": 30,
  "username_display": "test",
  "is_lifetime": false,
  "email": "email@domain.com",
  "trx_expiration_time":5,
  "partner_trx_id":"TRX0002",
  "trx_counter": 1
});
request.headers.addAll(headers);

http.StreamedResponse response = await request.send();

if (response.statusCode == 200) {
  print(await response.stream.bytesToString());
}
else {
  print(response.reasonPhrase);
}
package main

import (
  "fmt"
  "strings"
  "net/http"
  "io/ioutil"
)

func main() {

  url := "%7B%7Bbase_url%7D%7D/api/static-virtual-account/2701b82a-89f8-4343-81a2-fa0c92edca09"
  method := "PUT"

  payload := strings.NewReader(`{
    "amount": 50000,
    "is_single_use": true,
    "expiration_time": 30,
    "username_display": "john doe",
    "is_lifetime": false,
    "email": "john.doe@email.com",
    "trx_expiration_time":5,
  "partner_trx_id":"TRX0002",
  "trx_counter": 1
}`)

  client := &http.Client {
  }
  req, err := http.NewRequest(method, url, payload)

  if err != nil {
    fmt.Println(err)
    return
  }
  req.Header.Add("Content-Type", "application/json")
  req.Header.Add("X-Oy-Username", "{{username}}")
  req.Header.Add("X-Api-Key", "{{api-key}}")

  res, err := client.Do(req)
  if err != nil {
    fmt.Println(err)
    return
  }
  defer res.Body.Close()

  body, err := ioutil.ReadAll(res.Body)
  if err != nil {
    fmt.Println(err)
    return
  }
  fmt.Println(string(body))
}
OkHttpClient client = new OkHttpClient().newBuilder()
  .build();
MediaType mediaType = MediaType.parse("application/json");
RequestBody body = RequestBody.create(mediaType, "{\n\t\"amount\": 50000,\n\t\"is_single_use\": false,\n\t\"expiration_time\": 30,\n\t\"username_display\": "test",\n\t\"is_lifetime\": false,\n\t\"email\": "email@domain.com",\n\t\"trx_expiration_time\": 5,\n\t\"partner_trx_id\": \"TRX0002\",\n\t\"trx_counter\": 1\n}");
Request request = new Request.Builder()
  .url("{{base_url}}/api/static-virtual-account/2701b82a-89f8-4343-81a2-fa0c92edca09")
  .method("PUT", body)
  .addHeader("Content-Type", "application/json")
  .addHeader("X-Oy-Username", "{{username}}")
  .addHeader("X-Api-Key", "{{api-key}}")
  .build();
Response response = client.newCall(request).execute();
var data = JSON.stringify({
  "amount": 50000,
  "is_single_use": false,
  "expiration_time": 30,
  "username_display": "test",
  "is_lifetime": false,
  "email": "email@domain.com",
  "trx_expiration_time":5,
  "partner_trx_id":"TRX0002",
  "trx_counter": 1
});

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function() {
  if(this.readyState === 4) {
    console.log(this.responseText);
  }
});

xhr.open("PUT", "%7B%7Bbase_url%7D%7D/api/static-virtual-account/2701b82a-89f8-4343-81a2-fa0c92edca09");
xhr.setRequestHeader("Content-Type", "application/json");
xhr.setRequestHeader("X-Oy-Username", "{{username}}");
xhr.setRequestHeader("X-Api-Key", "{{api-key}}");

xhr.send(data);
<?php
require_once 'HTTP/Request2.php';
$request = new HTTP_Request2();
$request->setUrl('{{base_url}}/api/static-virtual-account/2701b82a-89f8-4343-81a2-fa0c92edca09');
$request->setMethod(HTTP_Request2::METHOD_PUT);
$request->setConfig(array(
  'follow_redirects' => TRUE
));
$request->setHeader(array(
  'Content-Type' => 'application/json',
  'X-Oy-Username' => '{{username}}',
  'X-Api-Key' => '{{api-key}}'
));
$request->setBody('{\n  "amount": 50000,\n  "is_single_use": false,\n   "expiration_time": 30,\n    "username_display": "test",\n   "is_lifetime": false,\n "email": "email@domain.com",\n  "trx_expiration_time": 5,\n "partner_trx_id": "TRX0002",\n  "trx_counter": 1\n}');
try {
  $response = $request->send();
  if ($response->getStatus() == 200) {
    echo $response->getBody();
  }
  else {
    echo 'Unexpected HTTP status: ' . $response->getStatus() . ' ' .
    $response->getReasonPhrase();
  }
}
catch(HTTP_Request2_Exception $e) {
  echo 'Error: ' . $e->getMessage();
}
import http.client
import json

conn = http.client.HTTPSConnection("{{base_url}}")
payload = json.dumps({
  "amount": 50000,
  "is_single_use": false,
  "expiration_time": 30,
  "username_display": "test",
  "is_lifetime": false,
  "email": "email@domain.com",
  "trx_expiration_time":5,
  "partner_trx_id":"TRX0002",
  "trx_counter": 1
})
headers = {
  'Content-Type': 'application/json',
  'X-Oy-Username': '{{username}}',
  'X-Api-Key': '{{api-key}}'
}
conn.request("PUT", "/api/static-virtual-account/2701b82a-89f8-4343-81a2-fa0c92edca09", payload, headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))

The above command returns JSON structured similar like this:

{
    "id": "1414255-12121-21212121-212121",
    "status": {
        "code": "000",
        "message": "Success"
    },
    "amount": 50000,
    "va_number": "1001234000000000001",
    "bank_code": "002",
    "is_open": true,
    "is_single_use": false,
    "expiration_time": 1582802205412,
    "va_status": "WAITING_PAYMENT",
    "username_display": "vaname",
    "partner_user_id": "12345677",
    "trx_expiration_time": 1582802205412,
    "partner_trx_id": "TRX0002",
    "trx_counter": 1,
    "counter_incoming_payment" : 0
}

HTTPS Request

[Production] PUT https://partner.oyindonesia.com/api/static-virtual-account/<ID>
[Staging] PUT https://api-stg.oyindonesia.com/api/static-virtual-account/<ID>

URL Parameter

Parameter Type Required Default Description
ID String(36) TRUE - Unique VA ID, you can get this once you success created VA

Request Parameters

Parameter Type Required Default Description
amount BigDecimal FALSE - Amount your user must paid to complete the transaction
is_single_use Boolean FALSE false True means that this VA should be closed once there is a successful payment that is being made to this VA.
expiration_time Long FALSE - Expiration time of the VA in minutes, if empty VA will be expired in 24 hour. If you want to deactivate/cancel the VA, pass "0" in the expiration_time
username_display String - - Customizable VA display name that will be seen by user, If empty willl be using partner username
is_lifetime Boolean FALSE - false
email String(255) FALSE - Email of user, using email standard format
trx_expiration_time Long FALSE - Transaction expiration time in minutes, e.g If Transaction want to be expired after 5 minutes, you just have to set expiration_time to 5. If you want to make the trx_expiration_time expired, pass "0" in the trx_expiration_time
partner_trx_id String(255) FALSE - Partner unique Transaction ID of a VA
trx_counter Int FALSE -1/1 Update transaction counter to limit number of transaction that can be receive by va number

Response Parameters

Parameter Type Nullable Description
id String FALSE Unique VA id
status Object FALSE Status of response in Object {code: <status_code>, message: <status_message>}
amount BigDecimal FALSE Amount of VA transaction
va_number String(20) FALSE Generated VA number
bank_code String(3) FALSE Bank code for VA, see VA Bank Code
is_open Boolean FALSE True means VA number can accept any amount, False means VA number only accept the specified amount in the field amount
is_single_use Boolean FALSE True means that this VA should be closed once there is a successful payment that is being made to this VA.
expiration_time Long FALSE Expiration time of VA on Unix timestamp in milliseconds, -1 means no expiration time.
va_status String(16) FALSE Status of VA, see VA Status
username_display String(255) FALSE Customizable VA display name that will be seen by user, If empty willl be using partner username
partner_user_id String(255) FALSE Partner unique ID for specific user
trx_expiration_time Long FALSE Transaction expiration time on Unix timestamp in milliseconds, -1 means no expiration time.
partner_trx_id String(255) TRUE Partner unique Transaction ID of a VA. This parameter will only be sent if end user fill the data in update request parameter.
trx_counter Int FALSE Transaction counter to limit number of transaction that can be receive by va number, if empty will be use default value -1 for multiple use va, and 1 for single use va. If counter reach zero, va cannot be inquiry or accept payment.
counter_incoming_payment Integer FALSE Count total incoming payment of VA
email String(255) TRUE This parameter will only be sent if the value inputted in creation request.
full_name String(255) TRUE If full_name is needed when creating the transaction, the inputted value at creation will be shown here. This parameter will only be sent if the value inputted in creation request. Only some VA banks required this parameter.

Deactivate VA

To deactivate a VA number, use API Update VA with specific request parameter explained below.

curl -X \
PUT https://partner.oyindonesia.com/api/static-virtual-account/1414255-12121-21212121-212121
-H 'content-type: application/json' \
-H 'accept: application/json' \
-H 'x-oy-username: username' \
-H 'x-api-key: apikey' \
-d '{
    "expiration_time": 0
}'
var headers = {
  'Content-Type': 'application/json',
  'X-Oy-Username': '{{username}}',
  'X-Api-Key': '{{api-key}}'
};
var request = http.Request('PUT', Uri.parse('{{base_url}}/api/static-virtual-account/2701b82a-89f8-4343-81a2-fa0c92edca09'));
request.body = json.encode({
  "expiration_time": 0
});
request.headers.addAll(headers);

http.StreamedResponse response = await request.send();

if (response.statusCode == 200) {
  print(await response.stream.bytesToString());
}
else {
  print(response.reasonPhrase);
}
package main

import (
  "fmt"
  "strings"
  "net/http"
  "io/ioutil"
)

func main() {

  url := "%7B%7Bbase_url%7D%7D/api/static-virtual-account/2701b82a-89f8-4343-81a2-fa0c92edca09"
  method := "PUT"

  payload := strings.NewReader(`{
    "expiration_time": 0
}`)

  client := &http.Client {
  }
  req, err := http.NewRequest(method, url, payload)

  if err != nil {
    fmt.Println(err)
    return
  }
  req.Header.Add("Content-Type", "application/json")
  req.Header.Add("X-Oy-Username", "{{username}}")
  req.Header.Add("X-Api-Key", "{{api-key}}")

  res, err := client.Do(req)
  if err != nil {
    fmt.Println(err)
    return
  }
  defer res.Body.Close()

  body, err := ioutil.ReadAll(res.Body)
  if err != nil {
    fmt.Println(err)
    return
  }
  fmt.Println(string(body))
}
OkHttpClient client = new OkHttpClient().newBuilder()
  .build();
MediaType mediaType = MediaType.parse("application/json");
RequestBody body = RequestBody.create(mediaType, "{\n\t\"amount\": 50000,\n\t\"is_single_use\": false,\n\t\"expiration_time\": 30,\n\t\"username_display\": "test",\n\t\"is_lifetime\": false,\n\t\"email\": "email@domain.com",\n\t\"trx_expiration_time\": 5,\n\t\"partner_trx_id\": \"TRX0002\",\n\t\"trx_counter\": 1\n}");
Request request = new Request.Builder()
  .url("{{base_url}}/api/static-virtual-account/2701b82a-89f8-4343-81a2-fa0c92edca09")
  .method("PUT", body)
  .addHeader("Content-Type", "application/json")
  .addHeader("X-Oy-Username", "{{username}}")
  .addHeader("X-Api-Key", "{{api-key}}")
  .build();
Response response = client.newCall(request).execute();
var data = JSON.stringify({
  "expiration_time": 0
});

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function() {
  if(this.readyState === 4) {
    console.log(this.responseText);
  }
});

xhr.open("PUT", "%7B%7Bbase_url%7D%7D/api/static-virtual-account/2701b82a-89f8-4343-81a2-fa0c92edca09");
xhr.setRequestHeader("Content-Type", "application/json");
xhr.setRequestHeader("X-Oy-Username", "{{username}}");
xhr.setRequestHeader("X-Api-Key", "{{api-key}}");

xhr.send(data);
<?php
require_once 'HTTP/Request2.php';
$request = new HTTP_Request2();
$request->setUrl('{{base_url}}/api/static-virtual-account/2701b82a-89f8-4343-81a2-fa0c92edca09');
$request->setMethod(HTTP_Request2::METHOD_PUT);
$request->setConfig(array(
  'follow_redirects' => TRUE
));
$request->setHeader(array(
  'Content-Type' => 'application/json',
  'X-Oy-Username' => '{{username}}',
  'X-Api-Key' => '{{api-key}}'
));
$request->setBody('{\n  "expiration_time": 0\n}');
try {
  $response = $request->send();
  if ($response->getStatus() == 200) {
    echo $response->getBody();
  }
  else {
    echo 'Unexpected HTTP status: ' . $response->getStatus() . ' ' .
    $response->getReasonPhrase();
  }
}
catch(HTTP_Request2_Exception $e) {
  echo 'Error: ' . $e->getMessage();
}
import http.client
import json

conn = http.client.HTTPSConnection("{{base_url}}")
payload = json.dumps({
  "expiration_time": 0
})
headers = {
  'Content-Type': 'application/json',
  'X-Oy-Username': '{{username}}',
  'X-Api-Key': '{{api-key}}'
}
conn.request("PUT", "/api/static-virtual-account/2701b82a-89f8-4343-81a2-fa0c92edca09", payload, headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))

The above command returns JSON structured similar like this:

{
    "id": "1414255-12121-21212121-212121",
    "status": {
        "code": "000",
        "message": "Success"
    },
    "amount": 50000,
    "va_number": "1001234000000000001",
    "bank_code": "002",
    "is_open": true,
    "is_single_use": false,
    "expiration_time": 0,
    "va_status": "EXPIRED",
    "username_display": "vaname",
    "partner_user_id": "12345677",
    "trx_expiration_time": 0,
    "partner_trx_id": "TRX0002",
    "trx_counter": 1,
    "counter_incoming_payment" : 0
}

HTTPS Request

[Production] PUT https://partner.oyindonesia.com/api/static-virtual-account/<ID>
[Staging] PUT https://api-stg.oyindonesia.com/api/static-virtual-account/<ID>

URL Parameter

Parameter Type Required Default Description
ID String(36) TRUE - Unique VA ID, you can get this once you success created VA

Request Parameters

Parameter Type Required Default Description
expiration_time Long TRUE - To deactivate/cancel the VA, pass "0" in the expiration_time.

Response Parameters

Parameter Type Nullable Description
id String FALSE Unique VA id
status Object FALSE Status of response in Object {code: <status_code>, message: <status_message>}.
amount BigDecimal FALSE Amount of VA transaction.
va_number String(20) FALSE Generated VA number.
bank_code String(3) FALSE Bank code for VA, see VA Bank Code.
is_open Boolean FALSE True means VA number can accept any amount, False means VA number only accept the specified amount in the field amount.
is_single_use Boolean FALSE True means that this VA should be closed once there is a successful payment that is being made to this VA.
expiration_time Long FALSE Expiration time of VA on Unix timestamp in milliseconds.
va_status String(16) FALSE Status of VA, see VA Status. For deactivation request, the va_status result should be EXPIRED.
username_display String(255) FALSE Customizable VA display name that will be seen by user, If empty willl be using partner username.
partner_user_id String(255) FALSE Partner unique ID for specific user.
trx_expiration_time Long FALSE Transaction expiration time on Unix timestamp in milliseconds.
partner_trx_id String(255) TRUE Partner unique Transaction ID of a VA. This parameter will only be sent if end user fill the data in update request parameter.
trx_counter Int FALSE Transaction counter to limit number of transaction that can be receive by va number, if empty will be use default value -1 for multiple use va, and 1 for single use va. If counter reach zero, va cannot be inquiry or accept payment.
counter_incoming_payment Integer FALSE Count total incoming payment of VA.
email String(255) TRUE This parameter will only be sent if the value inputted in creation request.
full_name String(255) TRUE If full_name is needed when creating the transaction, the inputted value at creation will be shown here. This parameter will only be sent if the value inputted in creation request. Only some VA banks required this parameter.

Get list of created VA

Get list of created VA

curl -X \
GET https://partner.oyindonesia.com/api/static-virtual-account?offset=0&limit=10
-H 'content-type: application/json' \
-H 'accept: application/json' \
-H 'x-oy-username: username' \
-H 'x-api-key: apikey'
var headers = {
  'Content-Type': 'application/json',
  'X-Oy-Username': '{{username}}',
  'X-Api-Key': '{{api-key}}'
};
var request = http.Request('GET', Uri.parse('{{base_url}}/api/static-virtual-account?offset=0&limit=5'));
request.headers.addAll(headers);

http.StreamedResponse response = await request.send();

if (response.statusCode == 200) {
  print(await response.stream.bytesToString());
}
else {
  print(response.reasonPhrase);
}
package main

import (
  "fmt"
  "strings"
  "net/http"
  "io/ioutil"
)

func main() {

  url := "%7B%7Bbase_url%7D%7D/api/static-virtual-account?offset=0&limit=5"
  method := "GET"

  client := &http.Client {
  }
  req, err := http.NewRequest(method, url)

  if err != nil {
    fmt.Println(err)
    return
  }
  req.Header.Add("Content-Type", "application/json")
  req.Header.Add("X-Oy-Username", "{{username}}")
  req.Header.Add("X-Api-Key", "{{api-key}}")

  res, err := client.Do(req)
  if err != nil {
    fmt.Println(err)
    return
  }
  defer res.Body.Close()

  body, err := ioutil.ReadAll(res.Body)
  if err != nil {
    fmt.Println(err)
    return
  }
  fmt.Println(string(body))
}
OkHttpClient client = new OkHttpClient().newBuilder()
  .build();
Request request = new Request.Builder()
  .url("{{base_url}}/api/static-virtual-account?offset=0&limit=5")
  .method("GET", null)
  .addHeader("Content-Type", "application/json")
  .addHeader("X-Oy-Username", "{{username}}")
  .addHeader("X-Api-Key", "{{api-key}}")
  .build();
Response response = client.newCall(request).execute();
var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function() {
  if(this.readyState === 4) {
    console.log(this.responseText);
  }
});

xhr.open("GET", "%7B%7Bbase_url%7D%7D/api/static-virtual-account?offset=0&limit=5");
xhr.setRequestHeader("Content-Type", "application/json");
xhr.setRequestHeader("X-Oy-Username", "{{username}}");
xhr.setRequestHeader("X-Api-Key", "{{api-key}}");

xhr.send();
<?php
require_once 'HTTP/Request2.php';
$request = new HTTP_Request2();
$request->setUrl('{{base_url}}/api/static-virtual-account?offset=0&limit=5');
$request->setMethod(HTTP_Request2::METHOD_GET);
$request->setConfig(array(
  'follow_redirects' => TRUE
));
$request->setHeader(array(
  'Content-Type' => 'application/json',
  'X-Oy-Username' => '{{username}}',
  'X-Api-Key' => '{{api-key}}'
));

try {
  $response = $request->send();
  if ($response->getStatus() == 200) {
    echo $response->getBody();
  }
  else {
    echo 'Unexpected HTTP status: ' . $response->getStatus() . ' ' .
    $response->getReasonPhrase();
  }
}
catch(HTTP_Request2_Exception $e) {
  echo 'Error: ' . $e->getMessage();
}
import http.client
import json

conn = http.client.HTTPSConnection("{{base_url}}")
payload = ''
headers = {
  'Content-Type': 'application/json',
  'X-Oy-Username': '{{username}}',
  'X-Api-Key': '{{api-key}}'
}
conn.request("GET", "/api/static-virtual-account?offset=0&limit=5", payload, headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))

The above command returns JSON structured similar like this:

{
    "total": 5,
    "data": [
        {
            "id": "9a660428-3373-436b-b929-ef69698dd26f",
            "amount": 12000.0000,
            "va_number": "100536000000000006",
            "bank_code": "002",
            "bank_name": "Bank BRI",
            "is_open": true,
            "is_single_use": false,
            "expiration_time": 1582791896416,
            "va_status": "EXPIRED",
            "username_display": "username",
            "amount_detected": 400000,
            "partner_user_id": "12345",
            "created" : 1613545965167,
            "counter_incoming_payment" : 0,
            "trx_expiration_time": 1582802205412,
            "partner_trx_id": "TRX0002",
            "trx_counter": 0,
            "email": "budi@gmal.com",
            "full_name": "budi budiman"
        },
        {
            "id": "de51383f-1557-409c-8542-dcb74ca76375",
            "amount": 12000.0000,
            "va_number": "100536000000000005",
            "bank_code": "002",
            "bank_name": "Bank BRI",
            "is_open": true,
            "is_single_use": false,
            "expiration_time": 1582790250609,
            "va_status": "EXPIRED",
            "username_display": "username",
            "amount_detected": 500000,
            "partner_user_id": "54321",
            "created" : 1613545965167,
            "counter_incoming_payment" : 0,
            "trx_expiration_time": 1582802205412,
            "partner_trx_id": "TRX0002",
            "trx_counter": 0,
            "email": "budi@gmal.com",
            "full_name": "budi budiman"
        }
    ],
    "status": {
        "code": "000",
        "message": "Success"
    }
}

HTTPS Request

[Production] GET https://partner.oyindonesia.com/api/static-virtual-account?offset=<offset>&limit=<limit>
[Staging] GET https://api-stg.oyindonesia.com/api/static-virtual-account?offset=<offset>&limit=<limit>

Request Parameters

Parameter Type Default Description
offset Integer 0 start offset, default is 0, if empty will used default value
limit Integer 10 max item to fetch, default is 10, if empty will used default value

Response Parameters

Parameter Type Nullable Description
total Integer FALSE total items
data Array of object TRUE List of Object {id: <va_id>, amount: <amount>, va_number: <va_number>, bank_code: <bank_code>, bank_name: <bank_name>, is_open: <is_open>, is_single_user: <is_single_user>, expiration_time: <expiration_time>, va_status: <va_status>, username_display: <username_display>, amount_detected: <amount_detected>, partner_user_id: <partner_user_id>, created: <created>, counter_incoming_payment: <counter_incoming_payment>, trx_counter: <trx_counter>, email: <email>, full_name: <full_name>} If the user has never created a va, the data will be empty
status Object FALSE Status of response in Object {code: <status_code>, message: <status_message>}

Get List of Transaction for VA

Get list of incoming transaction for specific va number. This API will only retrieve lastest updated data within last 3 months.

curl -X \
GET https://partner.oyindonesia.com/api/va-tx-history/2701b82a-89f8-4343-81a2-fa0c92edca09?offset=0&limit=10
-H 'content-type: application/json' \
-H 'accept: application/json' \
-H 'x-oy-username: username' \
-H 'x-api-key: apikey'
var headers = {
  'Content-Type': 'application/json',
  'X-Oy-Username': '{{username}}',
  'X-Api-Key': '{{api-key}}'
};
var request = http.Request('GET', Uri.parse('{{base_url}}/api/va-tx-history/2701b82a-89f8-4343-81a2-fa0c92edca09?offset=0&limit=5'));
request.headers.addAll(headers);

http.StreamedResponse response = await request.send();

if (response.statusCode == 200) {
  print(await response.stream.bytesToString());
}
else {
  print(response.reasonPhrase);
}

package main

import (
  "fmt"
  "strings"
  "net/http"
  "io/ioutil"
)

func main() {

  url := "%7B%7Bbase_url%7D%7D/api/va-tx-history/2701b82a-89f8-4343-81a2-fa0c92edca09?offset=0&limit=5"
  method := "GET"

  client := &http.Client {
  }
  req, err := http.NewRequest(method, url)

  if err != nil {
    fmt.Println(err)
    return
  }
  req.Header.Add("Content-Type", "application/json")
  req.Header.Add("X-Oy-Username", "{{username}}")
  req.Header.Add("X-Api-Key", "{{api-key}}")

  res, err := client.Do(req)
  if err != nil {
    fmt.Println(err)
    return
  }
  defer res.Body.Close()

  body, err := ioutil.ReadAll(res.Body)
  if err != nil {
    fmt.Println(err)
    return
  }
  fmt.Println(string(body))
}
OkHttpClient client = new OkHttpClient().newBuilder()
  .build();
Request request = new Request.Builder()
  .url("{{base_url}}/api/va-tx-history/2701b82a-89f8-4343-81a2-fa0c92edca09?offset=0&limit=5")
  .method("GET", null)
  .addHeader("Content-Type", "application/json")
  .addHeader("X-Oy-Username", "{{username}}")
  .addHeader("X-Api-Key", "{{api-key}}")
  .build();
Response response = client.newCall(request).execute();
var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function() {
  if(this.readyState === 4) {
    console.log(this.responseText);
  }
});

xhr.open("GET", "%7B%7Bbase_url%7D%7D/api/va-tx-history/2701b82a-89f8-4343-81a2-fa0c92edca09?offset=0&limit=5");
xhr.setRequestHeader("Content-Type", "application/json");
xhr.setRequestHeader("X-Oy-Username", "{{username}}");
xhr.setRequestHeader("X-Api-Key", "{{api-key}}");

xhr.send();
<?php
require_once 'HTTP/Request2.php';
$request = new HTTP_Request2();
$request->setUrl('{{base_url}}/api/va-tx-history/2701b82a-89f8-4343-81a2-fa0c92edca09?offset=0&limit=5');
$request->setMethod(HTTP_Request2::METHOD_GET);
$request->setConfig(array(
  'follow_redirects' => TRUE
));
$request->setHeader(array(
  'Content-Type' => 'application/json',
  'X-Oy-Username' => '{{username}}',
  'X-Api-Key' => '{{api-key}}'
));

try {
  $response = $request->send();
  if ($response->getStatus() == 200) {
    echo $response->getBody();
  }
  else {
    echo 'Unexpected HTTP status: ' . $response->getStatus() . ' ' .
    $response->getReasonPhrase();
  }
}
catch(HTTP_Request2_Exception $e) {
  echo 'Error: ' . $e->getMessage();
}
import http.client
import json

conn = http.client.HTTPSConnection("{{base_url}}")
payload = ''
headers = {
  'Content-Type': 'application/json',
  'X-Oy-Username': '{{username}}',
  'X-Api-Key': '{{api-key}}'
}
conn.request("GET", "/api/va-tx-history/2701b82a-89f8-4343-81a2-fa0c92edca09?offset=0&limit=5", payload, headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))

The above command returns JSON structured similar like this:

{
    "id": "12345676788898",
    "status": {
        "code": "000",
        "message": "Success"
    },
    "data": [
        {
            "id": "d9c2963f-be14-4558-9380-5ba1db8ed156",
            "created": "2020-02-27 07:48:01",
            "create_by": "Static VA by username",
            "last_updated": "2020-02-27 10:08:01",
            "last_update_by": "Static VA by username",
            "record_flag": "active",
            "name": "Static VA by username",
            "amount": 10000,
            "admin_fee": 1000,
            "va_number": "123456000000000001",
            "va_name": "test",
            "email": "email@mail.com",
            "va_bank": "BRI",
            "bank_code": "002",
            "partner_trx_id": "test123",
            "settlement_time": "2020-02-28 15:00:00",
            "settlement_status": "WAITING"
        }
    ],
    "number_of_transaction": 1,
    "total_incoming_payment": 10000
}

HTTPS Request

[Production] GET https://partner.oyindonesia.com/api/va-tx-history/<ID>?offset=<offset>&limit=<limit>
[Staging] GET https://api-stg.oyindonesia.com/api/va-tx-history/<ID>?offset=<offset>&limit=<limit>

URL Parameter

Parameter Type Required Default Description
ID String(36) TRUE - Unique VA ID, you can get this once you success created VA

Request Parameters

Parameter Type Required Default Description
offset Integer FALSE 0 start offset, default is 0, if empty will used default value
limit Integer FALSE 10 max item to fetch, default is 10, if empty will used default value

Response Parameters

Parameter Type Nullable Description
id Integer FALSE Unique VA id
status Object FALSE Status of response in Object {code: <status_code>, message: <status_message>}
data Array of Object TRUE List of Va Object, if the user has never created a va, the data will be empty
number_of_transaction Integer FALSE Total transaction
total_incoming_payment Integer FALSE Total incoming payment

VA Object

Parameter Type Nullable Description
id Integer FALSE Unique VA transaction id
created String FALSE Date and time when the transaction was created
create_by String FALSE Name of the user who created the transaction
last_updated String FALSE Date and time when the transaction was last updated
last_update_by String FALSE Name of the user who last updated the transaction
record_flag String FALSE transaction activate state
name String FALSE Name of the VA
amount BigDecimal FALSE Amount of the transaction
admin_fee BigDecimal FALSE Admin fee of the transaction
va_number String FALSE VA number
va_name String FALSE Name of the VA
email String FALSE Email of the user
va_bank String FALSE Bank name of the VA
bank_code String FALSE Bank code of the VA
partner_trx_id String FALSE Partner unique Transaction ID of a VA
settlement_time String FALSE Date and time when the transaction was settled
settlement_status String FALSE Status of the settlement

Create Customized VA

Use this API to create new VA number with customized VA suffix.

curl -X \
POST https://partner.oyindonesia.com/api/custom-va
-H 'content-type: application/json' \
-H 'accept: application/json' \
-H 'x-oy-username: username' \
-H 'x-api-key: apikey' \
-d '{
    "partner_user_id":"51200021",
    "bank_code": "002",
    "amount": 10000,
    "is_open": false,
    "username_display": "va name",
    "email": "email@mail.com",
    "trx_expiration_time": 5,
    "partner_trx_id": "TRX0001",
    "va_suffix" : "081234567890"
}'
var headers = {
  'Content-Type': 'application/json',
  'X-Oy-Username': '{{username}}',
  'X-Api-Key': '{{api-key}}'
};
var request = http.Request('POST', Uri.parse('{{base_url}}/api/custom-va'));
request.body = json.encode({
    "partner_user_id":"51200021",
    "bank_code": "002",
    "amount": 10000,
    "is_open": false,
    "username_display": "va name",
    "email": "email@mail.com",
    "trx_expiration_time": 5,
    "partner_trx_id": "TRX0001",
    "va_suffix" : "081234567890"
});
request.headers.addAll(headers);

http.StreamedResponse response = await request.send();

if (response.statusCode == 200) {
  print(await response.stream.bytesToString());
}
else {
  print(response.reasonPhrase);
}
package main

import (
  "fmt"
  "strings"
  "net/http"
  "io/ioutil"
)

func main() {

  url := "%7B%7Bbase_url%7D%7D/api/custom-va"
  method := "POST"

  payload := strings.NewReader(`{
  "partner_user_id":"51200021",
  "bank_code": "002",
  "amount": 10000,
  "is_open": false,
  "username_display": "va name",
  "email": "email@mail.com",
  "trx_expiration_time": 5,
  "partner_trx_id": "TRX0001",
  "va_suffix" : "081234567890"
}`)

  client := &http.Client {
  }
  req, err := http.NewRequest(method, url, payload)

  if err != nil {
    fmt.Println(err)
    return
  }
  req.Header.Add("Content-Type", "application/json")
  req.Header.Add("X-Oy-Username", "{{username}}")
  req.Header.Add("X-Api-Key", "{{api-key}}")

  res, err := client.Do(req)
  if err != nil {
    fmt.Println(err)
    return
  }
  defer res.Body.Close()

  body, err := ioutil.ReadAll(res.Body)
  if err != nil {
    fmt.Println(err)
    return
  }
  fmt.Println(string(body))
}
OkHttpClient client = new OkHttpClient().newBuilder()
  .build();
MediaType mediaType = MediaType.parse("application/json");
RequestBody body = RequestBody.create(mediaType, "{\n\"partner_user_id\":\"51200021\",\n\"bank_code\": \"002\",\n\"amount\": 10000,\n\"is_open\": false,\n\"username_display\": \"va name\",\n\"email\": \"email@mail.com\",\n\"trx_expiration_time\": 5,\n\"partner_trx_id\": \"TRX0001\",\n\"va_suffix\" : \"081234567890\"\n}");
Request request = new Request.Builder()
  .url("{{base_url}}/api/custom-va")
  .method("POST", body)
  .addHeader("Content-Type", "application/json")
  .addHeader("X-Oy-Username", "{{username}}")
  .addHeader("X-Api-Key", "{{api-key}}")
  .build();
Response response = client.newCall(request).execute();
var data = JSON.stringify({
  "partner_user_id":"51200021",
  "bank_code": "002",
  "amount": 10000,
  "is_open": false,
  "username_display": "va name",
  "email": "email@mail.com",
  "trx_expiration_time": 5,
  "partner_trx_id": "TRX0001",
  "va_suffix" : "081234567890"
});

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function() {
  if(this.readyState === 4) {
    console.log(this.responseText);
  }
});

xhr.open("POST", "%7B%7Bbase_url%7D%7D/api/custom-va");
xhr.setRequestHeader("Content-Type", "application/json");
xhr.setRequestHeader("X-Oy-Username", "{{username}}");
xhr.setRequestHeader("X-Api-Key", "{{api-key}}");

xhr.send(data);
<?php
require_once 'HTTP/Request2.php';
$request = new HTTP_Request2();
$request->setUrl('{{base_url}}/api/custom-va');
$request->setMethod(HTTP_Request2::METHOD_POST);
$request->setConfig(array(
  'follow_redirects' => TRUE
));
$request->setHeader(array(
  'Content-Type' => 'application/json',
  'X-Oy-Username' => '{{username}}',
  'X-Api-Key' => '{{api-key}}'
));
$request->setBody('"{\n\"partner_user_id\":\"51200021\",\n\"bank_code\": \"002\",\n\"amount\": 10000,\n\"is_open\": false,\n\"username_display\": \"va name\",\n\"email\": \"email@mail.com\",\n\"trx_expiration_time\": 5,\n\"partner_trx_id\": \"TRX0001\",\n\"va_suffix\" : \"081234567890\"\n}"');
try {
  $response = $request->send();
  if ($response->getStatus() == 200) {
    echo $response->getBody();
  }
  else {
    echo 'Unexpected HTTP status: ' . $response->getStatus() . ' ' .
    $response->getReasonPhrase();
  }
}
catch(HTTP_Request2_Exception $e) {
  echo 'Error: ' . $e->getMessage();
}
import http.client
import json

conn = http.client.HTTPSConnection("{{base_url}}")
payload = json.dumps({
  "partner_user_id":"51200021",
  "bank_code": "002",
  "amount": 10000,
  "is_open": false,
  "username_display": "va name",
  "email": "email@mail.com",
  "trx_expiration_time": 5,
  "partner_trx_id": "TRX0001",
  "va_suffix" : "081234567890"
})
headers = {
  'Content-Type': 'application/json',
  'X-Oy-Username': '{{username}}',
  'X-Api-Key': '{{api-key}}'
}
conn.request("POST", "/api/custom-va", payload, headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))

The above command returns JSON structured similar like this:

{
    "id": "12345b1-23be-45670-a123-5ca678f12b3e",
    "status": {
        "code": "000",
        "message": "Success"
    },
    "amount": 10000,
    "va_number": "134789181234567890",
    "bank_code": "002",
    "is_open": false,
    "va_status": "WAITING_PAYMENT",
    "username_display": "va name",
    "partner_user_id" : "51200021",
    "trx_expiration_time": 1582783668175,
    "partner_trx_id": "TRX0001"
}

HTTPS Request

[Production] POST https://partner.oyindonesia.com/api/custom-va
[Staging] POST https://api-stg.oyindonesia.com/api/custom-va

Request Parameters

Parameter Type Required Default Description
partner_user_id String(255) TRUE - Partner unique ID for specific user
bank_code String(3) TRUE - Bank code which the VA number will be generated. Currently our system only supports customized VA BRI and CIMB. For bank code detail, please refer to VA Bank Code
amount BigDecimal FALSE 0 Amount your user must paid to complete the transaction, if is_open is false, amount is required.
is_open Boolean FALSE true If set true means VA number can accept any amount, field amount can be optional, if set false means VA number only accept the specified amount in the field amount. When you set is_open to false, you must specify amount field.
username_display String(255) FALSE username Customizable VA display name that will be seen by user, If empty willl be using partner username
email String(255) FALSE - Email of user, using email standard format
trx_expiration_time Long FALSE - Transaction expiration time in minutes, e.g If Transaction want to be expired after 5 minutes, you just have to set expiration_time to 5. If empty, there will be no transaction expiration time.
partner_trx_id String(255) FALSE - Partner unique Transaction ID of a VA
va_suffix String (10-12) TRUE - Customized VA suffix that will be used by user. Must consists of digit only. Please note that given suffix may be trimmed from the front if it exceeds maximum VA digit capacity.

Response Parameters

Parameter Type Nullable Description
status Object FALSE Status of response in Object {code: <status_code>, message: <status_message>}
amount BigDecimal FALSE Amount of VA transaction
va_number String(20) FALSE Generated VA number
id String(36) FALSE Unique VA ID
partner_user_id String(255) FALSE Your unique ID for specific user
bank_code String(3) FALSE Bank code for VA, see VA Bank Code
is_open Boolean FALSE True means VA number can accept any amount, False means VA number only accept the specified amount in the field amount
va_status String(16) FALSE Status of VA, see VA Status
username_display String(255) FALSE Customizable VA display name that will be seen by user, If empty willl be using partner username
trx_expiration_time Long FALSE Transaction expiration time on Unix timestamp in milliseconds, -1 means no expiration time.
partner_trx_id String(255) TRUE Partner unique Transaction ID of a VA. This parameter will only be sent if end user fill the data in creation process

Update Customized VA

Update Customized VA using unique VA id.

curl -X \
PUT https://partner.oyindonesia.com/api/custom-va/1414255-12121-21212121-212121
-H 'content-type: application/json' \
-H 'accept: application/json' \
-H 'x-oy-username: username' \
-H 'x-api-key: apikey' \
-d '{
    "amount": 50000,
    "username_display": "test",
    "email": "email@domain.com",
    "trx_expiration_time": 5,
    "partner_trx_id": "TRX0002"
}'
var headers = {
  'Content-Type': 'application/json',
  'X-Oy-Username': '{{username}}',
  'X-Api-Key': '{{api-key}}'
};
var request = http.Request('PUT', Uri.parse('{{base_url}}/api/custom-va/2701b82a-89f8-4343-81a2-fa0c92edca09'));
request.body = json.encode({
  "amount": 50000,
  "username_display": "test",
  "email": "email@domain.com",
  "trx_expiration_time": 5,
  "partner_trx_id": "TRX0002"
});
request.headers.addAll(headers);

http.StreamedResponse response = await request.send();

if (response.statusCode == 200) {
  print(await response.stream.bytesToString());
}
else {
  print(response.reasonPhrase);
}
package main

import (
  "fmt"
  "strings"
  "net/http"
  "io/ioutil"
)

func main() {

  url := "%7B%7Bbase_url%7D%7D/api/custom-va/2701b82a-89f8-4343-81a2-fa0c92edca09"
  method := "PUT"

  payload := strings.NewReader(`{
  "amount": 50000,
  "username_display": "test",
  "email": "email@domain.com",
  "trx_expiration_time": 5,
  "partner_trx_id": "TRX0002"
}`)

  client := &http.Client {
  }
  req, err := http.NewRequest(method, url, payload)

  if err != nil {
    fmt.Println(err)
    return
  }
  req.Header.Add("Content-Type", "application/json")
  req.Header.Add("X-Oy-Username", "{{username}}")
  req.Header.Add("X-Api-Key", "{{api-key}}")

  res, err := client.Do(req)
  if err != nil {
    fmt.Println(err)
    return
  }
  defer res.Body.Close()

  body, err := ioutil.ReadAll(res.Body)
  if err != nil {
    fmt.Println(err)
    return
  }
  fmt.Println(string(body))
}
OkHttpClient client = new OkHttpClient().newBuilder()
  .build();
MediaType mediaType = MediaType.parse("application/json");
RequestBody body = RequestBody.create(mediaType, "{\n\t\"amount\": 50000,\n\t\"username_display\": "test",\n\t\"email\": "email@domain.com",\n\t\"trx_expiration_time\": 5,\n\t\"partner_trx_id\": \"TRX0002\"\n}");
Request request = new Request.Builder()
  .url("{{base_url}}/api/custom-va/2701b82a-89f8-4343-81a2-fa0c92edca09")
  .method("PUT", body)
  .addHeader("Content-Type", "application/json")
  .addHeader("X-Oy-Username", "{{username}}")
  .addHeader("X-Api-Key", "{{api-key}}")
  .build();
Response response = client.newCall(request).execute();
var data = JSON.stringify({
  "amount": 50000,
  "username_display": "test",
  "email": "email@domain.com",
  "trx_expiration_time": 5,
  "partner_trx_id": "TRX0002"
});

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function() {
  if(this.readyState === 4) {
    console.log(this.responseText);
  }
});

xhr.open("PUT", "%7B%7Bbase_url%7D%7D/api/custom-va/2701b82a-89f8-4343-81a2-fa0c92edca09");
xhr.setRequestHeader("Content-Type", "application/json");
xhr.setRequestHeader("X-Oy-Username", "{{username}}");
xhr.setRequestHeader("X-Api-Key", "{{api-key}}");

xhr.send(data);
<?php
require_once 'HTTP/Request2.php';
$request = new HTTP_Request2();
$request->setUrl('{{base_url}}/api/custom-va`/2701b82a-89f8-4343-81a2-fa0c92edca09');
$request->setMethod(HTTP_Request2::METHOD_PUT);
$request->setConfig(array(
  'follow_redirects' => TRUE
));
$request->setHeader(array(
  'Content-Type' => 'application/json',
  'X-Oy-Username' => '{{username}}',
  'X-Api-Key' => '{{api-key}}'
));
$request->setBody('{\n  "amount": 50000,\n  "username_display": "test",\n "email": "email@domain.com",\n  "trx_expiration_time": 5,\n "partner_trx_id": "TRX0002"\n}');
try {
  $response = $request->send();
  if ($response->getStatus() == 200) {
    echo $response->getBody();
  }
  else {
    echo 'Unexpected HTTP status: ' . $response->getStatus() . ' ' .
    $response->getReasonPhrase();
  }
}
catch(HTTP_Request2_Exception $e) {
  echo 'Error: ' . $e->getMessage();
}
import http.client
import json

conn = http.client.HTTPSConnection("{{base_url}}")
payload = json.dumps({
  "amount": 50000,
  "username_display": "test",
  "email": "email@domain.com",
  "trx_expiration_time": 5,
  "partner_trx_id": "TRX0002"
})
headers = {
  'Content-Type': 'application/json',
  'X-Oy-Username': '{{username}}',
  'X-Api-Key': '{{api-key}}'
}
conn.request("PUT", "/api/custom-va/2701b82a-89f8-4343-81a2-fa0c92edca09", payload, headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))

The above command returns JSON structured similar like this:

{
    "id": "1414255-12121-21212121-212121",
    "status": {
        "code": "000",
        "message": "Success"
    },
    "amount": 50000,
    "va_number": "134789181234567890",
    "bank_code": "002",
    "is_open": false,
    "va_status": "WAITING_PAYMENT",
    "username_display": "test",
    "partner_user_id": "12345677",
    "trx_expiration_time": 1582802205412,
    "partner_trx_id": "TRX0002",
}

HTTPS Request

[Production] PUT https://partner.oyindonesia.com/api/custom-va/<ID>
[Staging] PUT https://api-stg.oyindonesia.com/api/custom-va/<ID>

URL Parameter

Parameter Type Required Default Description
ID String(36) TRUE - Unique VA id, you can get this once you have successfully created a customized VA

Request Parameters

Parameter Type Required Default Description
amount BigDecimal FALSE - Amount your user must paid to complete the transaction
username_display String - - Customizable VA display name that will be seen by user, If empty willl be using partner username
email String(255) FALSE - Email of user, using email standard format
trx_expiration_time Long FALSE - Transaction expiration time in minutes, e.g If Transaction want to be expired after 5 minutes, you just have to set expiration_time to 5. If you want to make the trx_expiration_time expired, pass "0" in the trx_expiration_time
partner_trx_id String(255) FALSE - Partner unique Transaction ID of a VA

Response Parameters

Parameter Type Nullable Description
id String FALSE Unique VA id
status Object FALSE Status of response in Object {code: <status_code>, message: <status_message>}
amount BigDecimal FALSE Amount of VA transaction
va_number String(20) FALSE Generated VA number
bank_code String(3) FALSE Bank code for VA, see VA Bank Code
is_open Boolean FALSE True means VA number can accept any amount, False means VA number only accept the specified amount in the field amount
va_status String(16) FALSE Status of VA, see VA Status
username_display String(255) FALSE Customizable VA display name that will be seen by user, If empty willl be using partner username
partner_user_id String(255) FALSE Partner unique ID for specific user
trx_expiration_time Long FALSE Transaction expiration time on Unix timestamp in milliseconds, -1 means no expiration time.
partner_trx_id String(255) TRUE Partner unique Transaction ID of a VA. This parameter will only be sent if end user fill the data in update request parameter

Deactivate Customized VA

Use this API to deactivate an existing customized VA using unique VA id.

curl -X \
DELETE https://partner.oyindonesia.com/api/custom-va/1414255-12121-21212121-212121
-H 'content-type: application/json' \
-H 'accept: application/json' \
-H 'x-oy-username: username' \
-H 'x-api-key: apikey'
var headers = {
  'Content-Type': 'application/json',
  'X-Oy-Username': '{{username}}',
  'X-Api-Key': '{{api_key}}'
};
var request = http.Request('DELETE', Uri.parse('{{base_url}}/api/custom-va/2c26f23d-2dfa-44d1-9202-f8c1f907a983'));

request.headers.addAll(headers);

http.StreamedResponse response = await request.send();

if (response.statusCode == 200) {
  print(await response.stream.bytesToString());
}
else {
  print(response.reasonPhrase);
}
package main

import (
  "fmt"
  "net/http"
  "io/ioutil"
)

func main() {

  url := "%7B%7Bbase_url%7D%7D/api/custom-va/2c26f23d-2dfa-44d1-9202-f8c1f907a983"
  method := "DELETE"

  client := &http.Client {
  }
  req, err := http.NewRequest(method, url, nil)

  if err != nil {
    fmt.Println(err)
    return
  }
  req.Header.Add("Content-Type", "application/json")
  req.Header.Add("X-Oy-Username", "{{username}}")
  req.Header.Add("X-Api-Key", "{{api_key}}")

  res, err := client.Do(req)
  if err != nil {
    fmt.Println(err)
    return
  }
  defer res.Body.Close()

  body, err := ioutil.ReadAll(res.Body)
  if err != nil {
    fmt.Println(err)
    return
  }
  fmt.Println(string(body))
}
OkHttpClient client = new OkHttpClient().newBuilder()
  .build();
Request request = new Request.Builder()
  .url("{{base_url}}/api/custom-va/2c26f23d-2dfa-44d1-9202-f8c1f907a983")
  .method("DELETE", null)
  .addHeader("Content-Type", "application/json")
  .addHeader("X-Oy-Username", "{{username}}")
  .addHeader("X-Api-Key", "{{api_key}}")
  .build();
Response response = client.newCall(request).execute();

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function() {
  if(this.readyState === 4) {
    console.log(this.responseText);
  }
});

xhr.open("DELETE", "%7B%7Bbase_url%7D%7D/api/custom-va/2c26f23d-2dfa-44d1-9202-f8c1f907a983");
xhr.setRequestHeader("Content-Type", "application/json");
xhr.setRequestHeader("X-Oy-Username", "{{username}}");
xhr.setRequestHeader("X-Api-Key", "{{api_key}}");

xhr.send();
<?php
require_once 'HTTP/Request2.php';
$request = new HTTP_Request2();
$request->setUrl('{{base_url}}/api/custom-va/2c26f23d-2dfa-44d1-9202-f8c1f907a983');
$request->setMethod(HTTP_Request2::METHOD_DELETE);
$request->setConfig(array(
  'follow_redirects' => TRUE
));
$request->setHeader(array(
  'Content-Type' => 'application/json',
  'X-Oy-Username' => '{{username}}',
  'X-Api-Key' => '{{api_key}}'
));
try {
  $response = $request->send();
  if ($response->getStatus() == 200) {
    echo $response->getBody();
  }
  else {
    echo 'Unexpected HTTP status: ' . $response->getStatus() . ' ' .
    $response->getReasonPhrase();
  }
}
catch(HTTP_Request2_Exception $e) {
  echo 'Error: ' . $e->getMessage();
}
import http.client
import json

conn = http.client.HTTPSConnection("{{base_url}}")
payload = ''
headers = {
  'Content-Type': 'application/json',
  'X-Oy-Username': '{{username}}',
  'X-Api-Key': '{{api_key}}'
}
conn.request("DELETE", "/api/custom-va/2c26f23d-2dfa-44d1-9202-f8c1f907a983", payload, headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))

The above command returns JSON structured similar like this:

{
    "status": {
        "code": "000",
        "message": "Success"
    }
}

HTTPS Request

[Production] DELETE https://partner.oyindonesia.com/api/custom-va/<ID>
[Staging] DELETE https://api-stg.oyindonesia.com/api/custom-va/<ID>

URL Parameters

Parameter Type Required Default Description
ID String(255) TRUE - Unique VA id, you can get this once you have successfully created a customized VA

Response Parameters

Parameter Type Nullable Description
status Object FALSE Status of response in Object {code: <status_code>, message: <status_message>}

Partner Callback Va Aggregator

Response callback:

{
    "va_number": "1234567",
    "amount": 100000,
    "partner_user_id": "oy0000000001",
    "success": true,
    "tx_date": "31/01/2020T01:01:01.000+0000",
    "username_display": "VA Name",
    "trx_expiration_date": "31/01/2020T01:01:01.000+0000",
    "partner_trx_id": "TRX0002",
    "trx_id": "12345-12345-12453-12455",
    "settlement_time": "01/02/2020T15:00:00.000+0000",
    "settlement_status": "WAITING"
}

Once user successfully do the payment, our system will make a callback via HTTP POST request to your system

Callback Parameters

Parameter Type Nullable Description
va_number String(20) FALSE Generated VA number
amount BigDecimal FALSE Amount of VA transaction
partner_user_id String(255) FALSE Unique ID provided by partner for specific user
success boolean FALSE The status of the payment and it is always set to SUCCESS
tx_date Timestamp FALSE Incoming payment transaction date, format dd/MM/yyyy'T'HH:mm:ss.SSSZZZZ
username_display String(255) FALSE Customizable VA display name that will be seen by user. If partner did not provide the value on creation VA, then it will be using partner’s username
trx_expiration_date Long TRUE Transaction expiration date, format dd/MM/yyyy'T'HH:mm:ss.SSSZZZZ. For VA Lifetime, the value of this parameter will be null/empty
partner_trx_id String(255) TRUE Unique Transaction ID provided by partner on creation or update VA. This parameter will be empty if partner leave this parameter empty when creating or updating the VA
trx_id String (255) FALSE Unique ID of incoming payment
settlement_time Timestamp FALSE The timestamp (in UTC+7) indicating when the fund will be settled to partner’s account statement, format dd/MM/yyyy'T'HH:mm:ss.SSSZZZZ
settlement_status String(255) FALSE The status of the settlement
full_name String(255) TRUE If full_name is needed when creating the transaction, the inputted full_name value at creation will be shown here

VA aggregator Bank Code

Available Bank for VA aggregator

Bank (Virtual Account) Bank Code Open & Closed Amount Capability Lifetime Capability Maximum Expiration Time
BNI 009 Closed Amount Supported -
Bank Mandiri 008 Open Amount, Closed Amount Supported -
BRI O02 Open Amount, Closed Amount Supported -
BCA 014 Open Amount, Closed Amount Supported -
Bank Permata/Permata Syariah 013 Open Amount, Closed Amount Supported -
CIMB Niaga/CIMB Niaga Syariah 022 Open Amount, Closed Amount Supported -
BTPN 213 Open Amount, Closed Amount Supported -
BSI (Bank Syariah Indonesia) 451 Closed Amount Not Supported 99999 minutes

For all available banks, there is no minimum expiration time.

List of Documents

To enable VA Bank BCA, we need partner to send documents using email, directly to our business representative.

Common Documents

No Document
1 Taxpayer Registration Number
2 National ID

Documents for Foundation, or Donation Partner

No Documents
1 Akta Pendirian Perusahaan
2 Keputusan Dewan Pembina Yayasan
3 Persetujuan Menhumham
4 Taxpayer Registration Number Organization
5 Izin Usaha
6 Surat Keterangan Domisili
7 Sertifikat Yayasan

Documents for Other Company

No Documents
1 Trade Business License
2 Company's Deed
3 Company Registration Certificate
4 Decree of Minister Justine and Human Right

VA aggregator Status

Available Status for VA aggregator

Status Description
WAITING_PAYMENT This status means that VA is active and can receive a payment
PAYMENT_DETECTED This status means that there are incoming payment to VA Number
EXPIRED This status means that VA is expired. You cannot accept or make update to VA Number with this status.
STATIC_TRX_EXPIRED This status means that Transaction is expired. If VA have a unlimited lifetime, you can create a new transaction using update va info.
COMPLETE This status means that VA is closed/complete after get incoming payment. You cannot accept or make update to VA Number with this status. Only Static VA with attribute is_single_use true can have this status.

VA Aggregator Response Codes

Below is the list of response codes for API VA aggregator:

Response Code State Description
000 Final Response success without error
203 Final Request is Rejected (Duplicate partner tx id)
207 Final Request is Rejected (Request IP address is not registered)
208 Final Request is Rejected (API key is not valid)
211 Final Request is Rejected (Bank code is not available for this service)
212 Final Request is Rejected (Given amount are lesser than allowed value for static VA)
213 Final Request is Rejected (Given amount are greater than allowed value for static VA)
214 Final Request is Rejected (Failed to generate static VA)
214 Final Request is Rejected (Amount type is not supported for the requested bank code)
216 Final Request is Rejected (VA id is empty)
217 Final Request is Rejected (VA number is still active for this partner user id)
219 Final Request is Rejected (Virtual account is not enabled for this bank)
219 Final Request is Rejected (Virtual account for this bank has reached daily limit transaction)
226 Final Request is rejected (Transaction expiry time exceeds VA expiry time)
245 Final Request is rejected (Minimum expiry time is 10 minutes for VA CIMB and Permata)
246 Final Request is rejected (Failed update VA)
260 Final Request is rejected (Given VA suffix is invalid)
262 Final Request is rejected (VA prefix for this username is not available)
999 Non-Final Internal Server Error

IMPORTANT! The following response codes mean that your request is not received by OY! and do not represent any information related to your transaction activity/status:

Response Code Description
201 Request is Rejected (User ID is not found)
202 Request is Rejected (User ID is not active)
202 Request is Rejected (Multiple use VA is not allowed for use)
202 Request is Rejected (Custom VA is not allowed for use)
990 Request is Rejected (Field full_name and email is required)
990 Request is Rejected (Field full_name/email is invalid)
990 Request is Rejected (Invalid Format)

Below is the list of HTTP Status Code for API VA Aggregator:

HTTP Status Code Description
403 Forbidden (IP address is not whitelisted or request is deemed suspicious e.g SQL injection or XSS)
404 Not Found (wrong URL)
429 Request Rejected (Too Many Request to specific endpoint)
500 Internal Server Error (OY! system encountered unknown error)
503 Service Unavailable (OY! system is unable to process the request temporarily)
504 Gateway Timeout (OY! system took too long processing the request and was unable to respond in time)

Fund Acceptance

There are two products that fall under the category of funds acceptance which are Payment Link and Invoicing.

Payment Link product will allow you to receive funds from your customers by choosing from our various payment channels such as bank transfer or cards.

Similarly, Invoicing will let you to bill your customers for service/items purchased by sending a payment link to your customer's email by attatching/creating an invoice via our API.

All payment link and/or details can be monitored by using our dashboard and various API endpoints.

An endpoint to create payment link URL which return parameters by encapsulation.

curl -X POST \
  https://partner.oyindonesia.com/api/payment-checkout/create-v2 \
  -H 'cache-control: no-cache' \
  -H 'content-type: application/json' \
  -H 'X-Api-Key: apikeymu' \
  -H 'X-Oy-Username: yourusername' \
  -d '{
        "partner_tx_id":"partnerTxId",
        "child_balance":"child123",
        "description":"description",
        "notes":"notes",
        "sender_name":"Sender name",
        "amount":50000,
        "email":"johndoe@gmail.com;jane@gmail.com",
        "phone_number":"",
        "is_open":false,
        "include_admin_fee":false,
        "list_disabled_payment_methods":"",
        "list_enabled_banks":"",
        "expiration":"2020-08-08 08:09:12",
        "va_display_name":"Display Name on VA"
    }'
var headers = {
  'Content-Type': 'application/json',
  'x-oy-username': '{{username}}',
  'x-api-key': '{{api-key}}'
};
var request = http.Request('POST', Uri.parse('{{base_url}}/api/payment-checkout/create-v2'));
request.body = json.encode({
  "description": "Prod Test API",
  "partner_tx_id": "",
  "child_balance":"child123",
  "notes": "",
  "sender_name": "Mochamad Suryono",
  "amount": 10000,
  "email": "johndoe@gmail.com;jane@gmail.com",
  "phone_number": "085712163208",
  "is_open": true,
  "include_admin_fee": true,
  "list_disabled_payment_methods": "",
  "list_enabled_banks": "002, 008, 009, 013, 022",
  "list_enabled_ewallet": "shopeepay_ewallet",
  "expiration": "2021-06-14 13:00:00"
});
request.headers.addAll(headers);

http.StreamedResponse response = await request.send();

if (response.statusCode == 200) {
  print(await response.stream.bytesToString());
}
else {
  print(response.reasonPhrase);
}
package main

import (
  "fmt"
  "strings"
  "net/http"
  "io/ioutil"
)

func main() {

  url := "%7B%7Bbase_url%7D%7D/api/payment-checkout/create-v2"
  method := "POST"

  payload := strings.NewReader(`{
    "description": "Prod Test API",
    "partner_tx_id": "",
    "child_balance":"child123",
    "notes": "",
    "sender_name" : "Mochamad Suryono", 
    "amount" : 10000,
    "email": "johndoe@gmail.com;jane@gmail.com",
    "phone_number": "085712163208", 
    "is_open" : true,
    "include_admin_fee" : true,
    "list_disabled_payment_methods": "",
    "list_enabled_banks": "002, 008, 009, 013, 022",
    "list_enabled_ewallet": "shopeepay_ewallet",
    "expiration": "2021-06-14 13:00:00"
}`)

  client := &http.Client {
  }
  req, err := http.NewRequest(method, url, payload)

  if err != nil {
    fmt.Println(err)
    return
  }
  req.Header.Add("Content-Type", "application/json")
  req.Header.Add("x-oy-username", "{{username}}")
  req.Header.Add("x-api-key", "{{api-key}}")

  res, err := client.Do(req)
  if err != nil {
    fmt.Println(err)
    return
  }
  defer res.Body.Close()

  body, err := ioutil.ReadAll(res.Body)
  if err != nil {
    fmt.Println(err)
    return
  }
  fmt.Println(string(body))
}
OkHttpClient client = new OkHttpClient().newBuilder()
  .build();
MediaType mediaType = MediaType.parse("application/json");
RequestBody body = RequestBody.create(mediaType, "{\n    \"description\": \"Prod Test API\",\n    \"partner_tx_id\": \"\",\n    \"notes\": \"\",\n    \"sender_name\" : \"Mochamad Suryono\", \n    \"amount\" : 10000,\n    \"email\": \"johndoe@gmail.com;jane@gmail.com\",\n    \"phone_number\": \"085712163208\", \n    \"is_open\" : true,\n    \"include_admin_fee\" : true,\n    \"list_disabled_payment_methods\": \"\",\n    \"list_enabled_banks\": \"002, 008, 009, 013, 022\",\n    \"list_enabled_ewallet\": \"shopeepay_ewallet\",\n    \"expiration\": \"2021-06-14 13:00:00\"\n}");
Request request = new Request.Builder()
  .url("{{base_url}}/api/payment-checkout/create-v2")
  .method("POST", body)
  .addHeader("Content-Type", "application/json")
  .addHeader("x-oy-username", "{{username}}")
  .addHeader("x-api-key", "{{api-key}}")
  .build();
Response response = client.newCall(request).execute();
var data = JSON.stringify({
  "description": "Prod Test API",
  "partner_tx_id": "",
  "child_balance":"child123",
  "notes": "",
  "sender_name": "Mochamad Suryono",
  "amount": 10000,
  "email": "johndoe@gmail.com;jane@gmail.com",
  "phone_number": "085712163208",
  "is_open": true,
  "include_admin_fee": true,
  "list_disabled_payment_methods": "",
  "list_enabled_banks": "002, 008, 009, 013, 022",
  "list_enabled_ewallet": "shopeepay_ewallet",
  "expiration": "2021-06-14 13:00:00"
});

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function() {
  if(this.readyState === 4) {
    console.log(this.responseText);
  }
});

xhr.open("POST", "%7B%7Bbase_url%7D%7D/api/payment-checkout/create-v2");
xhr.setRequestHeader("Content-Type", "application/json");
xhr.setRequestHeader("x-oy-username", "{{username}}");
xhr.setRequestHeader("x-api-key", "{{api-key}}");

xhr.send(data);
<?php
require_once 'HTTP/Request2.php';
$request = new HTTP_Request2();
$request->setUrl('{{base_url}}/api/payment-checkout/create-v2');
$request->setMethod(HTTP_Request2::METHOD_POST);
$request->setConfig(array(
  'follow_redirects' => TRUE
));
$request->setHeader(array(
  'Content-Type' => 'application/json',
  'x-oy-username' => '{{username}}',
  'x-api-key' => '{{api-key}}'
));
$request->setBody('{\n    "description": "Prod Test API",\n    "partner_tx_id": "",\n    "notes": "",\n    "sender_name" : "Mochamad Suryono", \n    "amount" : 10000,\n    "email": "johndoe@gmail.com;jane@gmail.com",\n    "phone_number": "085712163208", \n    "is_open" : true,\n    "include_admin_fee" : true,\n    "list_disabled_payment_methods": "",\n    "list_enabled_banks": "002, 008, 009, 013, 022",\n    "list_enabled_ewallet": "shopeepay_ewallet",\n    "expiration": "2021-06-14 13:00:00"\n}');
try {
  $response = $request->send();
  if ($response->getStatus() == 200) {
    echo $response->getBody();
  }
  else {
    echo 'Unexpected HTTP status: ' . $response->getStatus() . ' ' .
    $response->getReasonPhrase();
  }
}
catch(HTTP_Request2_Exception $e) {
  echo 'Error: ' . $e->getMessage();
}
import http.client
import json

conn = http.client.HTTPSConnection("{{base_url}}")
payload = json.dumps({
  "description": "Prod Test API",
  "partner_tx_id": "",
  "child_balance":"child123",
  "notes": "",
  "sender_name": "Mochamad Suryono",
  "amount": 10000,
  "email": "business.support@oyindonesia.com",
  "phone_number": "085712163208",
  "is_open": True,
  "include_admin_fee": True,
  "list_disabled_payment_methods": "",
  "list_enabled_banks": "002, 008, 009, 013, 022",
  "list_enabled_ewallet": "shopeepay_ewallet",
  "expiration": "2021-06-14 13:00:00"
})
headers = {
  'Content-Type': 'application/json',
  'x-oy-username': '{{username}}',
  'x-api-key': '{{api-key}}'
}
conn.request("POST", "/api/payment-checkout/create-v2", payload, headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))

[Production] POST https://partner.oyindonesia.com/api/payment-checkout/create-v2
[Staging] POST https://api-stg.oyindonesia.com/api/payment-checkout/create-v2

Json Response

{
        "status": true,
        "url": "https://pay.oyindonesia.com/id",
        "message": "success",
        "email_status": "PROCESSED",
        "payment_link_id": "id"
        "child_balance":"child123",
}
Parameters Type Description
X-Api-Key String API Key for establishing connection to this particular endpoint
X-Oy-Username String The registered partner's username with enabled access for payment link product
Parameters Type Required Description Limitation
partner_tx_id String FALSE A unique transaction ID provided by partner. A partner_tx_id that has been succesfully paid cannot be used anymore under the same username and only accepts alphanumerics. If empty then OY will generate automatically.
child_balance String FALSE An optional parameter. Applicable for MAM transaction. Fill this with the username of your child account if you want to create a transaction on behalf of the child (the payment will go to the child account's balance)
description String FALSE Description of the payment link. Only accepts alphabets (A-Z), numeric (0-9) and space as input.
notes String FALSE Notes. Only accepts alphabets (A-Z), numeric (0-9) and space as input.
sender_name String TRUE Name of the payer for a transaction. Only accepts alphabets (A-Z) and space as input and cannot be empty.
amount Integer TRUE The amount of a transaction to be paid. The amount of a transaction to be paid, min. amount is 10000, except if you use unique code BCA which has min. amount 11000 or CARDS which has min. amount 15000
email String FALSE The email addresses where the payment link will be sent to. Up to 3 emails separated by ";"
phone_number Numeric FALSE Phone number of the payer for a transaction. Do not use special character (e.g. "+")
is_open Boolean TRUE Enable open/closed amount transaction method. If is_open = TRUE and the amount parameter is defined, then a payer can pay any amount (greater than IDR 10,000) up to the defined amount. And in the case that is_open=false, then the amount and partner_tx_id parameters must be defined.
include_admin_fee Boolean TRUE Admin fee will be added to the specified amount or amount inputted by user if this parameter is set as TRUE. -
list_disabled_payment_methods String FALSE To configure payment methods to be disabled (e.g. VA, CREDIT_CARD, QRIS, EWALLET, BANK_TRANSFER). When BANK_TRANSFER is included, you are disabling both VA and Unique Code. When CREDIT_CARD is included, you are disabling the ‘cards’ payment method as a whole - which means disabling both credit card and debit card. There must be at least 1 payment method enabled. If this field is not included in the request, or filled with an empty String, then all payment methods will be enabled.
list_enabled_banks String TRUE To configure banks to be enabled for BANK_TRANSFER payment method. List of eligible bank codes: "002" (BRI), "008" (Mandiri), "009" (BNI), "013" (Permata), "022" (CIMB), "213" (BTPN), "213" (BSI), and "014" (BCA). Unique code is only available for BCA.
list_enabled_ewallet String TRUE To configure list of e-wallets to be enabled on payment method page. List of eligible e-wallet: "shopeepay_ewallet", "dana_ewallet", "linkaja_ewallet", "ovo_ewallet".
expiration datetime FALSE To set the expiration of the payment link (yyyy-MM-dd HH:mm:ss) Expiration date will be defaulted to 24 hours if it is not defined.
va_display_name String FALSE Optional parameter, name to display on Bank Transfer VA Name Can be omitted. Accepts alphabets (A-Z), numeric (0-9) and space as input.
Parameter Type Nullable Description
status Boolean FALSE true / false
url String TRUE Payment link which used for payment. Only filled if payment checkout successfully created.
payment_link_id String TRUE A unique transaction ID provided by partner. Only filled if payment checkout successfully created.
child_balance String TRUE Applicable for MAM transaction. To be filled with the username of child account. If you do not pass the parameter in request, we will not pass this parameter in response. Only applicable for MAM transaction.
message String FALSE Message response
email_status String TRUE email status. Only filled if payment checkout successfully created.

API Create (Invoicing)

Our Invoicing product is leveraging most parameters that are defined for our payment link in the above section with some additional parameters that are only applicable for Inovicing product.

curl -X POST \
  https://partner.oyindonesia.com/api/payment-checkout/create-invoice\
  -H 'cache-control: no-cache' \
  -H 'content-type: application/json' \
  -H 'X-Api-key: apikeymu' \
  -H 'X-Oy-Username: yourusername' \
  -d '{
        "partner_tx_id":"partner tx id",
        "description":"desc invoice",
        "notes":"notes satu",
        "sender_name":"Sender Name API",
        "amount":"30000",
        "email":"",
        "phone_number":"",
        "is_open":"true",
        "include_admin_fee":false,
        "list_disabled_payment_methods":"",
        "list_enabled_banks":"013",
        "expiration":"2020-07-28 19:15:13",
        "due_date":"2020-07-28 18:00:00",
        "partner_user_id":"partner user id", 
        "full_name" : "Raymond",
        "is_va_lifetime": false,
        "attachment": "JVBERi0xLjQNJeLjz9MNCjYgMCBvYmogPDwvTGluZWFyaXplZCAxL0wgNzcxMjMvTyA4L0UgNzI5MDcvTiAxL1QgNzY5NTcvSCBbIDg5NiAyMDNdPj4NZW5kb2JqDSAgICAgICAgICAgICAgICAgICAgDQp4cmVmDQo2IDMwDQowMDAwMDAwMDE2IDAwMDAwIG4NCjAwMDAwMDEwOTkgMDAwMDAgbg0KMDAwMDAwMTE3NSAwMDAwMCBuDQowMDAwMDAxMzU3IDAwMDAwIG4NCjAwMDAwMDE0NzMgMDAwMDAgbg0KMDAwMDAwMTYwNyAwMDAwMCBuDQowMDAwMDAxODkwIDAwMDAwIG4NCjAwMDAwMDIwMTkgMDAwMDAgbg0KMDAwMDAwMjM5NSAwMDAwMCBuDQowMDAwMDAzNDU1IDAwMDAwIG4NCjAwMDAwMDQ0NzEgMDAwMDAgbg0KMDAwMDAwNTM1MSAwMDAwMCBuDQowMDAwMDA2MzMzIDAwMDAwIG4NCjAwMDAwMDczOTkgMDAwMDAgbg0KMDAwMDAwODM4NCAwMDAwMCBuDQowMDAwMDA5NDEwIDAwMDAwIG4NCjAwMDAwMTA0MTYgMDAwMDAgbg0KMDAwMDAyMjY0OCAwMDAwMCBuDQowMDAwMDIyOTAwIDAwMDAwIG4NCjAwMDAwMjMwODYgMDAwMDAgbg0KMDAwMDAyMzM3MCAwMDAwMCBuDQowMDAwMDM3OTgxIDAwMDAwIG4NCjAwMDAwMzgyMzQgMDAwMDAgbg0KMDAwMDA1MTU1NiAwMDAwMCBuDQowMDAwMDUxODAyIDAwMDAwIG4NCjAwMDAwNTE5ODMgMDAwMDAgbg0KMDAwMDA1MjI2OCAwMDAwMCBuDQowMDAwMDcyNTg0IDAwMDAwIG4NCjAwMDAwNzI4MzEgMDAwMDAgbg0KMDAwMDAwMDg5NiAwMDAwMCBuDQp0cmFpbGVyDQo8PC9TaXplIDM2L1ByZXYgNzY5NDcvUm9vdCA3IDAgUi9JbmZvIDUgMCBSL0lEWzw2Q0UwNTExNkQxMzc1QUFCMkEyRDgxMzU5QjQ3MUM2QT48N0E5OUJEMjY4NTM3MEM0MEI1ODU3QTk5NTMzNUEzRDc+XT4+DQpzdGFydHhyZWYNCjANCiUlRU9GDQogICAgICAgICAgICAgICAgDQozNSAw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ZW5kb2JqDTEgMCBvYmo8PC9OdW1zWzAgMiAwIFJdPj4NZW5kb2JqDTIgMCBvYmo8PC9TL0Q+Pg1lbmRvYmoNMyAwIG9iajw8L0NvdW50IDEvVHlwZS9QYWdlcy9LaWRzWzggMCBSXT4+DWVuZG9iag00IDAgb2JqPDwvU3VidHlwZS9YTUwvTGVuZ3RoIDM2MjIvVHlwZS9NZXRhZGF0YT4+c3RyZWFtDQo8P3hwYWNrZXQgYmVnaW49Iu+7vyIgaWQ9Ilc1TTBNcENlaGlIenJlU3pOVGN6a2M5ZCI/Pgo8eDp4bXBtZXRhIHhtbG5zOng9ImFkb2JlOm5zOm1ldGEvIiB4OnhtcHRrPSIzLjEtNzAyIj4KICAgPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICAgICAgPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIKICAgICAgICAgICAgeG1sbnM6cGRmPSJodHRwOi8vbnMuYWRvYmUuY29tL3BkZi8xLjMvIj4KICAgICAgICAgPHBkZjpQcm9kdWNlcj5BY3JvYmF0IERpc3RpbGxlciA3LjAuNSAoV2luZG93cyk8L3BkZjpQcm9kdWNlcj4KICAgICAgPC9yZGY6RGVzY3JpcHRpb24+CiAgICAgIDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiCiAgICAgICAgICAgIHhtbG5zOnhhcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyI+CiAgICAgICAgIDx4YXA6Q3JlYXRvclRvb2w+UFNjcmlwdDUuZGxsIFZlcnNpb24gNS4yPC94YXA6Q3JlYXRvclRvb2w+CiAgICAgICAgIDx4YXA6TW9kaWZ5RGF0ZT4yMDEwLTAzLTA0VDEzOjA4OjM3KzAxOjAwPC94YXA6TW9kaWZ5RGF0ZT4KICAgICAgICAgPHhhcDpDcmVhdGVEYXRlPjIwMTAtMDMtMDRUMTM6MDgrMDE6MDA8L3hhcDpDcmVhdGVEYXRlPgogICAgICAgICA8eGFwOk1ldGFkYXRhRGF0ZT4yMDEwLTAzLTA0VDEzOjA4OjM3KzAxOjAwPC94YXA6TWV0YWRhdGFEYXRlPgogICAgICA8L3JkZjpEZXNjcmlwdGlvbj4KICAgICAgPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIKICAgICAgICAgICAgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIj4KICAgICAgICAgPGRjOmZvcm1hdD5hcHBsaWNhdGlvbi9wZGY8L2RjOmZvcm1hdD4KICAgICAgICAgPGRjOnRpdGxlPgogICAgICAgICAgICA8cmRmOkFsdD4KICAgICAgICAgICAgICAgPHJkZjpsaSB4bWw6bGFuZz0ieC1kZWZhdWx0Ij5NaWNyb3NvZnQgV29yZCAtIFRlc3QgZG9jdW1lbnQgV29yZC5kb2M8L3JkZjpsaT4KICAgICAgICAgICAgPC9yZGY6QWx0PgogICAgICAgICA8L2RjOnRpdGxlPgogICAgICAgICA8ZGM6Y3JlYXRvcj4KICAgICAgICAgICAgPHJkZjpTZXE+CiAgICAgICAgICAgICAgIDxyZGY6bGk+bWFuc2hhbmRlbjwvcmRmOmxpPgogICAgICAgICAgICA8L3JkZjpTZXE+CiAgICAgICAgIDwvZGM6Y3JlYXRvcj4KICAgICAgPC9yZGY6RGVzY3JpcHRpb24+CiAgICAgIDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiCiAgICAgICAgICAgIHhtbG5zOnhhcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIj4KICAgICAgICAgPHhhcE1NOkRvY3VtZW50SUQ+dXVpZDowN2QwZjBmMC1jMDFmLTRhNjQtOTIzOC03OTdkOGE1MmY3MGM8L3hhcE1NOkRvY3VtZW50SUQ+CiAgICAgICAgIDx4YXBNTTpJbnN0YW5jZUlEPnV1aWQ6ODU0ZjczN2MtN2NiYi00ODc3LTljMWQtZDljYmE4NzA1NTk5PC94YXBNTTpJbnN0YW5jZUlEPgogICAgICA8L3JkZjpEZXNjcmlwdGlvbj4KICAgPC9yZGY6UkRGPgo8L3g6eG1wbWV0YT4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgIAo8P3hwYWNrZXQgZW5kPSJ3Ij8+DQplbmRzdHJlYW0NZW5kb2JqDTUgMCBvYmo8PC9DcmVhdGlvbkRhdGUoRDoyMDEwMDMwNDEzMDgwMCswMScwMCcpL0F1dGhvcihtYW5zaGFuZGVuKS9DcmVhdG9yKFBTY3JpcHQ1LmRsbCBWZXJzaW9uIDUuMikvUHJvZHVjZXIoQWNyb2JhdCBEaXN0aWxsZXIgNy4wLjUgXChXaW5kb3dzXCkpL01vZERhdGUoRDoyMDEwMDMwNDEzMDgzNyswMScwMCcpL1RpdGxlKE1pY3Jvc29mdCBXb3JkIC0gVGVzdCBkb2N1bWVudCBXb3JkLmRvYyk+Pg1lbmRvYmoNeHJlZg0KMCA2DQowMDAwMDAwMDAwIDY1NTM1IGYNCjAwMDAwNzI5MDcgMDAwMDAgbg0KMDAwMDA3Mjk0MCAwMDAwMCBuDQowMDAwMDcyOTYzIDAwMDAwIG4NCjAwMDAwNzMwMTMgMDAwMDAgbg0KMDAwMDA3NjcxMSAwMDAwMCBuDQp0cmFpbGVyDQo8PC9TaXplIDY+Pg0Kc3RhcnR4cmVmDQoxMTYNCiUlRU9GDQo=",
        "invoice_items": [
          {
            "item":"item name", 
            "description":"description", 
            "quantity": 10, 
            "date_of_purchase":"2020-09-20", 
            "price_per_item": 33000  
          }
        ]
    }'
var headers = {
  'Content-Type': 'application/json',
  'x-oy-username': '{{username}}',
  'x-api-key': '{{api-key}}'
};
var request = http.Request('POST', Uri.parse('{{base_url}}/api/payment-checkout/create-invoice'));
request.body = json.encode({
  "description": "testdesc",
  "notes": "testnote",
  "partner_tx_id": "ab9c",
  "sender_name": "Mochamad Suryono",
  "amount": "15000",
  "email": "business.support@oyindonesia.com",
  "phone_number": "085712163208",
  "is_open": true,
  "include_admin_fee": false,
  "list_disabled_payment_methods": "",
  "list_enabled_banks": "002, 008, 009, 013, 022",
  "expiration": "2021-03-13 00:00:00",
  "due_date": "2021-03-12 12:00:00",
  "partner_user_id": "OYON-CHECKOUT000003",
  "full_name": "Mochamad Suryono",
  "is_va_lifetime": false,
  "attachment": "JVBERi0xLjQKJeLjz9MKMyAwIG9iago8PC9GaWx0ZXIvRmxhdGVEZWNvZGUvTGVuZ3RoIDQ5Nj4+c3RyZWFtCnicrZVdb9MwFIbv/SsOd51EwrHjz0tKhxQk2IciJMS4CG46lbVNyYcE/HqcbNloh5xO8U3OUXJ8Hr/2aweBQkQBQRjhnnZLfpJ5RhIJQhjIluQ8I1eEwYfubVeHMFRnW/LmPQWKkK3I7Cz70dU+lfTN/hnE3ChJY9SPA0U3EPvP1S2ZXXx5Bemnzxfpu/OuGcLtfxp+/ebisp+QH8VkrNjhHJ9QaV23xRKyciKIGuCGjYPmv6cq0idKWuRNEYDlV7VoixAgwcdEXeZVsysqyH5BughA88t6uy3bXQNO3XRbCEq9pKr8sw5gPuXT8zGv7/JNCOeh9mAYMoxQRcyEMJ5KRlEmokkI63lVrSgqi8JEWlsV8ZURkRFMR1pILkVuZcJYCEd69V7vY3eZxYj4GvEkGsaMK5SAMTcauYsKje6aObskUsGWaKr7bPOYHUd7/8XIocZlx9H2DfuSh+Qw2AG4GZLDYMlqmLfHEQIS/XyBaOf++5uoqG213jfrcjfVfAYdi/tY0288noxBrpqpvwoh1AjjslrbqUo6j/kpWdnkG7iZpYvrm7MQmyOe045vBhkhDbFFI6gTz6Jvj9zqCd+frz/5MRMvOvyeBUxGRM3bvIHvRZXvmryGu7Jq901ZhTDJqEweC+xlvkTqX6+ILeYKZW5kc3RyZWFtCmVuZG9iagoxIDAgb2JqCjw8L1RhYnMvUy9Hcm91cDw8L1MvVHJhbnNwYXJlbmN5L1R5cGUvR3JvdXAvQ1MvRGV2aWNlUkdCPj4vQ29udGVudHMgMyAwIFIvVHlwZS9QYWdlL1Jlc291cmNlczw8L0NvbG9yU3BhY2U8PC9DUy9EZXZpY2VSR0I+Pi9Qcm9jU2V0IFsvUERGIC9UZXh0IC9JbWFnZUIgL0ltYWdlQyAvSW1hZ2VJXS9Gb250PDwvRjEgMiAwIFI+Pj4+L1BhcmVudCA0IDAgUi9Sb3RhdGUgOTAvTWVkaWFCb3hbMCAwIDU5NSA4NDJdPj4KZW5kb2JqCjUgMCBvYmoKWzEgMCBSL1hZWiAwIDYwNSAwXQplbmRvYmoKMiAwIG9iago8PC9TdWJ0eXBlL1R5cGUxL1R5cGUvRm9udC9CYXNlRm9udC9IZWx2ZXRpY2EvRW5jb2RpbmcvV2luQW5zaUVuY29kaW5nPj4KZW5kb2JqCjQgMCBvYmoKPDwvS2lkc1sxIDAgUl0vVHlwZS9QYWdlcy9Db3VudCAxL0lUWFQoMi4xLjcpPj4KZW5kb2JqCjYgMCBvYmoKPDwvTmFtZXNbKEpSX1BBR0VfQU5DSE9SXzBfMSkgNSAwIFJdPj4KZW5kb2JqCjcgMCBvYmoKPDwvRGVzdHMgNiAwIFI+PgplbmRvYmoKOCAwIG9iago8PC9OYW1lcyA3IDAgUi9UeXBlL0NhdGFsb2cvUGFnZXMgNCAwIFIvVmlld2VyUHJlZmVyZW5jZXM8PC9QcmludFNjYWxpbmcvQXBwRGVmYXVsdD4+Pj4KZW5kb2JqCjkgMCBvYmoKPDwvTW9kRGF0ZShEOjIwMjAwNzI5MTE1MzE1WikvQ3JlYXRvcihKYXNwZXJSZXBvcnRzIExpYnJhcnkgdmVyc2lvbiBudWxsKS9DcmVhdGlvbkRhdGUoRDoyMDIwMDcyOTExNTMxNVopL1Byb2R1Y2VyKGlUZXh0IDIuMS43IGJ5IDFUM1hUKT4+CmVuZG9iagp4cmVmCjAgMTAKMDAwMDAwMDAwMCA2NTUzNSBmIAowMDAwMDAwNTc4IDAwMDAwIG4gCjAwMDAwMDA4NjQgMDAwMDAgbiAKMDAwMDAwMDAxNSAwMDAwMCBuIAowMDAwMDAwOTUyIDAwMDAwIG4gCjAwMDAwMDA4MjkgMDAwMDAgbiAKMDAwMDAwMTAxNSAwMDAwMCBuIAowMDAwMDAxMDY5IDAwMDAwIG4gCjAwMDAwMDExMDEgMDAwMDAgbiAKMDAwMDAwMTIwNCAwMDAwMCBuIAp0cmFpbGVyCjw8L0luZm8gOSAwIFIvSUQgWzwzZWMyMWUyNjkwNjcxYzViYTliNjUxODNhY2IxOTM3ND48NzZhNzM1MWE1YmY4ZmMxNDNmY2NlZmUwYjRjMzA4MWI+XS9Sb290IDggMCBSL1NpemUgMTA+PgpzdGFydHhyZWYKMTM1OAolJUVPRgo=",
  "invoice_items": [
    {
      "item": "McDonald's Big Mac",
      "description": "Oyon Meals",
      "quantity": 3,
      "date_of_purchase": "2021-03-12",
      "price_per_item": 50000
    }
  ]
});
request.headers.addAll(headers);

http.StreamedResponse response = await request.send();

if (response.statusCode == 200) {
  print(await response.stream.bytesToString());
}
else {
  print(response.reasonPhrase);
}

package main

import (
  "fmt"
  "strings"
  "net/http"
  "io/ioutil"
)

func main() {

  url := "%7B%7Bbase_url%7D%7D/api/payment-checkout/create-invoice"
  method := "POST"

  payload := strings.NewReader(`{
    "description": "testdesc",
    "notes": "testnote",
    "partner_tx_id": "ab9c",
    "sender_name" : "Mochamad Suryono", 
    "amount" : "15000",
    "email": "business.support@oyindonesia.com",
    "phone_number": "085712163208", 
    "is_open" : true,
    "include_admin_fee" : false,
    "list_disabled_payment_methods": "",
    "list_enabled_banks": "002, 008, 009, 013, 022",
    "expiration": "2021-03-13 00:00:00",
    "due_date": "2021-03-12 12:00:00",
    "partner_user_id": "OYON-CHECKOUT000003",
    "full_name": "Mochamad Suryono",
    "is_va_lifetime": false,
    "attachment": "JVBERi0xLjQKJeLjz9MKMyAwIG9iago8PC9GaWx0ZXIvRmxhdGVEZWNvZGUvTGVuZ3RoIDQ5Nj4+c3RyZWFtCnicrZVdb9MwFIbv/SsOd51EwrHjz0tKhxQk2IciJMS4CG46lbVNyYcE/HqcbNloh5xO8U3OUXJ8Hr/2aweBQkQBQRjhnnZLfpJ5RhIJQhjIluQ8I1eEwYfubVeHMFRnW/LmPQWKkK3I7Cz70dU+lfTN/hnE3ChJY9SPA0U3EPvP1S2ZXXx5Bemnzxfpu/OuGcLtfxp+/ebisp+QH8VkrNjhHJ9QaV23xRKyciKIGuCGjYPmv6cq0idKWuRNEYDlV7VoixAgwcdEXeZVsysqyH5BughA88t6uy3bXQNO3XRbCEq9pKr8sw5gPuXT8zGv7/JNCOeh9mAYMoxQRcyEMJ5KRlEmokkI63lVrSgqi8JEWlsV8ZURkRFMR1pILkVuZcJYCEd69V7vY3eZxYj4GvEkGsaMK5SAMTcauYsKje6aObskUsGWaKr7bPOYHUd7/8XIocZlx9H2DfuSh+Qw2AG4GZLDYMlqmLfHEQIS/XyBaOf++5uoqG213jfrcjfVfAYdi/tY0288noxBrpqpvwoh1AjjslrbqUo6j/kpWdnkG7iZpYvrm7MQmyOe045vBhkhDbFFI6gTz6Jvj9zqCd+frz/5MRMvOvyeBUxGRM3bvIHvRZXvmryGu7Jq901ZhTDJqEweC+xlvkTqX6+ILeYKZW5kc3RyZWFtCmVuZG9iagoxIDAgb2JqCjw8L1RhYnMvUy9Hcm91cDw8L1MvVHJhbnNwYXJlbmN5L1R5cGUvR3JvdXAvQ1MvRGV2aWNlUkdCPj4vQ29udGVudHMgMyAwIFIvVHlwZS9QYWdlL1Jlc291cmNlczw8L0NvbG9yU3BhY2U8PC9DUy9EZXZpY2VSR0I+Pi9Qcm9jU2V0IFsvUERGIC9UZXh0IC9JbWFnZUIgL0ltYWdlQyAvSW1hZ2VJXS9Gb250PDwvRjEgMiAwIFI+Pj4+L1BhcmVudCA0IDAgUi9Sb3RhdGUgOTAvTWVkaWFCb3hbMCAwIDU5NSA4NDJdPj4KZW5kb2JqCjUgMCBvYmoKWzEgMCBSL1hZWiAwIDYwNSAwXQplbmRvYmoKMiAwIG9iago8PC9TdWJ0eXBlL1R5cGUxL1R5cGUvRm9udC9CYXNlRm9udC9IZWx2ZXRpY2EvRW5jb2RpbmcvV2luQW5zaUVuY29kaW5nPj4KZW5kb2JqCjQgMCBvYmoKPDwvS2lkc1sxIDAgUl0vVHlwZS9QYWdlcy9Db3VudCAxL0lUWFQoMi4xLjcpPj4KZW5kb2JqCjYgMCBvYmoKPDwvTmFtZXNbKEpSX1BBR0VfQU5DSE9SXzBfMSkgNSAwIFJdPj4KZW5kb2JqCjcgMCBvYmoKPDwvRGVzdHMgNiAwIFI+PgplbmRvYmoKOCAwIG9iago8PC9OYW1lcyA3IDAgUi9UeXBlL0NhdGFsb2cvUGFnZXMgNCAwIFIvVmlld2VyUHJlZmVyZW5jZXM8PC9QcmludFNjYWxpbmcvQXBwRGVmYXVsdD4+Pj4KZW5kb2JqCjkgMCBvYmoKPDwvTW9kRGF0ZShEOjIwMjAwNzI5MTE1MzE1WikvQ3JlYXRvcihKYXNwZXJSZXBvcnRzIExpYnJhcnkgdmVyc2lvbiBudWxsKS9DcmVhdGlvbkRhdGUoRDoyMDIwMDcyOTExNTMxNVopL1Byb2R1Y2VyKGlUZXh0IDIuMS43IGJ5IDFUM1hUKT4+CmVuZG9iagp4cmVmCjAgMTAKMDAwMDAwMDAwMCA2NTUzNSBmIAowMDAwMDAwNTc4IDAwMDAwIG4gCjAwMDAwMDA4NjQgMDAwMDAgbiAKMDAwMDAwMDAxNSAwMDAwMCBuIAowMDAwMDAwOTUyIDAwMDAwIG4gCjAwMDAwMDA4MjkgMDAwMDAgbiAKMDAwMDAwMTAxNSAwMDAwMCBuIAowMDAwMDAxMDY5IDAwMDAwIG4gCjAwMDAwMDExMDEgMDAwMDAgbiAKMDAwMDAwMTIwNCAwMDAwMCBuIAp0cmFpbGVyCjw8L0luZm8gOSAwIFIvSUQgWzwzZWMyMWUyNjkwNjcxYzViYTliNjUxODNhY2IxOTM3ND48NzZhNzM1MWE1YmY4ZmMxNDNmY2NlZmUwYjRjMzA4MWI+XS9Sb290IDggMCBSL1NpemUgMTA+PgpzdGFydHhyZWYKMTM1OAolJUVPRgo=",
    "invoice_items": [
        {
            "item": "McDonald's Big Mac",
            "description": "Oyon Meals",
            "quantity": 3,
            "date_of_purchase": "2021-03-12",
            "price_per_item": 50000
        }
    ]
}`)

  client := &http.Client {
  }
  req, err := http.NewRequest(method, url, payload)

  if err != nil {
    fmt.Println(err)
    return
  }
  req.Header.Add("Content-Type", "application/json")
  req.Header.Add("x-oy-username", "{{username}}")
  req.Header.Add("x-api-key", "{{api-key}}")

  res, err := client.Do(req)
  if err != nil {
    fmt.Println(err)
    return
  }
  defer res.Body.Close()

  body, err := ioutil.ReadAll(res.Body)
  if err != nil {
    fmt.Println(err)
    return
  }
  fmt.Println(string(body))
}
OkHttpClient client = new OkHttpClient().newBuilder()
  .build();
MediaType mediaType = MediaType.parse("application/json");
RequestBody body = RequestBody.create(mediaType, "{\n    \"description\": \"testdesc\",\n    \"notes\": \"testnote\",\n    \"partner_tx_id\": \"ab9c\",\n    \"sender_name\" : \"Mochamad Suryono\", \n    \"amount\" : \"15000\",\n    \"email\": \"business.support@oyindonesia.com\",\n    \"phone_number\": \"085712163208\", \n    \"is_open\" : true,\n      \"include_admin_fee\" : false,\n    \"list_disabled_payment_methods\": \"\",\n    \"list_enabled_banks\": \"002, 008, 009, 013, 022\",\n    \"expiration\": \"2021-03-13 00:00:00\",\n    \"due_date\":\"2021-03-12 12:00:00\",\n    \"partner_user_id\": \"OYON-CHECKOUT000003\",\n    \"full_name\": \"Mochamad Suryono\",\n    \"is_va_lifetime\": false,\n    \"attachment\": \"JVBERi0xLjQKJeLjz9MKMyAwIG9iago8PC9GaWx0ZXIvRmxhdGVEZWNvZGUvTGVuZ3RoIDQ5Nj4+c3RyZWFtCnicrZVdb9MwFIbv/SsOd51EwrHjz0tKhxQk2IciJMS4CG46lbVNyYcE/HqcbNloh5xO8U3OUXJ8Hr/2aweBQkQBQRjhnnZLfpJ5RhIJQhjIluQ8I1eEwYfubVeHMFRnW/LmPQWKkK3I7Cz70dU+lfTN/hnE3ChJY9SPA0U3EPvP1S2ZXXx5Bemnzxfpu/OuGcLtfxp+/ebisp+QH8VkrNjhHJ9QaV23xRKyciKIGuCGjYPmv6cq0idKWuRNEYDlV7VoixAgwcdEXeZVsysqyH5BughA88t6uy3bXQNO3XRbCEq9pKr8sw5gPuXT8zGv7/JNCOeh9mAYMoxQRcyEMJ5KRlEmokkI63lVrSgqi8JEWlsV8ZURkRFMR1pILkVuZcJYCEd69V7vY3eZxYj4GvEkGsaMK5SAMTcauYsKje6aObskUsGWaKr7bPOYHUd7/8XIocZlx9H2DfuSh+Qw2AG4GZLDYMlqmLfHEQIS/XyBaOf++5uoqG213jfrcjfVfAYdi/tY0288noxBrpqpvwoh1AjjslrbqUo6j/kpWdnkG7iZpYvrm7MQmyOe045vBhkhDbFFI6gTz6Jvj9zqCd+frz/5MRMvOvyeBUxGRM3bvIHvRZXvmryGu7Jq901ZhTDJqEweC+xlvkTqX6+ILeYKZW5kc3RyZWFtCmVuZG9iagoxIDAgb2JqCjw8L1RhYnMvUy9Hcm91cDw8L1MvVHJhbnNwYXJlbmN5L1R5cGUvR3JvdXAvQ1MvRGV2aWNlUkdCPj4vQ29udGVudHMgMyAwIFIvVHlwZS9QYWdlL1Jlc291cmNlczw8L0NvbG9yU3BhY2U8PC9DUy9EZXZpY2VSR0I+Pi9Qcm9jU2V0IFsvUERGIC9UZXh0IC9JbWFnZUIgL0ltYWdlQyAvSW1hZ2VJXS9Gb250PDwvRjEgMiAwIFI+Pj4+L1BhcmVudCA0IDAgUi9Sb3RhdGUgOTAvTWVkaWFCb3hbMCAwIDU5NSA4NDJdPj4KZW5kb2JqCjUgMCBvYmoKWzEgMCBSL1hZWiAwIDYwNSAwXQplbmRvYmoKMiAwIG9iago8PC9TdWJ0eXBlL1R5cGUxL1R5cGUvRm9udC9CYXNlRm9udC9IZWx2ZXRpY2EvRW5jb2RpbmcvV2luQW5zaUVuY29kaW5nPj4KZW5kb2JqCjQgMCBvYmoKPDwvS2lkc1sxIDAgUl0vVHlwZS9QYWdlcy9Db3VudCAxL0lUWFQoMi4xLjcpPj4KZW5kb2JqCjYgMCBvYmoKPDwvTmFtZXNbKEpSX1BBR0VfQU5DSE9SXzBfMSkgNSAwIFJdPj4KZW5kb2JqCjcgMCBvYmoKPDwvRGVzdHMgNiAwIFI+PgplbmRvYmoKOCAwIG9iago8PC9OYW1lcyA3IDAgUi9UeXBlL0NhdGFsb2cvUGFnZXMgNCAwIFIvVmlld2VyUHJlZmVyZW5jZXM8PC9QcmludFNjYWxpbmcvQXBwRGVmYXVsdD4+Pj4KZW5kb2JqCjkgMCBvYmoKPDwvTW9kRGF0ZShEOjIwMjAwNzI5MTE1MzE1WikvQ3JlYXRvcihKYXNwZXJSZXBvcnRzIExpYnJhcnkgdmVyc2lvbiBudWxsKS9DcmVhdGlvbkRhdGUoRDoyMDIwMDcyOTExNTMxNVopL1Byb2R1Y2VyKGlUZXh0IDIuMS43IGJ5IDFUM1hUKT4+CmVuZG9iagp4cmVmCjAgMTAKMDAwMDAwMDAwMCA2NTUzNSBmIAowMDAwMDAwNTc4IDAwMDAwIG4gCjAwMDAwMDA4NjQgMDAwMDAgbiAKMDAwMDAwMDAxNSAwMDAwMCBuIAowMDAwMDAwOTUyIDAwMDAwIG4gCjAwMDAwMDA4MjkgMDAwMDAgbiAKMDAwMDAwMTAxNSAwMDAwMCBuIAowMDAwMDAxMDY5IDAwMDAwIG4gCjAwMDAwMDExMDEgMDAwMDAgbiAKMDAwMDAwMTIwNCAwMDAwMCBuIAp0cmFpbGVyCjw8L0luZm8gOSAwIFIvSUQgWzwzZWMyMWUyNjkwNjcxYzViYTliNjUxODNhY2IxOTM3ND48NzZhNzM1MWE1YmY4ZmMxNDNmY2NlZmUwYjRjMzA4MWI+XS9Sb290IDggMCBSL1NpemUgMTA+PgpzdGFydHhyZWYKMTM1OAolJUVPRgo=\",\n    \"invoice_items\": [\n        {\n            \"item\": \"McDonald's Big Mac\",\n            \"description\": \"Oyon Meals\",\n            \"quantity\": 3,\n            \"date_of_purchase\": \"2021-03-12\",\n            \"price_per_item\": 50000\n        }\n    ]\n}");
Request request = new Request.Builder()
  .url("{{base_url}}/api/payment-checkout/create-invoice")
  .method("POST", body)
  .addHeader("Content-Type", "application/json")
  .addHeader("x-oy-username", "{{username}}")
  .addHeader("x-api-key", "{{api-key}}")
  .build();
Response response = client.newCall(request).execute();
var data = JSON.stringify({
  "description": "testdesc",
  "notes": "testnote",
  "partner_tx_id": "ab9c",
  "sender_name": "Mochamad Suryono",
  "amount": "15000",
  "email": "business.support@oyindonesia.com",
  "phone_number": "085712163208",
  "is_open": true,
  "include_admin_fee": false,
  "list_disabled_payment_methods": "",
  "list_enabled_banks": "002, 008, 009, 013, 022",
  "expiration": "2021-03-13 00:00:00",
  "due_date": "2021-03-12 12:00:00",
  "partner_user_id": "OYON-CHECKOUT000003",
  "full_name": "Mochamad Suryono",
  "is_va_lifetime": false,
  "attachment": "JVBERi0xLjQKJeLjz9MKMyAwIG9iago8PC9GaWx0ZXIvRmxhdGVEZWNvZGUvTGVuZ3RoIDQ5Nj4+c3RyZWFtCnicrZVdb9MwFIbv/SsOd51EwrHjz0tKhxQk2IciJMS4CG46lbVNyYcE/HqcbNloh5xO8U3OUXJ8Hr/2aweBQkQBQRjhnnZLfpJ5RhIJQhjIluQ8I1eEwYfubVeHMFRnW/LmPQWKkK3I7Cz70dU+lfTN/hnE3ChJY9SPA0U3EPvP1S2ZXXx5Bemnzxfpu/OuGcLtfxp+/ebisp+QH8VkrNjhHJ9QaV23xRKyciKIGuCGjYPmv6cq0idKWuRNEYDlV7VoixAgwcdEXeZVsysqyH5BughA88t6uy3bXQNO3XRbCEq9pKr8sw5gPuXT8zGv7/JNCOeh9mAYMoxQRcyEMJ5KRlEmokkI63lVrSgqi8JEWlsV8ZURkRFMR1pILkVuZcJYCEd69V7vY3eZxYj4GvEkGsaMK5SAMTcauYsKje6aObskUsGWaKr7bPOYHUd7/8XIocZlx9H2DfuSh+Qw2AG4GZLDYMlqmLfHEQIS/XyBaOf++5uoqG213jfrcjfVfAYdi/tY0288noxBrpqpvwoh1AjjslrbqUo6j/kpWdnkG7iZpYvrm7MQmyOe045vBhkhDbFFI6gTz6Jvj9zqCd+frz/5MRMvOvyeBUxGRM3bvIHvRZXvmryGu7Jq901ZhTDJqEweC+xlvkTqX6+ILeYKZW5kc3RyZWFtCmVuZG9iagoxIDAgb2JqCjw8L1RhYnMvUy9Hcm91cDw8L1MvVHJhbnNwYXJlbmN5L1R5cGUvR3JvdXAvQ1MvRGV2aWNlUkdCPj4vQ29udGVudHMgMyAwIFIvVHlwZS9QYWdlL1Jlc291cmNlczw8L0NvbG9yU3BhY2U8PC9DUy9EZXZpY2VSR0I+Pi9Qcm9jU2V0IFsvUERGIC9UZXh0IC9JbWFnZUIgL0ltYWdlQyAvSW1hZ2VJXS9Gb250PDwvRjEgMiAwIFI+Pj4+L1BhcmVudCA0IDAgUi9Sb3RhdGUgOTAvTWVkaWFCb3hbMCAwIDU5NSA4NDJdPj4KZW5kb2JqCjUgMCBvYmoKWzEgMCBSL1hZWiAwIDYwNSAwXQplbmRvYmoKMiAwIG9iago8PC9TdWJ0eXBlL1R5cGUxL1R5cGUvRm9udC9CYXNlRm9udC9IZWx2ZXRpY2EvRW5jb2RpbmcvV2luQW5zaUVuY29kaW5nPj4KZW5kb2JqCjQgMCBvYmoKPDwvS2lkc1sxIDAgUl0vVHlwZS9QYWdlcy9Db3VudCAxL0lUWFQoMi4xLjcpPj4KZW5kb2JqCjYgMCBvYmoKPDwvTmFtZXNbKEpSX1BBR0VfQU5DSE9SXzBfMSkgNSAwIFJdPj4KZW5kb2JqCjcgMCBvYmoKPDwvRGVzdHMgNiAwIFI+PgplbmRvYmoKOCAwIG9iago8PC9OYW1lcyA3IDAgUi9UeXBlL0NhdGFsb2cvUGFnZXMgNCAwIFIvVmlld2VyUHJlZmVyZW5jZXM8PC9QcmludFNjYWxpbmcvQXBwRGVmYXVsdD4+Pj4KZW5kb2JqCjkgMCBvYmoKPDwvTW9kRGF0ZShEOjIwMjAwNzI5MTE1MzE1WikvQ3JlYXRvcihKYXNwZXJSZXBvcnRzIExpYnJhcnkgdmVyc2lvbiBudWxsKS9DcmVhdGlvbkRhdGUoRDoyMDIwMDcyOTExNTMxNVopL1Byb2R1Y2VyKGlUZXh0IDIuMS43IGJ5IDFUM1hUKT4+CmVuZG9iagp4cmVmCjAgMTAKMDAwMDAwMDAwMCA2NTUzNSBmIAowMDAwMDAwNTc4IDAwMDAwIG4gCjAwMDAwMDA4NjQgMDAwMDAgbiAKMDAwMDAwMDAxNSAwMDAwMCBuIAowMDAwMDAwOTUyIDAwMDAwIG4gCjAwMDAwMDA4MjkgMDAwMDAgbiAKMDAwMDAwMTAxNSAwMDAwMCBuIAowMDAwMDAxMDY5IDAwMDAwIG4gCjAwMDAwMDExMDEgMDAwMDAgbiAKMDAwMDAwMTIwNCAwMDAwMCBuIAp0cmFpbGVyCjw8L0luZm8gOSAwIFIvSUQgWzwzZWMyMWUyNjkwNjcxYzViYTliNjUxODNhY2IxOTM3ND48NzZhNzM1MWE1YmY4ZmMxNDNmY2NlZmUwYjRjMzA4MWI+XS9Sb290IDggMCBSL1NpemUgMTA+PgpzdGFydHhyZWYKMTM1OAolJUVPRgo=",
  "invoice_items": [
    {
      "item": "McDonald's Big Mac",
      "description": "Oyon Meals",
      "quantity": 3,
      "date_of_purchase": "2021-03-12",
      "price_per_item": 50000
    }
  ]
});

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function() {
  if(this.readyState === 4) {
    console.log(this.responseText);
  }
});

xhr.open("POST", "%7B%7Bbase_url%7D%7D/api/payment-checkout/create-invoice");
xhr.setRequestHeader("Content-Type", "application/json");
xhr.setRequestHeader("x-oy-username", "{{username}}");
xhr.setRequestHeader("x-api-key", "{{api-key}}");

xhr.send(data);
<?php
require_once 'HTTP/Request2.php';
$request = new HTTP_Request2();
$request->setUrl('{{base_url}}/api/payment-checkout/create-invoice');
$request->setMethod(HTTP_Request2::METHOD_POST);
$request->setConfig(array(
  'follow_redirects' => TRUE
));
$request->setHeader(array(
  'Content-Type' => 'application/json',
  'x-oy-username' => '{{username}}',
  'x-api-key' => '{{api-key}}'
));
$request->setBody('{\n    "description": "testdesc",\n    "notes": "testnote",\n    "partner_tx_id": "ab9c",\n    "sender_name" : "Mochamad Suryono", \n    "amount" : "15000",\n    "email": "business.support@oyindonesia.com",\n    "phone_number": "085712163208", \n    "is_open" : true,\n     "include_admin_fee" : false,\n    "list_disabled_payment_methods": "",\n    "list_enabled_banks": "002, 008, 009, 013, 022",\n    "expiration": "2021-03-13 00:00:00",\n    "due_date": "2021-03-12 12:00:00",\n    "partner_user_id": "OYON-CHECKOUT000003",\n    "full_name": "Mochamad Suryono",\n    "is_va_lifetime": false,\n    "attachment": "JVBERi0xLjQKJeLjz9MKMyAwIG9iago8PC9GaWx0ZXIvRmxhdGVEZWNvZGUvTGVuZ3RoIDQ5Nj4+c3RyZWFtCnicrZVdb9MwFIbv/SsOd51EwrHjz0tKhxQk2IciJMS4CG46lbVNyYcE/HqcbNloh5xO8U3OUXJ8Hr/2aweBQkQBQRjhnnZLfpJ5RhIJQhjIluQ8I1eEwYfubVeHMFRnW/LmPQWKkK3I7Cz70dU+lfTN/hnE3ChJY9SPA0U3EPvP1S2ZXXx5Bemnzxfpu/OuGcLtfxp+/ebisp+QH8VkrNjhHJ9QaV23xRKyciKIGuCGjYPmv6cq0idKWuRNEYDlV7VoixAgwcdEXeZVsysqyH5BughA88t6uy3bXQNO3XRbCEq9pKr8sw5gPuXT8zGv7/JNCOeh9mAYMoxQRcyEMJ5KRlEmokkI63lVrSgqi8JEWlsV8ZURkRFMR1pILkVuZcJYCEd69V7vY3eZxYj4GvEkGsaMK5SAMTcauYsKje6aObskUsGWaKr7bPOYHUd7/8XIocZlx9H2DfuSh+Qw2AG4GZLDYMlqmLfHEQIS/XyBaOf++5uoqG213jfrcjfVfAYdi/tY0288noxBrpqpvwoh1AjjslrbqUo6j/kpWdnkG7iZpYvrm7MQmyOe045vBhkhDbFFI6gTz6Jvj9zqCd+frz/5MRMvOvyeBUxGRM3bvIHvRZXvmryGu7Jq901ZhTDJqEweC+xlvkTqX6+ILeYKZW5kc3RyZWFtCmVuZG9iagoxIDAgb2JqCjw8L1RhYnMvUy9Hcm91cDw8L1MvVHJhbnNwYXJlbmN5L1R5cGUvR3JvdXAvQ1MvRGV2aWNlUkdCPj4vQ29udGVudHMgMyAwIFIvVHlwZS9QYWdlL1Jlc291cmNlczw8L0NvbG9yU3BhY2U8PC9DUy9EZXZpY2VSR0I+Pi9Qcm9jU2V0IFsvUERGIC9UZXh0IC9JbWFnZUIgL0ltYWdlQyAvSW1hZ2VJXS9Gb250PDwvRjEgMiAwIFI+Pj4+L1BhcmVudCA0IDAgUi9Sb3RhdGUgOTAvTWVkaWFCb3hbMCAwIDU5NSA4NDJdPj4KZW5kb2JqCjUgMCBvYmoKWzEgMCBSL1hZWiAwIDYwNSAwXQplbmRvYmoKMiAwIG9iago8PC9TdWJ0eXBlL1R5cGUxL1R5cGUvRm9udC9CYXNlRm9udC9IZWx2ZXRpY2EvRW5jb2RpbmcvV2luQW5zaUVuY29kaW5nPj4KZW5kb2JqCjQgMCBvYmoKPDwvS2lkc1sxIDAgUl0vVHlwZS9QYWdlcy9Db3VudCAxL0lUWFQoMi4xLjcpPj4KZW5kb2JqCjYgMCBvYmoKPDwvTmFtZXNbKEpSX1BBR0VfQU5DSE9SXzBfMSkgNSAwIFJdPj4KZW5kb2JqCjcgMCBvYmoKPDwvRGVzdHMgNiAwIFI+PgplbmRvYmoKOCAwIG9iago8PC9OYW1lcyA3IDAgUi9UeXBlL0NhdGFsb2cvUGFnZXMgNCAwIFIvVmlld2VyUHJlZmVyZW5jZXM8PC9QcmludFNjYWxpbmcvQXBwRGVmYXVsdD4+Pj4KZW5kb2JqCjkgMCBvYmoKPDwvTW9kRGF0ZShEOjIwMjAwNzI5MTE1MzE1WikvQ3JlYXRvcihKYXNwZXJSZXBvcnRzIExpYnJhcnkgdmVyc2lvbiBudWxsKS9DcmVhdGlvbkRhdGUoRDoyMDIwMDcyOTExNTMxNVopL1Byb2R1Y2VyKGlUZXh0IDIuMS43IGJ5IDFUM1hUKT4+CmVuZG9iagp4cmVmCjAgMTAKMDAwMDAwMDAwMCA2NTUzNSBmIAowMDAwMDAwNTc4IDAwMDAwIG4gCjAwMDAwMDA4NjQgMDAwMDAgbiAKMDAwMDAwMDAxNSAwMDAwMCBuIAowMDAwMDAwOTUyIDAwMDAwIG4gCjAwMDAwMDA4MjkgMDAwMDAgbiAKMDAwMDAwMTAxNSAwMDAwMCBuIAowMDAwMDAxMDY5IDAwMDAwIG4gCjAwMDAwMDExMDEgMDAwMDAgbiAKMDAwMDAwMTIwNCAwMDAwMCBuIAp0cmFpbGVyCjw8L0luZm8gOSAwIFIvSUQgWzwzZWMyMWUyNjkwNjcxYzViYTliNjUxODNhY2IxOTM3ND48NzZhNzM1MWE1YmY4ZmMxNDNmY2NlZmUwYjRjMzA4MWI+XS9Sb290IDggMCBSL1NpemUgMTA+PgpzdGFydHhyZWYKMTM1OAolJUVPRgo=",\n    "invoice_items": [\n        {\n            "item": "McDonald\'s Big Mac",\n            "description": "Oyon Meals",\n            "quantity": 3,\n            "date_of_purchase": "2021-03-12",\n            "price_per_item": 50000\n        }\n    ]\n}');
try {
  $response = $request->send();
  if ($response->getStatus() == 200) {
    echo $response->getBody();
  }
  else {
    echo 'Unexpected HTTP status: ' . $response->getStatus() . ' ' .
    $response->getReasonPhrase();
  }
}
catch(HTTP_Request2_Exception $e) {
  echo 'Error: ' . $e->getMessage();
}
import http.client
import json

conn = http.client.HTTPSConnection("{{base_url}}")
payload = json.dumps({
  "description": "testdesc",
  "notes": "testnote",
  "partner_tx_id": "ab9c",
  "sender_name": "Mochamad Suryono",
  "amount": "15000",
  "email": "business.support@oyindonesia.com",
  "phone_number": "085712163208",
  "is_open": True,
  "include_admin_fee": False,
  "list_disabled_payment_methods": "",
  "list_enabled_banks": "002, 008, 009, 013, 022",
  "expiration": "2021-03-13 00:00:00",
  "due_date": "2021-03-12 12:00:00",
  "partner_user_id": "OYON-CHECKOUT000003",
  "full_name": "Mochamad Suryono",
  "is_va_lifetime": False,
  "attachment": "JVBERi0xLjQKJeLjz9MKMyAwIG9iago8PC9GaWx0ZXIvRmxhdGVEZWNvZGUvTGVuZ3RoIDQ5Nj4+c3RyZWFtCnicrZVdb9MwFIbv/SsOd51EwrHjz0tKhxQk2IciJMS4CG46lbVNyYcE/HqcbNloh5xO8U3OUXJ8Hr/2aweBQkQBQRjhnnZLfpJ5RhIJQhjIluQ8I1eEwYfubVeHMFRnW/LmPQWKkK3I7Cz70dU+lfTN/hnE3ChJY9SPA0U3EPvP1S2ZXXx5Bemnzxfpu/OuGcLtfxp+/ebisp+QH8VkrNjhHJ9QaV23xRKyciKIGuCGjYPmv6cq0idKWuRNEYDlV7VoixAgwcdEXeZVsysqyH5BughA88t6uy3bXQNO3XRbCEq9pKr8sw5gPuXT8zGv7/JNCOeh9mAYMoxQRcyEMJ5KRlEmokkI63lVrSgqi8JEWlsV8ZURkRFMR1pILkVuZcJYCEd69V7vY3eZxYj4GvEkGsaMK5SAMTcauYsKje6aObskUsGWaKr7bPOYHUd7/8XIocZlx9H2DfuSh+Qw2AG4GZLDYMlqmLfHEQIS/XyBaOf++5uoqG213jfrcjfVfAYdi/tY0288noxBrpqpvwoh1AjjslrbqUo6j/kpWdnkG7iZpYvrm7MQmyOe045vBhkhDbFFI6gTz6Jvj9zqCd+frz/5MRMvOvyeBUxGRM3bvIHvRZXvmryGu7Jq901ZhTDJqEweC+xlvkTqX6+ILeYKZW5kc3RyZWFtCmVuZG9iagoxIDAgb2JqCjw8L1RhYnMvUy9Hcm91cDw8L1MvVHJhbnNwYXJlbmN5L1R5cGUvR3JvdXAvQ1MvRGV2aWNlUkdCPj4vQ29udGVudHMgMyAwIFIvVHlwZS9QYWdlL1Jlc291cmNlczw8L0NvbG9yU3BhY2U8PC9DUy9EZXZpY2VSR0I+Pi9Qcm9jU2V0IFsvUERGIC9UZXh0IC9JbWFnZUIgL0ltYWdlQyAvSW1hZ2VJXS9Gb250PDwvRjEgMiAwIFI+Pj4+L1BhcmVudCA0IDAgUi9Sb3RhdGUgOTAvTWVkaWFCb3hbMCAwIDU5NSA4NDJdPj4KZW5kb2JqCjUgMCBvYmoKWzEgMCBSL1hZWiAwIDYwNSAwXQplbmRvYmoKMiAwIG9iago8PC9TdWJ0eXBlL1R5cGUxL1R5cGUvRm9udC9CYXNlRm9udC9IZWx2ZXRpY2EvRW5jb2RpbmcvV2luQW5zaUVuY29kaW5nPj4KZW5kb2JqCjQgMCBvYmoKPDwvS2lkc1sxIDAgUl0vVHlwZS9QYWdlcy9Db3VudCAxL0lUWFQoMi4xLjcpPj4KZW5kb2JqCjYgMCBvYmoKPDwvTmFtZXNbKEpSX1BBR0VfQU5DSE9SXzBfMSkgNSAwIFJdPj4KZW5kb2JqCjcgMCBvYmoKPDwvRGVzdHMgNiAwIFI+PgplbmRvYmoKOCAwIG9iago8PC9OYW1lcyA3IDAgUi9UeXBlL0NhdGFsb2cvUGFnZXMgNCAwIFIvVmlld2VyUHJlZmVyZW5jZXM8PC9QcmludFNjYWxpbmcvQXBwRGVmYXVsdD4+Pj4KZW5kb2JqCjkgMCBvYmoKPDwvTW9kRGF0ZShEOjIwMjAwNzI5MTE1MzE1WikvQ3JlYXRvcihKYXNwZXJSZXBvcnRzIExpYnJhcnkgdmVyc2lvbiBudWxsKS9DcmVhdGlvbkRhdGUoRDoyMDIwMDcyOTExNTMxNVopL1Byb2R1Y2VyKGlUZXh0IDIuMS43IGJ5IDFUM1hUKT4+CmVuZG9iagp4cmVmCjAgMTAKMDAwMDAwMDAwMCA2NTUzNSBmIAowMDAwMDAwNTc4IDAwMDAwIG4gCjAwMDAwMDA4NjQgMDAwMDAgbiAKMDAwMDAwMDAxNSAwMDAwMCBuIAowMDAwMDAwOTUyIDAwMDAwIG4gCjAwMDAwMDA4MjkgMDAwMDAgbiAKMDAwMDAwMTAxNSAwMDAwMCBuIAowMDAwMDAxMDY5IDAwMDAwIG4gCjAwMDAwMDExMDEgMDAwMDAgbiAKMDAwMDAwMTIwNCAwMDAwMCBuIAp0cmFpbGVyCjw8L0luZm8gOSAwIFIvSUQgWzwzZWMyMWUyNjkwNjcxYzViYTliNjUxODNhY2IxOTM3ND48NzZhNzM1MWE1YmY4ZmMxNDNmY2NlZmUwYjRjMzA4MWI+XS9Sb290IDggMCBSL1NpemUgMTA+PgpzdGFydHhyZWYKMTM1OAolJUVPRgo=",
  "invoice_items": [
    {
      "item": "McDonald's Big Mac",
      "description": "Oyon Meals",
      "quantity": 3,
      "date_of_purchase": "2021-03-12",
      "price_per_item": 50000
    }
  ]
})
headers = {
  'Content-Type': 'application/json',
  'x-oy-username': '{{username}}',
  'x-api-key': '{{api-key}}'
}
conn.request("POST", "/api/payment-checkout/create-invoice", payload, headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))

HTTPS Request

[Production] POST https://partner.oyindonesia.com/api/payment-checkout/create-invoice
[Staging] POST https://api-stg.oyindonesia.com/api/payment-checkout/create-invoice

Json Response

{
        "status": true,
        "url": "https://pay.oyindonesia.com/invoice/id",
        "message": "success",
        "email_status": "PROCESSED",
        "payment_link_id": "id"
}

Request Headers

Parameters Type Description
X-Api-Key String API Key for establishing connection to this particular endpoint
X-Oy-Username String The registered partner's username with enabled access for payment link product

Request Parameters

Parameters Type Description Limitation
partner_tx_id String A unique transaction ID provided by partner. A partner_tx_id that has been succesfully paid cannot be used anymore under the same username and only accepts alphanumerics. If empty then OY will generate automatically.
description String Description of the payment link. Only accepts alphabets (A-Z), numeric (0-9) and space as input.
notes String Notes. Only accepts alphabets (A-Z), numeric (0-9) and space as input.
sender_name String Name of the payer for a transaction. Only accepts alphabets (A-Z) and space as input and cannot be empty.
amount Integer The amount of a transaction to be paid. The amount of a transaction to be paid, min. amount is 10000, except if you use unique code BCA which has min. amount 11000 or CARDS which has min. amount 15000
email String The email address where the payment link will be sent to. Up to 3 emails separated by ";"
phone_number Numeric Phone number of the payer for a transaction. Do not use special character (e.g. "+").
is_open Boolean Enable open/closed amount transaction method. If is_open = TRUE and the amount parameter is defined, then a payer can pay any amount (greater than IDR 10,000) up to the defined amount. And in the case that is_open=false, then the amount and partner_tx_id parameters must be defined.
include_admin_fee Boolean Admin fee will be added to the specified amount or amount inputted by user if this parameter is set as TRUE. -
list_disabled_payment_methods String To configure payment methods to be disabled (e.g. VA, CREDIT_CARD, QRIS, EWALLET, BANK_TRANSFER). When BANK_TRANSFER is included, you are disabling both VA and Unique Code. When CREDIT_CARD is included, you are disabling the ‘cards’ payment method as a whole - which means disabling both credit card and debit card. There must be at least 1 payment method is enabled.
list_enabled_banks String To configure banks to be enabled for VA payment method. List of eligible bank codes: "002" (BRI), "008" (Mandiri), "009" (BNI), "013" (Permata), "022" (CIMB), "213" (BTPN), "213" (BSI), and "014" (BCA).
expiration datetime To set the expiration of the payment link (yyyy-MM-dd HH:mm:ss) -
due_date datetime To set the transaction due date of the payment (yyyy-MM-dd HH:mm:ss) Transaction due date should equal or before expiration. As default, transaction due date will be same as expiration if it is not defined.
partner_user_id String Username assigned to the customer by partner. -
full_name String The customer's full name. -
is_va_lifetime Boolean To enable VA static confirugation for a payment . If this is set as true and the partner_user_id is already associated to specific VAs, then the same VA numbers will be used for this partner_tx_id instead of generating new VA number. Partner_user_id and VA payment method must be specified to use this parameter.
invoice_items List List of items to be invoiced that can be generated via API in the following format: [item, description, quantity, date_of_purchase, price_per_item ] -
attachment - Upload attachment (string base 64 pdf) and can be downloaded via the webview There is a maximum limit of 1 PDF attachment (maximum 2 MB) to be uploaded per URL

Response Parameters

Parameter Type Nullable Description
status Boolean FALSE true / false
url String TRUE Payment link which used for payment. Only filled if payment checkout successfully created.
message String FALSE Message response
payment_link_id String TRUE A unique payment link transaction ID. Only filled if payment checkout successfully created.
email_status String TRUE email status. Only filled if payment checkout successfully created.

API Create (Recurring Invoice) (Coming soon)

This endpoint is to enable the capability to send recurring invoice with the same invoice configuration (e.g. payment method, amount, attachment) via email.

curl -X POST \
  https://partner.oyindonesia.com/api/TBD\
  -H 'cache-control: no-cache' \ 
  -H 'content-type: application/json' \
  -H 'x-api-key: apikeymu' \
  -H 'x-oy-username: yourusername' \
  -d '{
        "username":"testaccount",
        "partner_tx_id":"ABC123456527",
        "sender_name":"Roberto F",
        "sender_note":"bill payment",
        "sender_phone": "082114845847", 
        "amount":75000,
        "is_open":false,
        "list_disabled_payment_methods":"CREDIT_CARD",
        "list_enabled_payment_banks": "008", 
        "included_admin_fee": true, 
        "expiration": 7,
        "description":"payment for March 2020", 
        "partner_user_id": "merchant A", 
        "is_va_lifetime" : true , 
        "email" : "johndoe@gmail.com;jane@gmail.com",
        "recurring_start_date" : "10/11/2020", 
        "recurring_end_date": "10/11/2021", 
        "recurring_frequency": 30
    }'

HTTPS Request

[Production] POST https://partner.oyindonesia.com/api/TBD
[Staging] POST https://api-stg.oyindonesia.com/api/TBD

Json Response

{
        "status": true,
        "url": "https://pay.oyindonesia.com/v2?98999987uydfuiwk73636hehnrm",
        "email_status" : "delivered"
}

Request Parameters

*Note: all parameters from API Create (Payment Link and Invoicing) are still applicable. Below is the list of the additional specific parameters for Recurring Invoice feature.

Parameters Type Description
recurring_start_date String Defining the date when the first invoice will be sent.
recurring_end_date String Username assigned to the customer by partner.
recurring_frequency Integer The interval of a recurring invoice to be sent to customers (in days).

The data on the callback will be sent using JSON format via POST data to your web hook.

curl -X POST \
  https://partner.url.com/api/callback\
  -H 'cache-control: no-cache' \
  -H 'content-type: application/json' \
  -d '{
        "partner_tx_id":"938bca2f-7771-47a1-9315-13507cf7bba3",
        "amount":60000,
        "sender_phone":"082114845847",
        "sender_note":"sender notes",
        "created":"2020-09-29T20:57:41",
        "tx_ref_number":"20097G1X2329",
        "sender_name":"Sender Name",
        "is_invoice":false,
        "updated":"2020-09-29T20:59:08",
        "payment_method":"VA",
        "status":"complete",
        "sender_bank":"008",
        "settlement_type":"non_realtime",
        "description":"description",
        "payment_reference_number": "",
        "expiration":"2020-10-18T15:00:00",
        "due_date": "2020-10-18T14:00:00",
        "email":"johndoe@gmail.com;jane@gmail.com",
        "paid_amount": 70000,
        "settlement_time": "2020-09-30T15:00:00",
        "settlement_status": "WAITING"
      }'

Parameter Type Nullable Description
partner_tx_id String FALSE A unique transaction ID provided by partner.
child_balance String TRUE Applicable for MAM transaction. To be filled with the username of child account. If you do not pass the parameter in request, we will not pass this parameter in Callback.
tx_ref_number String FALSE OY's internal unique transaction ID.
amount BigDecimal FALSE The amount of a transaction that is paid.
sender_name String FALSE Name of a payer for a transaction.
sender_phone String TRUE Phone number of a payer for a transaction. This parameter will only be sent if end user fill the data.
sender_note String TRUE Additional notes from a payer for a transaction. This parameter will only be sent if end user fill the data.
status String FALSE The status of a transaction (e.g. success/failed/processing).
sender_bank String FALSE The bank code used by a payer to do payment.
payment_method String FALSE The payment method used by user to complete a payment.
settlement_type String FALSE Indicate if a transaction will be settled in realtime/non-realtime.
created DateTime FALSE The timestamp which indicates the creation time of a payment link.
updated DateTime FALSE The timestamp which indicates the latest updated time of a payment link due to status update.
payment_received_time DateTime TRUE Indicates the time when payment routing is marked as COMPLETE (this parameter will only be sent once status of the payment link is set to ‘COMPLETE’).
is_invoice Boolean FALSE The invoice which indicates the transaction is invoice or not.
description String FALSE The description of the payment link/invoice link.
payment_reference_number String TRUE Identifier of a payment attempt when the end user successfully completes the payment. The reference number is also stated in the end user’s receipt/proof of transaction. Note that if a QRIS transaction is paid using OVO, the payment reference number is only the first 12 characters from the given transaction code. Available for: QRIS.
expiration DateTime FALSE The expiration time of the payment link/invoice link.
due_date DateTime FALSE The transaction due date of the payment link/invoice.
email String FALSE The email addresses for the payment link/invoice link to be sent. You can add up to 3 emails separated by ";".
paid_amount BigDecimal FALSE The total amount that a user has paid.
settlement_time DateTime TRUE The timestamp (in UTC+7) indicating when the fund will be settled to partner’s account statement. This parameter will only be sent once status of the payment link is set to 'COMPLETE'.
settlement_status String TRUE Status of the settlement (e.g. success/waiting). This parameter will only be sent once status of the payment link is set to 'COMPLETE'.

Additional data on the callback if invoice = true

Parameter Type Nullable Description
invoice_ID String FALSE The invoice id.
full_name String FALSE The full name.
Payment Status Type Description
created String Status that will be returned when the payment link is first created and user has not selected a payment method
waiting_payment String Status that indicates that the user has selected a payment method
expired String The payment link has expired
charge_in_progress String Payment currently in processed
failed String OTP for card payment method has been succesfully entered but payment is rejected or the selected payment channel has expired (but the link is still not yet expired)
complete String Transaction has been succesfully completed
closed String Payment link has been deleted

API Payment Status

An endpoint to retrieve and/or re-send the latest callback status of a transaction. We can also provide a static IP for the callback to ensure the callback sent is from OY that can be whitelisted by partners.

Please contact us to submit a request of an API Key and IP whitelisting.

HTTPS Request

[Production] GET https://partner.oyindonesia.com/api/payment-checkout/status
[Staging] GET https://api-stg.oyindonesia.com/api/payment-checkout/status

To retrieve a callback result for a particular transaction, use following code from your platform:

curl -X GET \
  'https://partner.oyindonesia.com/api/payment-checkout/status?partner_tx_id=OY123456&send_callback=false' \
  -H 'x-oy-username:yourusername' \
  -H 'x-api-key:yourapikey'
var headers = {
  'Content-Type': 'application/json'
};
var request = http.Request('GET', Uri.parse('https://partner.oyindonesia.com/api/payment-checkout/status?partner_tx_id=abc6&send_callback=false'));

request.headers.addAll(headers);

http.StreamedResponse response = await request.send();

if (response.statusCode == 200) {
  print(await response.stream.bytesToString());
}
else {
  print(response.reasonPhrase);
}
package main

import (
  "fmt"
  "net/http"
  "io/ioutil"
)

func main() {

  url := "https://partner.oyindonesia.com/api/payment-checkout/status?partner_tx_id=abc6&send_callback=false"
  method := "GET"

  client := &http.Client {
  }
  req, err := http.NewRequest(method, url, nil)

  if err != nil {
    fmt.Println(err)
    return
  }
  req.Header.Add("Content-Type", "application/json")

  res, err := client.Do(req)
  if err != nil {
    fmt.Println(err)
    return
  }
  defer res.Body.Close()

  body, err := ioutil.ReadAll(res.Body)
  if err != nil {
    fmt.Println(err)
    return
  }
  fmt.Println(string(body))
}
OkHttpClient client = new OkHttpClient().newBuilder()
  .build();
Request request = new Request.Builder()
  .url("https://partner.oyindonesia.com/api/payment-checkout/status?partner_tx_id=abc6&send_callback=false")
  .method("GET", null)
  .addHeader("Content-Type", "application/json")
  .build();
Response response = client.newCall(request).execute();

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function() {
  if(this.readyState === 4) {
    console.log(this.responseText);
  }
});

xhr.open("GET", "https://partner.oyindonesia.com/api/payment-checkout/status?partner_tx_id=abc6&send_callback=false");
xhr.setRequestHeader("Content-Type", "application/json");

xhr.send();
<?php
require_once 'HTTP/Request2.php';
$request = new HTTP_Request2();
$request->setUrl('https://partner.oyindonesia.com/api/payment-checkout/status?partner_tx_id=abc6&send_callback=false');
$request->setMethod(HTTP_Request2::METHOD_GET);
$request->setConfig(array(
  'follow_redirects' => TRUE
));
$request->setHeader(array(
  'Content-Type' => 'application/json'
));
try {
  $response = $request->send();
  if ($response->getStatus() == 200) {
    echo $response->getBody();
  }
  else {
    echo 'Unexpected HTTP status: ' . $response->getStatus() . ' ' .
    $response->getReasonPhrase();
  }
}
catch(HTTP_Request2_Exception $e) {
  echo 'Error: ' . $e->getMessage();
}
import http.client
import json

conn = http.client.HTTPSConnection("partner.oyindonesia.com")
payload = ''
headers = {
  'Content-Type': 'application/json'
}
conn.request("GET", "/api/payment-checkout/status?partner_tx_id=abc6&send_callback=false", payload, headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))

The above command returns JSON structured similar like this:

{
  "partner_tx_id": "partner000001",
  "tx_ref_number": "1234567",
  "child_balance": "child123",
  "amount": 15000,
  "sender_name": "Budi",
  "sender_phone": "+6281111111",
  "sender_note": "Mohon dikirim segera",
  "status": "success",
  "settlement_type": "realtime",
  "sender_bank": "008",
  "payment_method": "CC",
  "created": "2021-01-12T16:25:33",
  "description": "",
  "payment_reference_number": "",
  "paid_amount": 100000,
  "expiration": "2021-01-13T16:25:14",
  "due_date": "2021-01-13T15:00:00",
  "is_invoice": false,
  "updated": "2021-01-12T16:26:17",
  "email": "johndoe@gmail.com;jane@gmail.com",
  "settlement_time": "2021-01-13T15:00:00",
  "settlement_status": "WAITING"
}

Request Headers

Parameters Type Description
x-api-key String API Key for establishing connection to this particular endpoint
X-Oy-Username String The registered partner's username with enabled access for payment link product

Request Parameters

Parameters Type Description
partner_tx_id String A unique transaction ID which callback status to be checked
payment_reference_number String A unique reference ID only for QRIS transactions. Used to identify which callback status to be checked. The reference number is stated in the end user’s receipt/proof of transaction. Note that if a QRIS transaction is paid using OVO, the payment reference number is only the first 12 characters from the given transaction code
send_callback Boolean A flag to indiciate if the latest callback of a transaction need to be re-sent or not

Response Parameters

Parameter Type Nullable Description
partner_tx_id String FALSE A unique transaction ID provided by partner.
child_balance String FALSE Applicable for MAM transaction. To be filled with the username of child account. If you do not pass the parameter in request Create Payment Link, we will not pass this parameter in the response.
tx_ref_number String FALSE OY's internal unique transaction ID.
amount BigDecimal FALSE The amount of a transaction that is paid.
sender_name String FALSE Name of a payer for a transaction.
sender_phone String FALSE Phone number of a payer for a transaction.
sender_note String FALSE Additional notes from a payer for a transaction.
status String FALSE The status of a payment link.
payment_received_time String TRUE Indicates the time when payment routing is marked as COMPLETE (this parameter will only be sent once status of the payment link is set to ‘COMPLETE’).
settlement_type String FALSE Indicate if a transaction will be settled in realtime/non-realtime.
sender_bank String FALSE The bank code used by a payer to do payment.
payment_method String FALSE The payment method used in a transaction. Choices are: CC (Cards), QRIS, EWALLET (shopeepay_ewallet, dana_ewallet, linkaja_ewallet, ovo_ewallet), VA (Virtual Account), or BANK_TRANSFER (Unique Code).
created String FALSE The timestamp which indicates the creation time of a payment link.
description String FALSE Description of the payment link.
payment_reference_number String FALSE Identifier of a payment attempt when the end user successfully completes the payment. The reference number is also stated in the end user’s receipt/proof of transaction. Note that if a QRIS transaction is paid using OVO, the payment reference number is only the first 12 characters from the given transaction code. Available for: QRIS.
paid_amount BigDecimal FALSE the total amount that a user has paid.
expiration String FALSE To set the expiration of the payment link (yyyy-MM-dd HH:mm:ss).
due_date String FALSE To set the transaction due date of the payment (yyyy-MM-dd HH:mm:ss).
is_invoice Boolean FALSE The invoice which indicates the transaction is invoice or not.
updated String FALSE The timestamp which indicates the latest updated time of a payment link due to status update.
email String FALSE The email addresses where the payment link will be sent to. You can add up to 3 emails separated by ";".
settlement_time String FALSE The timestamp (in UTC+7) indicating when the fund will be settled to partner’s account statement (this parameter will only be sent once status of the payment link is set to ‘COMPLETE’).
settlement_status String FALSE The status of the settlement (this parameter will only be sent once status of the payment link is set to ‘COMPLETE’).

API Delete

An endpoint to Delete Payment / Invoice Link based on payment_link_id or partner_tx_id that is still active and a payment method has not been selected.

curl -X DELETE \
  https://partner.oyindonesia.com/api/payment-checkout/{payment_link_id_or_partner_tx_id}\
  -H 'cache-control: no-cache' \
  -H 'content-type: application/json' \
  -H 'X-Api-key: apikeymu' \
  -H 'X-Oy-Username: yourusername' 
var headers = {
  'Content-Type': 'application/json'
};
var request = http.Request('DELETE', Uri.parse('https://partner.oyindonesia.com/api/payment-checkout/4fce3338-e2b7-400d-98d1-f117c0e0fcb4'));

request.headers.addAll(headers);

http.StreamedResponse response = await request.send();

if (response.statusCode == 200) {
  print(await response.stream.bytesToString());
}
else {
  print(response.reasonPhrase);
}
package main

import (
  "fmt"
  "net/http"
  "io/ioutil"
)

func main() {

  url := "https://partner.oyindonesia.com/api/payment-checkout/4fce3338-e2b7-400d-98d1-f117c0e0fcb4"
  method := "DELETE"

  client := &http.Client {
  }
  req, err := http.NewRequest(method, url, nil)

  if err != nil {
    fmt.Println(err)
    return
  }
  req.Header.Add("Content-Type", "application/json")

  res, err := client.Do(req)
  if err != nil {
    fmt.Println(err)
    return
  }
  defer res.Body.Close()

  body, err := ioutil.ReadAll(res.Body)
  if err != nil {
    fmt.Println(err)
    return
  }
  fmt.Println(string(body))
}
OkHttpClient client = new OkHttpClient().newBuilder()
  .build();
MediaType mediaType = MediaType.parse("application/json");
RequestBody body = RequestBody.create(mediaType, "");
Request request = new Request.Builder()
  .url("https://partner.oyindonesia.com/api/payment-checkout/4fce3338-e2b7-400d-98d1-f117c0e0fcb4")
  .method("DELETE", body)
  .addHeader("Content-Type", "application/json")
  .build();
Response response = client.newCall(request).execute();

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function() {
  if(this.readyState === 4) {
    console.log(this.responseText);
  }
});

xhr.open("DELETE", "https://partner.oyindonesia.com/api/payment-checkout/4fce3338-e2b7-400d-98d1-f117c0e0fcb4");
xhr.setRequestHeader("Content-Type", "application/json");

xhr.send();
<?php
require_once 'HTTP/Request2.php';
$request = new HTTP_Request2();
$request->setUrl('https://partner.oyindonesia.com/api/payment-checkout/4fce3338-e2b7-400d-98d1-f117c0e0fcb4');
$request->setMethod(HTTP_Request2::METHOD_DELETE);
$request->setConfig(array(
  'follow_redirects' => TRUE
));
$request->setHeader(array(
  'Content-Type' => 'application/json'
));
try {
  $response = $request->send();
  if ($response->getStatus() == 200) {
    echo $response->getBody();
  }
  else {
    echo 'Unexpected HTTP status: ' . $response->getStatus() . ' ' .
    $response->getReasonPhrase();
  }
}
catch(HTTP_Request2_Exception $e) {
  echo 'Error: ' . $e->getMessage();
}
import http.client
import json

conn = http.client.HTTPSConnection("partner.oyindonesia.com")
payload = ''
headers = {
  'Content-Type': 'application/json'
}
conn.request("DELETE", "/api/payment-checkout/4fce3338-e2b7-400d-98d1-f117c0e0fcb4", payload, headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))

HTTPS Request

[Production] DELETE https://partner.oyindonesia.com/api/payment-checkout/{payment_link_id_or_partner_tx_id}
[Staging] DELETE https://api-stg.oyindonesia.com/api/payment-checkout/{payment_link_id_or_partner_tx_id}

The above command returns JSON structured similar like this:

{
  "status" : true,
  "message" : "success delete payment checkout data"
}

Request Parameters

Parameters Type Description
payment_link_id_or_partner_tx_id String payment_link_id or partner_tx_id in url param

Response Parameters

Parameters Type Nullable Description
status Boolean FALSE TRUE if delete is successful and FALSE otherwise.
message String FALSE Return message.
child_balance String TRUE Applicable for MAM transaction. To be filled with the username of child account. If you do not pass the parameter in request, we will not pass this parameter in Callback.

Return Message

Reason Message
Successful Deletion Payment link has been deleted
Data Not Found The payment_link_id or partner_trx_id cannot be found in our system
Invalid Payment Link Id The payment_link_id or partner_trx_id is null or invalid
Username Not Found Username is not found
Invalid IP Address Invalid IP Address
Invalid API Key Invalid API Key
Restricted Access User does not have access to delete the payment link
Invalid Payment Status Cannot delete payment link status other than CREATED/INITIATIED

API Get

An endpoint to get a payment/invoice data.

curl -X GET \
  https://partner.oyindonesia.com/api/payment-checkout/{payment_link_id_or_partner_tx_id}\
  -H 'cache-control: no-cache' \
  -H 'content-type: application/json' \
  -H 'X-Api-key: apikeymu' \
  -H 'X-Oy-Username: yourusername'
var headers = {
  'Content-Type': 'application/json'
};
var request = http.Request('GET', Uri.parse('https://partner.oyindonesia.com/api/payment-checkout/aa2d30f7-6e45-464b-bd4f-7e042f7e114b'));

request.headers.addAll(headers);

http.StreamedResponse response = await request.send();

if (response.statusCode == 200) {
  print(await response.stream.bytesToString());
}
else {
  print(response.reasonPhrase);
}
package main

import (
  "fmt"
  "net/http"
  "io/ioutil"
)

func main() {

  url := "https://partner.oyindonesia.com/api/payment-checkout/aa2d30f7-6e45-464b-bd4f-7e042f7e114b"
  method := "GET"

  client := &http.Client {
  }
  req, err := http.NewRequest(method, url, nil)

  if err != nil {
    fmt.Println(err)
    return
  }
  req.Header.Add("Content-Type", "application/json")

  res, err := client.Do(req)
  if err != nil {
    fmt.Println(err)
    return
  }
  defer res.Body.Close()

  body, err := ioutil.ReadAll(res.Body)
  if err != nil {
    fmt.Println(err)
    return
  }
  fmt.Println(string(body))
}
OkHttpClient client = new OkHttpClient().newBuilder()
  .build();
Request request = new Request.Builder()
  .url("https://partner.oyindonesia.com/api/payment-checkout/aa2d30f7-6e45-464b-bd4f-7e042f7e114b")
  .method("GET", null)
  .addHeader("Content-Type", "application/json")
  .build();
Response response = client.newCall(request).execute();

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function() {
  if(this.readyState === 4) {
    console.log(this.responseText);
  }
});

xhr.open("GET", "https://partner.oyindonesia.com/api/payment-checkout/aa2d30f7-6e45-464b-bd4f-7e042f7e114b");
xhr.setRequestHeader("Content-Type", "application/json");

xhr.send();
<?php
require_once 'HTTP/Request2.php';
$request = new HTTP_Request2();
$request->setUrl('https://partner.oyindonesia.com/api/payment-checkout/aa2d30f7-6e45-464b-bd4f-7e042f7e114b');
$request->setMethod(HTTP_Request2::METHOD_GET);
$request->setConfig(array(
  'follow_redirects' => TRUE
));
$request->setHeader(array(
  'Content-Type' => 'application/json'
));
try {
  $response = $request->send();
  if ($response->getStatus() == 200) {
    echo $response->getBody();
  }
  else {
    echo 'Unexpected HTTP status: ' . $response->getStatus() . ' ' .
    $response->getReasonPhrase();
  }
}
catch(HTTP_Request2_Exception $e) {
  echo 'Error: ' . $e->getMessage();
}
import http.client
import json

conn = http.client.HTTPSConnection("partner.oyindonesia.com")
payload = ''
headers = {
  'Content-Type': 'application/json'
}
conn.request("GET", "/api/payment-checkout/aa2d30f7-6e45-464b-bd4f-7e042f7e114b", payload, headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))

HTTPS Request

[Production] GET https://partner.oyindonesia.com/api/payment-checkout/{payment_link_id_or_partner_tx_id}
[Staging] GET https://api-stg.oyindonesia.com/api/payment-checkout/{payment_link_id_or_partner_tx_id}

The above command returns JSON structured similar like this:

{
    "data": {
        "partnerTxId": "abc10",
        "child_balance":"child123",
        "paymentLinkId": "703e05c0-48e3-47bd-9c22-670941d4d5fe",
        "amount": 15000,
        "username": "justkhals",
        "senderName": "John Doe",
        "senderPhoneNumber": null,
        "senderNotes": null,
        "status": "CREATED",
        "txRefNumber": null,
        "description": "testdesc",
        "isOpen": true,
        "notes": "testnote",
        "phoneNumber": "085248395555",
        "email": "maskalgrr@gmail.com",
        "includeAdminFee": false,
        "listDisabledPaymentMethods": "",
        "listEnabledBanks": "008",
        "expirationTime": "2020-08-12 00:00:00",
        "due_date": "2020-08-11 12:00:00",
        "invoiceData": {
            "fullName": "John Dooe",
            "isVaLifetime": false,
            "isScheduled": false,
            "recurringStartDate": null,
            "recurringEndDate": null,
            "recurringFrequency": null,
            "invoiceItems": "[{\"item\": \"Semen Gresik\", \"quantity\": 2000, \"description\": \"Grade B\", \"price_per_item\": 2250000, \"date_of_purchase\": 1590969600000}]"
        }
    },
    "message": "return payment checkout data",
    "status": true
}

Request Parameters

Parameters Type Description
payment_link_id_or_partner_tx_id String payment_link_id or partner_tx_id in url param

Payment Response Parameters

Parameters Type Nullable Description Example Value
partnerTxId String FALSE Payment Partner Tx Id abc123
child_balance String TRUE Applicable for MAM transaction. To be filled with the username of child account. If you do not pass the parameter in request, we will not pass this parameter in Callback child123
paymentLinkId String FALSE Payment Link Id 35281815-4784-4f55-9a61-090f5c17a191
amount Integer FALSE Payment Amount 30000
username String FALSE Partner Username johndoe
senderName String FALSE Payment Sender Name Budi
senderPhoneNumber String TRUE Payment Sender Phone Number. This parameter will only be sent if end user fill the data 081234567890
senderNotes String TRUE Payment Notes / Subject. This parameter will only be sent if end user fill the data Cicilan Mobil - 5
status String FALSE Payment Status COMPLETE
txRefNumber String FALSE Payment Transaction Reference Number GTY67JJU
description String FALSE Payment Description Tagihan Cicilan Mobil
isOpen Boolean FALSE Payment Editable Amount Capability true
notes String FALSE Payment Notes / Subject Cicilan Mobil - 5
email String FALSE Payment Sender Email(s).You can add up to 3 emails separated by ";" johndoe@gmail.com;jane@gmail.com
senderPhoneNumber String FALSE Payment Sender Phone Number 081234567890
includeAdminFee Boolean FALSE Admin fee bills destination between partner or user true
listDisabledPaymentMethods String FALSE List Of Disable Payment Method.
listEnabledBanks String FALSE Payment Method List Enable Bank for VA or Unique Code Payment Method 002,008
expirationTime String FALSE Payment Expiration Date and Time "2020-08-12 00:00:00"
due_date String FALSE Transaction Due Date "2020-08-11 12:00:00"
invoiceData Invoice TRUE Data For Invoice Payment will be null CREDIT_CARD)**

Invoice Response Parameters

Parameters Type Description Example Value
fullName String Invoice Payer Name John Doe
isVaLifetime String Invoice static VA status true
isScheduled Boolean Invoice Scheduled status true
invoiceItems String JSON Invoice Item List JSON "[{\"item\": \"Semen Gresik\", \"quantity\": 2000, \"description\": \"Grade B\", \"price_per_item\": 2250000, \"date_of_purchase\": 1590969600000}]"

Failed Response Parameters

Parameters Type Description
status Boolean Return FALSE if data is not found
message String Return message

Failed Return Message

Reason Message
Data Not Found The payment_link_id or partner_trx_id cannot be found in our system
Invalid Payment Link Id The payment_link_id or partner_trx_id is null or invalid
Username Not Found Username is not found
Invalid IP Address Invalid IP Address
Invalid API Key Invalid API Key
Restricted Access User does not have access to the payment link

Pop!: Seamless Payment Experience

With Pop!, displaying our payment link page on your front-end web environment is now made easier than ever. Our payment link offers a seamless user experience in a way that can be catered to your UI needs.

This section covers a demonstration and a snippet code on how to display a payment link page in 4 styles/locations: Center, Right, Left, and Slide Right.

Pop! - Center

import React from 'react';
import classNames from 'classnames';
import styles from './paycheckout_popup.module.css';

function PaycheckoutPopUp({
  position = "center",
  show,
  onClose,
  paymentLinkId,
}) {

  return (
    <div>
      {/* The Modal container*/}

        {/* Modal content */}

          <iframe 
            width="400"
            height="800"
            src={`https://pay-dev.oyindonesia.com/${paymentLinkId}`}
            title="OY! Indonesia Payment Link">
          </iframe>

          {/* Trigger/Close The Modal */}
    </div>
  );
}

Pop! - Left

import React from 'react';
import classNames from 'classnames';
import styles from './paycheckout_popup.module.css';

function PaycheckoutPopUp({
  position = "left",
  show,
  onClose,
  paymentLinkId,
}) {

  return (
    <div>
      {/* The Modal container*/}

        {/* Modal content */}

          <iframe 
            width="400"
            height="800"
            src={`https://pay-dev.oyindonesia.com/${paymentLinkId}`}
            title="OY! Indonesia Payment Link">
          </iframe>

          {/* Trigger/Close The Modal */}
    </div>
  );
}

Pop! - Right

import React from 'react';
import classNames from 'classnames';
import styles from './paycheckout_popup.module.css';

function PaycheckoutPopUp({
  position = "right",
  show,
  onClose,
  paymentLinkId,
}) {

  return (
    <div>
      {/* The Modal container*/}

        {/* Modal content */}

          <iframe 
            width="400"
            height="800"
            src={`https://pay-dev.oyindonesia.com/${paymentLinkId}`}
            title="OY! Indonesia Payment Link">
          </iframe>

          {/* Trigger/Close The Modal */}
    </div>
  );
}

Pop! - Slide Right

import React from 'react';
import styles from './paycheckout_slide.module.css';

function PaycheckoutSlide({
    show, 
    onClose,
    paymentLinkId,
  }) {

  return (
    <div>
      {/* The Modal container*/}
        {/* Modal content */}
          <iframe 
            width="400"
            src={`https://pay-dev.oyindonesia.com/${paymentLinkId}`}
            title="OY! Indonesia Payment Link">
          </iframe>
    </div>
  );
}

Fund Acceptance Response Codes

Below is the list of HTTP Status Code for API Fund Acceptance:

HTTP Status Code Description
200 Response success without error
403 Forbidden (IP address is not whitelisted or request is deemed suspicious e.g SQL injection or XSS)
404 Not Found (wrong URL)
429 Request Rejected (Too Many Request to specific endpoint)
500 Internal Server Error (OY! system encountered unknown error)
503 Service Unavailable (OY! system is unable to process the request temporarily)
504 Gateway Timeout (OY! system took too long processing the request and was unable to respond in time)

API Account Receivable

API Account Receivable is the newest feature that allows Partners to manage customers and account receivable invoices via API. The differences between API Account Receivable API and API Invoicing is in the customer management ability. By utilizing API Account Receivable, Partners do not need to maintain manual data of the customers anymore when inputting invoice.

Create New Customer

This endpoint enables the creation of new customers via API. Addition of new customer can also be done via dashboard at your convenience.

curl --location --request POST 'https://partner.oyindonesia.com/api/account-receivable/customers' \
--header 'x-oy-username: username' \
--header 'x-api-key: api-key' \
--header 'Content-Type: application/json' \
--data-raw '{
    "name": "Acumen Metros",
    "partner_customer_id": "customer_id",
    "tax_type": "PPN_10_INCLUSIVE",
    "address": "address",
    "email": "email@address.com",
    "pic_name": "Pic name",
    "phone_number": "08123456789",
    "pph_tax":"PPH_23_NON_NPWP"
}'
var headers = {
  'x-oy-username': 'username',
  'x-api-key': 'api_key',
  'Content-Type': 'application/json'
};
var request = http.Request('POST', Uri.parse('https://partner.oyindonesia.com/api/account-receivable/customers'));
request.body = json.encode({
  "name": "Acumen Metros",
  "partner_customer_id": "customer_id",
  "tax_type": "PPN_10_INCLUSIVE",
  "address": "address",
  "email": "email@address.com",
  "pic_name": "Pic Name",
  "phone_number": "0812345678",
  "pph_tax": "PPH_23_NON_NPWP"
});
request.headers.addAll(headers);

http.StreamedResponse response = await request.send();

if (response.statusCode == 200) {
  print(await response.stream.bytesToString());
}
else {
  print(response.reasonPhrase);
}

package main

import (
  "fmt"
  "strings"
  "net/http"
  "io/ioutil"
)

func main() {

  url := "https://partner.oyindonesia.com/api/account-receivable/customers"
  method := "POST"

  payload := strings.NewReader(`{
    "name": "Acumen Metros",
    "partner_customer_id": "customer_id",
    "tax_type": "PPN_10_INCLUSIVE",
    "address": "address",
    "email": "email@address.com",
    "pic_name": "Pic Name",
    "phone_number": "0812345678",
    "pph_tax":"PPH_23_NON_NPWP"
}`)

  client := &http.Client {
  }
  req, err := http.NewRequest(method, url, payload)

  if err != nil {
    fmt.Println(err)
    return
  }
  req.Header.Add("x-oy-username", "username")
  req.Header.Add("x-api-key", "api_key")
  req.Header.Add("Content-Type", "application/json")

  res, err := client.Do(req)
  if err != nil {
    fmt.Println(err)
    return
  }
  defer res.Body.Close()

  body, err := ioutil.ReadAll(res.Body)
  if err != nil {
    fmt.Println(err)
    return
  }
  fmt.Println(string(body))
}
OkHttpClient client = new OkHttpClient().newBuilder()
  .build();
  MediaType mediaType = MediaType.parse("application/json");
  RequestBody body = RequestBody.create(mediaType, "{\n    \"name\": \"Acumen Metros\",\n    \"partner_customer_id\": \"customer_id\",\n    \"tax_type\": \"PPN_10_INCLUSIVE\",\n    \"address\": \"address\",\n    \"email\": \"email@address.com\",\n    \"pic_name\": \"Pic Name\",\n    \"phone_number\": \"0812345678\",\n    \"pph_tax\":\"PPH_23_NON_NPWP\"\n}");
  Request request = new Request.Builder()
  .url("https://partner.oyindonesia.com/api/account-receivable/customers")
  .method("POST", body)
  .addHeader("x-oy-username", "username")
  .addHeader("x-api-key", "api_key")
  .addHeader("Content-Type", "application/json")
  .build();
  Response response = client.newCall(request).execute();
// WARNING: For POST requests, body is set to null by browsers.
var data = JSON.stringify({
  "name": "Acumen Metros",
  "partner_customer_id": "customer_id",
  "tax_type": "PPN_10_INCLUSIVE",
  "address": "address",
  "email": "email@address.com",
  "pic_name": "Pic Name",
  "phone_number": "0812345678",
  "pph_tax": "PPH_23_NON_NPWP"
});

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function() {
  if(this.readyState === 4) {
    console.log(this.responseText);
  }
});

xhr.open("POST", "https://partner.oyindonesia.com/api/account-receivable/customers");
xhr.setRequestHeader("x-oy-username", "username");
xhr.setRequestHeader("x-api-key", "api_key");
xhr.setRequestHeader("Content-Type", "application/json");

xhr.send(data);
<?php
require_once 'HTTP/Request2.php';
$request = new HTTP_Request2();
$request->setUrl('https://partner.oyindonesia.com/api/account-receivable/customers');
$request->setMethod(HTTP_Request2::METHOD_POST);
$request->setConfig(array(
  'follow_redirects' => TRUE
));
$request->setHeader(array(
  'x-oy-username' => 'username',
  'x-api-key' => 'api_key',
  'Content-Type' => 'application/json'
));
$request->setBody('{\n    "name": "Acumen Metros",\n    "partner_customer_id": "customer_id",\n    "tax_type": "PPN_10_INCLUSIVE",\n    "address": "address",\n    "email": "email@address.com",\n    "pic_name": "Pic Name",\n    "phone_number": "0812345678",\n    "pph_tax":"PPH_23_NON_NPWP"\n}');
try {
  $response = $request->send();
  if ($response->getStatus() == 200) {
    echo $response->getBody();
  }
  else {
    echo 'Unexpected HTTP status: ' . $response->getStatus() . ' ' .
    $response->getReasonPhrase();
  }
}
catch(HTTP_Request2_Exception $e) {
  echo 'Error: ' . $e->getMessage();
}
import http.client
import json

conn = http.client.HTTPSConnection("partner.oyindonesia.com")
payload = json.dumps({
  "name": "Acumen Metros",
  "partner_customer_id": "customer_id",
  "tax_type": "PPN_10_INCLUSIVE",
  "address": "address",
  "email": "email@address.com",
  "pic_name": "Pic Name",
  "phone_number": "0812345678",
  "pph_tax": "PPH_23_NON_NPWP"
})
headers = {
  'x-oy-username': 'username',
  'x-api-key': 'api_key',
  'Content-Type': 'application/json'
}
conn.request("POST", "/api/account-receivable/customers", payload, headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))

The above command returns JSON structured similar like this:

{
  "data": {
    "id": "8b57cbb0-41f9-48f2-b092-5fa999ddcb15",
    "name": "Acumen Metros",
    "partner_customer_id": "customer_id",
    "tax_type": "PPN_10_INCLUSIVE",
    "address": "address",
    "email": "email@address.com",
    "pic_name": "Pic Name",
    "phone_number": "0812345678",
    "pph_tax": "PPH_23_NON_NPWP",
    "status": "ACTIVE"
  },
  "error": null,
  "status": true,
  "reason": null,
  "status_code": 200
}

HTTPS Request

[Production] POST https://partner.oyindonesia.com/api/account-receivable/customers
[Staging] POST https://api-stg.oyindonesia.com/api/account-receivable/customers

Request Headers

Parameters Type Description
X-Api-Key String API Key for establishing connection to this particular endpoint
X-Oy-Username String The registered partner username which access is enabled for payment link product

Request Parameters

Parameters Type Required Description
name String TRUE Name of a payer / customer for a transaction
partner_customer_id String FALSE A unique customer ID
tax_type NO_TAX / PPN_11_INCLUSIVE / PPN_11_EXCLUSIVE / PPN_10_INCLUSIVE / PPN_10_EXCLUSIVE TRUE PPN Tax type that is applicable for the customer will be reflected in the invoice
address String FALSE Customer's address
email String FALSE The email address where the payment link will be sent to. Max up to 6 email separated by ;
pic_name String FALSE Name of the person in charge for handling the invoice
phone_number String FALSE Phone number of the customer for a transaction. Do not use special character (e.g. +).
pph_tax NO_TAX/ PPH_23_NON_NPWP / PPH_23_NPWP TRUE PPH Tax type that is applicable for the customer will be reflected in the invoice

Response Parameters

Parameters Type Description
success Boolean To determine result of endpoint
error Object Specific code for cause of error and error message
data Object Status of response in Object {id: , partner_customer_id: , status: , name: , tax_type: , address:
, email: , pic_name: , phone_number: , pph_tax: }
id String customer primary id
partner_customer_id String Inputted customer id name
status ACTIVE Customer's status, first creation always active.
name String Name of a customer for a transaction
tax_type NO_TAX / PPN_11_INCLUSIVE / PPN_11_EXCLUSIVE / PPN_10_INCLUSIVE / PPN_10_EXCLUSIVE Result of choosen enum tax type
address String Inputted customer's address
email String Inputted customer's email
pic_name String Inputted PIC name
phone_number String Inputted customer's phone number
pph_tax NO_TAX/ PPH_23_NON_NPWP / PPH_23_NPWP Result of choosen enum
reason String Reserved field to add additional notes for the response
status_code Integer Response Status code

Edit Customer

This endpoint allows update of customer’s data, such as tax information or even deactivation of customer.

curl --location --request PUT 'https://partner.oyindonesia.com/api/account-receivable/customers/8b57cbb0-41f9-48f2-b092-5fa999ddcb15' \
--header 'x-oy-username: username' \
--header 'x-api-key: api_key' \
--header 'Content-Type: application/json' \
--data-raw '{
    "name": "Acumen Metros",
    "partner_customer_id": "customer_id",
    "tax_type": "NO_TAX",
    "address": "",
    "email": "new_email@address.com",
    "pic_name": 123,
    "phone_number": "082143207721",
    "pph_tax": "PPH_23_NON_NPWP",
    "status": "ACTIVE"
}'
var headers = {
  'x-oy-username': 'username',
  'x-api-key': 'api_key',
  'Content-Type': 'application/json'
};
var request = http.Request('PUT', Uri.parse('https://partner.oyindonesia.com/api/account-receivable/customers/8b57cbb0-41f9-48f2-b092-5fa999ddcb15'));
request.body = json.encode({
  "name": "Acumen Metros",
  "partner_customer_id": "customer_id",
  "tax_type": "NO_TAX",
  "address": "",
  "email": "new_email@address.com",
  "pic_name": 123,
  "phone_number": "082143207721",
  "pph_tax": "PPH_23_NON_NPWP",
  "status": "ACTIVE"
});
request.headers.addAll(headers);

http.StreamedResponse response = await request.send();

if (response.statusCode == 200) {
  print(await response.stream.bytesToString());
}
else {
  print(response.reasonPhrase);
}
package main

import (
  "fmt"
  "strings"
  "net/http"
  "io/ioutil"
)

func main() {

  url := "https://partner.oyindonesia.com/api/account-receivable/customers/8b57cbb0-41f9-48f2-b092-5fa999ddcb15"
  method := "PUT"

  payload := strings.NewReader(`{
    "name": "Acumen Metros",
    "partner_customer_id": "customer_id",
    "tax_type": "NO_TAX",
    "address": "",
    "email": "new_email@address.com",
    "pic_name": 123,
    "phone_number": "082143207721",
    "pph_tax": "PPH_23_NON_NPWP",
    "status": "ACTIVE"
}

`)

  client := &http.Client {
  }
  req, err := http.NewRequest(method, url, payload)

  if err != nil {
    fmt.Println(err)
    return
  }
  req.Header.Add("x-oy-username", "username")
  req.Header.Add("x-api-key", "api_key")
  req.Header.Add("Content-Type", "application/json")

  res, err := client.Do(req)
  if err != nil {
    fmt.Println(err)
    return
  }
  defer res.Body.Close()

  body, err := ioutil.ReadAll(res.Body)
  if err != nil {
    fmt.Println(err)
    return
  }
  fmt.Println(string(body))
}
OkHttpClient client = new OkHttpClient().newBuilder()
  .build();
  MediaType mediaType = MediaType.parse("application/json");
  RequestBody body = RequestBody.create(mediaType, "{\n    \"name\": \"Acumen Metros\",\n    \"partner_customer_id\": \"customer_id\",\n    \"tax_type\": \"NO_TAX\",\n    \"address\": \"\",\n    \"email\": \"new_email@address.com\",\n    \"pic_name\": 123,\n    \"phone_number\": \"082143207721\",\n    \"pph_tax\": \"PPH_23_NON_NPWP\",\n    \"status\": \"ACTIVE\"\n}\n\n");
  Request request = new Request.Builder()
  .url("https://partner.oyindonesia.com/api/account-receivable/customers/8b57cbb0-41f9-48f2-b092-5fa999ddcb15")
  .method("PUT", body)
  .addHeader("x-oy-username", "username")
  .addHeader("x-api-key", "api_key")
  .addHeader("Content-Type", "application/json")
  .build();
  Response response = client.newCall(request).execute();
var data = JSON.stringify({
  "name": "Acumen Metros",
  "partner_customer_id": "customer_id",
  "tax_type": "NO_TAX",
  "address": "",
  "email": "new_email@address.com",
  "pic_name": 123,
  "phone_number": "082143207721",
  "pph_tax": "PPH_23_NON_NPWP",
  "status": "ACTIVE"
});

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function() {
  if(this.readyState === 4) {
    console.log(this.responseText);
  }
});

xhr.open("PUT", "https://partner.oyindonesia.com/api/account-receivable/customers/8b57cbb0-41f9-48f2-b092-5fa999ddcb15");
xhr.setRequestHeader("x-oy-username", "username");
xhr.setRequestHeader("x-api-key", "api_key");
xhr.setRequestHeader("Content-Type", "application/json");

xhr.send(data);
<?php
require_once 'HTTP/Request2.php';
$request = new HTTP_Request2();
$request->setUrl('https://partner.oyindonesia.com/api/account-receivable/customers/8b57cbb0-41f9-48f2-b092-5fa999ddcb15');
$request->setMethod(HTTP_Request2::METHOD_PUT);
$request->setConfig(array(
  'follow_redirects' => TRUE
));
$request->setHeader(array(
  'x-oy-username' => 'username',
  'x-api-key' => 'api_key',
  'Content-Type' => 'application/json'
));
$request->setBody('{\n    "name": "Acumen Metros",\n    "partner_customer_id": "customer_id",\n    "tax_type": "NO_TAX",\n    "address": "",\n    "email": "new_email@address.com",\n    "pic_name": 123,\n    "phone_number": "082143207721",\n    "pph_tax": "PPH_23_NON_NPWP",\n    "status": "ACTIVE"\n}\n\n');
try {
  $response = $request->send();
  if ($response->getStatus() == 200) {
    echo $response->getBody();
  }
  else {
    echo 'Unexpected HTTP status: ' . $response->getStatus() . ' ' .
    $response->getReasonPhrase();
  }
}
catch(HTTP_Request2_Exception $e) {
  echo 'Error: ' . $e->getMessage();
}
import http.client
import json

conn = http.client.HTTPSConnection("partner.oyindonesia.com")
payload = json.dumps({
  "name": "Acumen Metros",
  "partner_customer_id": "customer_id",
  "tax_type": "NO_TAX",
  "address": "",
  "email": "new_email@address.com",
  "pic_name": 123,
  "phone_number": "082143207721",
  "pph_tax": "PPH_23_NON_NPWP",
  "status": "ACTIVE"
})
headers = {
  'x-oy-username': 'username',
  'x-api-key': 'api_key',
  'Content-Type': 'application/json'
}
conn.request("PUT", "/api/account-receivable/customers/8b57cbb0-41f9-48f2-b092-5fa999ddcb15", payload, headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))

The above command returns JSON structured similar like this:

{
  "data": {
    "id": "8b57cbb0-41f9-48f2-b092-5fa999ddcb15",
    "name": "Acumen Metros",
    "partner_customer_id": "customer_id",
    "tax_type": "NO_TAX",
    "address": "",
    "email": "new_email@address.com",
    "pic_name": 123,
    "phone_number": "082143207721",
    "pph_tax": "PPH_23_NON_NPWP",
    "status": "ACTIVE"
  },
  "error": null,
  "status": true,
  "reason": null,
  "status_code": 200
}

HTTPS Request

[Production] PUT https://partner.oyindonesia.com/api/account-receivable/customers/:id
[Staging] PUT https://api-stg.oyindonesia.com/api/account-receivable/customers/:id

Request Parameters

Parameters Type Required Description
name String TRUE Name of a customer for a transaction
partner_customer_id String FALSE A unique customer ID
tax_type NO_TAX / PPN_11_INCLUSIVE / PPN_11_EXCLUSIVE / PPN_10_INCLUSIVE / PPN_10_EXCLUSIVE TRUE PPN Tax type that is applicable for the customer will be reflected in the invoice
address String FALSE customer's address
email String FALSE The email address where the payment link will be sent to. Max 6 email separate by ;
pic_name String FALSE Name of the person in charge for handling the invoice
phone_number String with phone pattern FALSE Phone number of the customer for a transaction. Do not use special character (e.g. "+").
pph_tax NO_TAX / PPH_23_NON_NPWP / PPH_23_NPWP TRUE PPH Tax type that is applicable for the customer will be reflected in the invoice
status ACTIVE/INACTIVE TRUE Changing status from Active to Inactive only applicable when there is not outstanding invoice

Response Parameters

Parameters Type Description
success Boolean To determine result of endpoint
error Object Specific code for cause of error and error message
data Object Status of response in Object {id: , partner_customer_id: , status: , name: , tax_type: , address:
, email: , pic_name: , phone_number: , pph_tax: }
id String customer primary id
partner_customer_id String Inputted customer id name
status ACTIVE Customer's status, first creation always active.
name String Name of a customer for a transaction
tax_type NO_TAX / PPN_11_INCLUSIVE / PPN_11_EXCLUSIVE / PPN_10_INCLUSIVE / PPN_10_EXCLUSIVE Result of choosen enum tax type
address String Inputted customer's address
email String Inputted customer's email
pic_name String Inputted PIC name
phone_number String Inputted customer's phone number
pph_tax NO_TAX / PPH_23_NON_NPWP / PPH_23_NPWP Result of choosen enum
reason String Reserved field to add additional notes for the response
status_code Integer Response Status code

Retrieve Customer's Details

This endpoints allow Partners to retrieve existing customers details.

curl --location --request GET 'https://partner.oyindonesia.com/api/account-receivable/customers/8b57cbb0-41f9-48f2-b092-5fa999ddcb15' \
--header 'x-oy-username: username' \
--header 'x-api-key: api_key' 
var headers = {
  'x-oy-username': 'username',
  'x-api-key': 'api_key',

var request = http.Request('GET', Uri.parse('https://partner.oyindonesia.com/api/account-receivable/customers/8b57cbb0-41f9-48f2-b092-5fa999ddcb15'));

request.headers.addAll(headers);

http.StreamedResponse response = await request.send();

if (response.statusCode == 200) {
  print(await response.stream.bytesToString());
}
else {
  print(response.reasonPhrase);
}
package main

import (
  "fmt"
  "net/http"
  "io/ioutil"
)

func main() {

  url := "https://partner.oyindonesia.com/api/account-receivable/customers/8b57cbb0-41f9-48f2-b092-5fa999ddcb15"
  method := "GET"

  client := &http.Client {
  }
  req, err := http.NewRequest(method, url, nil)

  if err != nil {
    fmt.Println(err)
    return
  }
  req.Header.Add("x-oy-username", "username")
  req.Header.Add("x-api-key", "api_key")

  res, err := client.Do(req)
  if err != nil {
    fmt.Println(err)
    return
  }
  defer res.Body.Close()

  body, err := ioutil.ReadAll(res.Body)
  if err != nil {
    fmt.Println(err)
    return
  }
  fmt.Println(string(body))
}
OkHttpClient client = new OkHttpClient().newBuilder()
  .build();
MediaType mediaType = MediaType.parse("text/plain");
RequestBody body = RequestBody.create(mediaType, "");
Request request = new Request.Builder()
  .url("https://partner.oyindonesia.com/api/account-receivable/customers/8b57cbb0-41f9-48f2-b092-5fa999ddcb15")
  .method("GET", body)
  .addHeader("x-oy-username", "username")
  .addHeader("x-api-key", "api_key")
  .build();
Response response = client.newCall(request).execute();
<?php
require_once 'HTTP/Request2.php';
$request = new HTTP_Request2();
$request->setUrl('https://partner.oyindonesia.com/api/account-receivable/customers/8b57cbb0-41f9-48f2-b092-5fa999ddcb15');
$request->setMethod(HTTP_Request2::METHOD_GET);
$request->setConfig(array(
  'follow_redirects' => TRUE
));
$request->setHeader(array(
  'x-oy-username' => 'username',
  'x-api-key' => 'api_key'
));
try {
  $response = $request->send();
  if ($response->getStatus() == 200) {
    echo $response->getBody();
  }
  else {
    echo 'Unexpected HTTP status: ' . $response->getStatus() . ' ' .
    $response->getReasonPhrase();
  }
}
catch(HTTP_Request2_Exception $e) {
  echo 'Error: ' . $e->getMessage();
}
import http.client

conn = http.client.HTTPSConnection("partner.oyindonesia.com")
payload = ''
headers = {
  'x-oy-username': 'username',
  'x-api-key': 'api_key'
}
conn.request("GET", "/api/account-receivable/customers/8b57cbb0-41f9-48f2-b092-5fa999ddcb15", payload, headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))

The above command returns JSON structured similar like this:

{
  "data": {
    "id": "8b57cbb0-41f9-48f2-b092-5fa999ddcb15",
    "status": "ACTIVE",
    "partner_customer_id": "customer_id",
    "name": "Acumen Metros",
    "pic_name": null,
    "phone_number": "082143207721",
    "tax_type": "NO_TAX",
    "pph_tax": "PPH_23_NON_NPWP",
    "email": "new_email@address.com",
    "address": "",
    "total_piutang": 0,
    "can_be_deactivated": true
  },
  "error": null,
  "status": true,
  "reason": null,
  "status_code": 200
}

HTTPS Request

[Production] GET https://partner.oyindonesia.com/api/account-receivable/customers/:id
[Staging] GET https://api-stg.oyindonesia.com/api/account-receivable/customers/:id

Response Parameters

Parameters Type Description
success Boolean To determine result of endpoint
error Object Specific code for cause of error and error message
data Object Status of response in Object {id: , partner_customer_id: , status: , name: , tax_type: , address:
, email: , pic_name: , phone_number: , pph_tax: }
id String customer primary id
partner_customer_id String Inputted customer id name
status ACTIVE Customer's status, first creation always active.
name String Name of a customer for a transaction
tax_type NO_TAX Result of choosen enum tax type
address String Inputted customer's address
email String Inputted customer's email
pic_name String Inputted PIC name
phone_number String Inputted customer's phone number
pph_tax PPH_23_NON_NPWP Result of choosen enum
reason String Reserved field to add additional notes for the response
status_code Integer Response Status code

Filter & Search Customers

This endpoint filters customer data based on criteria that can be set through API

curl --location --request GET 'https://partner.oyindonesia.com/api/account-receivable/customers' \
--header 'x-oy-username: username' \
--header 'x-api-key: api_key' \
--header 'Content-Type: application/json' \
--data-raw '{

}'
var headers = {
  'x-oy-username': 'username',
  'x-api-key': 'api_key',
  'Content-Type': 'application/json'
};
var request = http.Request('GET', Uri.parse('https://partner.oyindonesia.com/api/account-receivable/customers'));
request.body = json.encode({});
request.headers.addAll(headers);

http.StreamedResponse response = await request.send();

if (response.statusCode == 200) {
  print(await response.stream.bytesToString());
}
else {
  print(response.reasonPhrase);
}

package main

import (
  "fmt"
  "strings"
  "net/http"
  "io/ioutil"
)

func main() {

  url := "https://partner.oyindonesia.com/api/account-receivable/customers"
  method := "GET"

  payload := strings.NewReader(`{

}`)

  client := &http.Client {
  }
  req, err := http.NewRequest(method, url, payload)

  if err != nil {
    fmt.Println(err)
    return
  }
  req.Header.Add("x-oy-username", "username")
  req.Header.Add("x-api-key", "api_key")
  req.Header.Add("Content-Type", "application/json")

  res, err := client.Do(req)
  if err != nil {
    fmt.Println(err)
    return
  }
  defer res.Body.Close()

  body, err := ioutil.ReadAll(res.Body)
  if err != nil {
    fmt.Println(err)
    return
  }
  fmt.Println(string(body))
}
OkHttpClient client = new OkHttpClient().newBuilder()
  .build();
  MediaType mediaType = MediaType.parse("application/json");
  RequestBody body = RequestBody.create(mediaType, "{\n    \n}");
  Request request = new Request.Builder()
  .url("https://partner.oyindonesia.com/api/account-receivable/customers")
  .method("GET", body)
  .addHeader("x-oy-username", "username")
  .addHeader("x-api-key", "api_key")
  .addHeader("Content-Type", "application/json")
  .build();
  Response response = client.newCall(request).execute();
<?php
require_once 'HTTP/Request2.php';
$request = new HTTP_Request2();
$request->setUrl('https://partner.oyindonesia.com/api/account-receivable/customers');
$request->setMethod(HTTP_Request2::METHOD_GET);
$request->setConfig(array(
  'follow_redirects' => TRUE
));
$request->setHeader(array(
  'x-oy-username' => 'username',
  'x-api-key' => 'api_key',
  'Content-Type' => 'application/json'
));
$request->setBody('{\n    \n}');
try {
  $response = $request->send();
  if ($response->getStatus() == 200) {
    echo $response->getBody();
  }
  else {
    echo 'Unexpected HTTP status: ' . $response->getStatus() . ' ' .
    $response->getReasonPhrase();
  }
}
catch(HTTP_Request2_Exception $e) {
  echo 'Error: ' . $e->getMessage();
}
import http.client
import json

conn = http.client.HTTPSConnection("partner.oyindonesia.com")
payload = json.dumps({})
headers = {
  'x-oy-username': 'username',
  'x-api-key': 'api_key',
  'Content-Type': 'application/json'
}
conn.request("GET", "/api/account-receivable/customers", payload, headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))

The above command returns JSON structured similar like this:

{
  "data": [
    {
      "id": "8b57cbb0-41f9-48f2-b092-5fa999ddcb15",
      "status": "ACTIVE",
      "partner_customer_id": "customer_id",
      "name": "Acumen Metros",
      "pic_name": null,
      "phone_number": "082143207721",
      "tax_type": "NO_TAX",
      "pph_tax": "PPH_23_NON_NPWP",
      "email": "new_email@address.com",
      "address": "",
      "total_piutang": null,
      "can_be_deactivated": true
    }
  ],
  "error": null,
  "status": true,
  "reason": null,
  "status_code": 200
}

HTTPS Request

[Production] GET https://partner.oyindonesia.com/api/account-receivable/customers?*parameter*
[Staging] GET https://api-stg.oyindonesia.com/api/account-receivable/customers?*parameter*

Request Parameters

Parameters Required Description Example value
limit FALSE Number of records that should be returned to the API 10
offset FALSE Offset number of records 0
status FALSE Filter based on invoice status Possible value: CREATED, OVERDUE, PAID
partner_customer_id FALSE partner customer id name USER001
name FALSE partner customer name Aston
tax_type FALSE Filter based on PPN Tax Type NO_TAX
pph_tax FALSE Filter based on PPh Tax Type PPH_23_NON_NPWP

Response Parameters

Parameters Type Description
success Boolean To determine result of endpoint
error Object Specific code for cause of error and error message
data Object Status of response in Object {id: , partner_customer_id: , status: , name: , tax_type: , address:
, email: , pic_name: , phone_number: , pph_tax: }
id String customer primary id
partner_customer_id String Inputted customer id name
status ACTIVE Customer's status, first creation always active.
name String Name of a customer for a transaction
tax_type NO_TAX Result of choosen enum tax type
address String Inputted customer's address
email String Inputted customer's email
pic_name String Inputted PIC name
phone_number String Inputted customer's phone number
pph_tax PPH_23_NON_NPWP Result of choosen enum
reason String Reserved field to add additional notes for the response
status_code Integer Response Status code

Create & Send Invoice

This endpoint allows Partners to create Account Receivable Invoice through API and send invoice directly to customers via email.

curl --location --request POST 'https://partner.oyindonesia.com/api/account-receivable/invoices' \
--header 'x-oy-username: username' \
--header 'x-api-key: api_key' \
--header 'Content-Type: application/json' \
--data-raw '{
    "invoice_number": "INV/2022/12/210205",
    "invoice_date": "2022-12-21",
    "due_date": "2022-12-25",
    "customer_id": "8b57cbb0-41f9-48f2-b092-5fa999ddcb15",
    "expiration_date":"2022-12-25 12:58:01",
    "invoice_items": [{
        "price_per_item": 25600,
        "description": "kopi susu",
        "quantity": 4
    }],
    "additional_items": [{
        "description": "Diskon",
        "price_per_item": -5000,
        "quantity": 1
    }],
    "message": null,
    "attachments": [],
    "save_as_default_message": false,
    "payment_configuration": {
        "include_admin_fee": true,
        "list_disabled_payment_methods": "OFFLINE_CASH_IN",
        "list_enabled_banks": "002,008,009,013,213",
        "list_enabled_ewallet": "shopeepay_ewallet,linkaja_ewallet,dana_ewallet",
        "list_enabled_offline_channel": ""
    }
}'
var headers = {
  'x-oy-username': 'username',
  'x-api-key': 'api_key',
  'Content-Type': 'application/json'
};
var request = http.Request('POST', Uri.parse('https://partner.oyindonesia.com/api/account-receivable/invoices'));
request.body = json.encode({
  "invoice_number": "INV/2022/12/210205",
  "invoice_date": "2022-12-21",
  "due_date": "2022-12-25",
  "customer_id": "8b57cbb0-41f9-48f2-b092-5fa999ddcb15",
  "expiration_date": "2022-12-25 12:58:01",
  "invoice_items": [
    {
      "price_per_item": 25600,
      "description": "kopi susu",
      "quantity": 4
    }
  ],
  "additional_items": [
    {
      "description": "Diskon",
      "price_per_item": -5000,
      "quantity": 1
    }
  ],
  "message": null,
  "attachments": [],
  "save_as_default_message": false,
  "payment_configuration": {
    "include_admin_fee": true,
    "list_disabled_payment_methods": "OFFLINE_CASH_IN",
    "list_enabled_banks": "002,008,009,013,213",
    "list_enabled_ewallet": "shopeepay_ewallet,linkaja_ewallet,dana_ewallet",
    "list_enabled_offline_channel": ""
  }
});
request.headers.addAll(headers);

http.StreamedResponse response = await request.send();

if (response.statusCode == 200) {
  print(await response.stream.bytesToString());
}
else {
  print(response.reasonPhrase);
}
package main

import (
  "fmt"
  "strings"
  "net/http"
  "io/ioutil"
)

func main() {

  url := "https://partner.oyindonesia.com/api/account-receivable/invoices"
  method := "POST"

  payload := strings.NewReader(`{
    "invoice_number": "INV/2022/12/210205",
    "invoice_date": "2022-12-21",
    "due_date": "2022-12-25",
    "customer_id": "8b57cbb0-41f9-48f2-b092-5fa999ddcb15",
    "expiration_date":"2022-12-25 12:58:01",
    "invoice_items": [{
        "price_per_item": 25600,
        "description": "kopi susu",
        "quantity": 4
    }],
    "additional_items": [{
        "description": "Diskon",
        "price_per_item": -5000,
        "quantity": 1
    }],
    "message": null,
    "attachments": [],
    "save_as_default_message": false,
    "payment_configuration": {
        "include_admin_fee": true,
        "list_disabled_payment_methods": "OFFLINE_CASH_IN",
        "list_enabled_banks": "002,008,009,013,213",
        "list_enabled_ewallet": "shopeepay_ewallet,linkaja_ewallet,dana_ewallet",
        "list_enabled_offline_channel": ""
    }
}`)

  client := &http.Client {
  }
  req, err := http.NewRequest(method, url, payload)

  if err != nil {
    fmt.Println(err)
    return
  }
  req.Header.Add("x-oy-username", "username")
  req.Header.Add("x-api-key", "api_key")
  req.Header.Add("Content-Type", "application/json")

  res, err := client.Do(req)
  if err != nil {
    fmt.Println(err)
    return
  }
  defer res.Body.Close()

  body, err := ioutil.ReadAll(res.Body)
  if err != nil {
    fmt.Println(err)
    return
  }
  fmt.Println(string(body))
}
OkHttpClient client = new OkHttpClient().newBuilder()
  .build();
  MediaType mediaType = MediaType.parse("application/json");
  RequestBody body = RequestBody.create(mediaType, "{\n    \"invoice_number\": \"INV/2022/12/210205\",\n    \"invoice_date\": \"2022-12-21\",\n    \"due_date\": \"2022-12-25\",\n    \"customer_id\": \"8b57cbb0-41f9-48f2-b092-5fa999ddcb15\",\n    \"expiration_date\":\"2022-12-25 12:58:01\",\n    \"invoice_items\": [{\n        \"price_per_item\": 25600,\n        \"description\": \"kopi susu\",\n        \"quantity\": 4\n    }],\n    \"additional_items\": [{\n        \"description\": \"Diskon\",\n        \"price_per_item\": -5000,\n        \"quantity\": 1\n    }],\n    \"message\": null,\n    \"attachments\": [],\n    \"save_as_default_message\": false,\n    \"payment_configuration\": {\n        \"include_admin_fee\": true,\n        \"list_disabled_payment_methods\": \"OFFLINE_CASH_IN\",\n        \"list_enabled_banks\": \"002,008,009,013,213\",\n        \"list_enabled_ewallet\": \"shopeepay_ewallet,linkaja_ewallet,dana_ewallet\",\n        \"list_enabled_offline_channel\": \"\"\n    }\n}");
  Request request = new Request.Builder()
  .url("https://partner.oyindonesia.com/api/account-receivable/invoices")
  .method("POST", body)
  .addHeader("x-oy-username", "username")
  .addHeader("x-api-key", "api_key")
  .addHeader("Content-Type", "application/json")
  .build();
  Response response = client.newCall(request).execute();
// WARNING: For POST requests, body is set to null by browsers.
var data = JSON.stringify({
  "invoice_number": "INV/2022/12/210205",
  "invoice_date": "2022-12-21",
  "due_date": "2022-12-25",
  "customer_id": "8b57cbb0-41f9-48f2-b092-5fa999ddcb15",
  "expiration_date": "2022-12-25 12:58:01",
  "invoice_items": [
    {
      "price_per_item": 25600,
      "description": "kopi susu",
      "quantity": 4
    }
  ],
  "additional_items": [
    {
      "description": "Diskon",
      "price_per_item": -5000,
      "quantity": 1
    }
  ],
  "message": null,
  "attachments": [],
  "save_as_default_message": false,
  "payment_configuration": {
    "include_admin_fee": true,
    "list_disabled_payment_methods": "OFFLINE_CASH_IN",
    "list_enabled_banks": "002,008,009,013,213",
    "list_enabled_ewallet": "shopeepay_ewallet,linkaja_ewallet,dana_ewallet",
    "list_enabled_offline_channel": ""
  }
});

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function() {
  if(this.readyState === 4) {
    console.log(this.responseText);
  }
});

xhr.open("POST", "https://partner.oyindonesia.com/api/account-receivable/invoices");
xhr.setRequestHeader("x-oy-username", "username");
xhr.setRequestHeader("x-api-key", "api_key");
xhr.setRequestHeader("Content-Type", "application/json");

xhr.send(data);
<?php
require_once 'HTTP/Request2.php';
$request = new HTTP_Request2();
$request->setUrl('https://partner.oyindonesia.com/api/account-receivable/invoices');
$request->setMethod(HTTP_Request2::METHOD_POST);
$request->setConfig(array(
  'follow_redirects' => TRUE
));
$request->setHeader(array(
  'x-oy-username' => 'username',
  'x-api-key' => 'api_key',
  'Content-Type' => 'application/json'
));
$request->setBody('{\n    "invoice_number": "INV/2022/12/210205",\n    "invoice_date": "2022-12-21",\n    "due_date": "2022-12-25",\n    "customer_id": "8b57cbb0-41f9-48f2-b092-5fa999ddcb15",\n    "expiration_date":"2022-12-25 12:58:01",\n    "invoice_items": [{\n        "price_per_item": 25600,\n        "description": "kopi susu",\n        "quantity": 4\n    }],\n    "additional_items": [{\n        "description": "Diskon",\n        "price_per_item": -5000,\n        "quantity": 1\n    }],\n    "message": null,\n    "attachments": [],\n    "save_as_default_message": false,\n    "payment_configuration": {\n        "include_admin_fee": true,\n        "list_disabled_payment_methods": "OFFLINE_CASH_IN",\n        "list_enabled_banks": "002,008,009,013,213",\n        "list_enabled_ewallet": "shopeepay_ewallet,linkaja_ewallet,dana_ewallet",\n        "list_enabled_offline_channel": ""\n    }\n}');
try {
  $response = $request->send();
  if ($response->getStatus() == 200) {
    echo $response->getBody();
  }
  else {
    echo 'Unexpected HTTP status: ' . $response->getStatus() . ' ' .
    $response->getReasonPhrase();
  }
}
catch(HTTP_Request2_Exception $e) {
  echo 'Error: ' . $e->getMessage();
}
import http.client
import json

conn = http.client.HTTPSConnection("partner.oyindonesia.com")
payload = json.dumps({
  "invoice_number": "INV/2022/12/210205",
  "invoice_date": "2022-12-21",
  "due_date": "2022-12-25",
  "customer_id": "8b57cbb0-41f9-48f2-b092-5fa999ddcb15",
  "expiration_date": "2022-12-25 12:58:01",
  "invoice_items": [
    {
      "price_per_item": 25600,
      "description": "kopi susu",
      "quantity": 4
    }
  ],
  "additional_items": [
    {
      "description": "Diskon",
      "price_per_item": -5000,
      "quantity": 1
    }
  ],
  "message": None,
  "attachments": [],
  "save_as_default_message": False,
  "payment_configuration": {
    "include_admin_fee": True,
    "list_disabled_payment_methods": "OFFLINE_CASH_IN",
    "list_enabled_banks": "002,008,009,013,213",
    "list_enabled_ewallet": "shopeepay_ewallet,linkaja_ewallet,dana_ewallet",
    "list_enabled_offline_channel": ""
  }
})
headers = {
  'x-oy-username': 'username',
  'x-api-key': 'api_key',
  'Content-Type': 'application/json'
}
conn.request("POST", "/api/account-receivable/invoices", payload, headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))

The above command returns JSON structured similar like this:

{
  "data": {
    "id": "c6733a50-f93b-489f-b12b-48f8cc67735e",
    "invoice_number": "INV/2022/12/210205",
    "invoice_date": "2022-12-21",
    "due_date": "2022-12-25",
    "customer_id": "8b57cbb0-41f9-48f2-b092-5fa999ddcb15",
    "expiration_date": "2022-12-25 12:58:01",
    "invoice_items": [
      {
        "price_per_item": 25600,
        "description": "kopi susu",
        "quantity": 4
      }
    ],
    "additional_items": [
      {
        "description": "Diskon",
        "price_per_item": -5000,
        "quantity": 1
      }
    ],
    "message": "None",
    "attachments": [],
    "save_as_default_message": "False",
    "payment_configuration": {
      "include_admin_fee": "True",
      "list_disabled_payment_methods": "OFFLINE_CASH_IN",
      "list_enabled_banks": "002,008,009,013,213",
      "list_enabled_ewallet": "shopeepay_ewallet,linkaja_ewallet,dana_ewallet",
      "list_enabled_offline_channel": ""
    },
    "payment_url": "https://pay-dev.oyindonesia.com/invoice/c6733a50-f93b-489f-b12b-48f8cc67735e"
  },
  "error": null,
  "status": true,
  "reason": null,
  "status_code": 200
}

HTTPS Request

[Production] POST https://partner.oyindonesia.com/api/account-receivable/invoices
[Staging] POST https://api-stg.oyindonesia.com/api/account-receivable/invoices

Request Parameters

Parameters Type Required Description
invoice_number String TRUE Invoice number for identification purposes
invoice_date Date string with pattern yyyy-MM-dd TRUE The date of the invoice
due_date Date string with pattern yyyy-MM-dd TRUE Must be bigger than present time
customer_id String TRUE Customer must be in ACTIVE state
expiration_date Date string with pattern yyyy-MM-dd HH:mm:ss TRUE Experation date must be bigger than invoice date. Empty string will returns error and Null will be treated as lifetime value.
invoice_items List Object of invoice items TRUE List Invoice Items object, Request in Object {price_per_item: , description: , quantity: }
price_per_item Integer TRUE Minimum is 0
description String TRUE The description of the items
quantity Integer TRUE Minimum is 1
additional_items List Object of additional items FALSE List additional items object. Request in object {price_per_item: , description: , quantity: }
price_per_item Integer TRUE Can be negative to substract total price
description String TRUE The description of the additional items
quantity Integer TRUE Minimum is 1
message String FALSE Additional footnote message inside invoice
attachments String FALSE Max 4 Attachments and need to decode to String base64
payment_configuration Object TRUE Status of request in Object {include_admin_fee: , list_disabled_payment_methods: , list_enabled_banks: , list_enabled_ewallet: , list_enabled_offline_channel: }
include_admin_fee Boolean TRUE true/false
list_disabled_payment_methods String TRUE To configure payment methods to be disabled (e.g. VA, CREDIT_CARD, QRIS, EWALLET). When CREDIT_CARD is included, you are disabling the ‘cards’ payment method as a whole - which means disabling both credit card and debit card. There must be at least 1 payment method is enabled. If this field is not included in the request, or filled with an empty String, then all payment methods will be enabled.
list_enabled_banks String TRUE To configure banks to be enabled for VA payment method. List of eligible bank codes: "002" (BRI), "008" (Mandiri), "009" (BNI), "013" (Permata), "022" (CIMB).
list_enabled_ewallet String TRUE To configure list of e-wallets to be enabled on payment method page
list_enabled_offline_channel String TRUE To configure list of offline channels to be enabled on payment method page

Response Parameters

Parameters Type Description
success Boolean To determine result of endpoint
error Object Specific code for cause of error and error message
data Object Status of response in Object {id: , invoice_number: , invoice_date: , due_date: , customer_id: , expiration_date: , invoice_items: ,additional_items: , message: , attachments: ,save_as_default_message: , payment_configuration: , payment_url: }
id String Unique Payment ID for a specific invoice, that is generated after successful invoice creation.
invoice_number String Invoice number for identification purposes
invoice_date Date string with pattern yyyy-MM-dd The date of the invoice
due_date Date string with pattern yyyy-MM-dd Due date of invoice
customer_id String Customer must be in ACTIVE state
expiration_date Date string with pattern yyyy-MM-dd HH:mm:ss Expiration date of invoice payment.
invoice_items List Object of invoice items List Invoice Items object, Request in Object {price_per_item: , description: , quantity: }
price_per_item Integer Price per item
description String The description of the items
quantity Integer Quantity of item
additional_items List Object of additional items List additional items object. Request in object {price_per_item: , description: , quantity: }
price_per_item Integer Price per additional item
description String The description of the additional items
quantity Integer Quantity of additional item
message String Additional footnote message inside invoice
attachments String Attachment of invoice
payment_configuration Object Status of request in Object {include_admin_fee: , list_disabled_payment_methods: , list_enabled_banks: , list_enabled_ewallet: , list_enabled_offline_channel: }
include_admin_fee Boolean Identifier whether admin fee included or not
list_disabled_payment_methods String List of disabled payment methods.
list_enabled_banks String List of enabled bank for VA payment.
list_enabled_ewallet String List of e-wallet for invoice payment.
list_enabled_offline_channel String List of offline channel
payment_url String Payment link to pay this invoice
reason String Reserved field to add additional notes for the response
status_code Integer Response Status code

Cancel Invoice

An endpoint that allows invoice cancellation after creation

curl --location --request PUT 'https://partner.oyindonesia.com/api/account-receivable/invoices/c6733a50-f93b-489f-b12b-48f8cc67735e' \
--header 'x-oy-username: username' \
--header 'x-api-key: api_key' \
--data-raw ''
var headers = {
  'x-oy-username': 'username',
  'x-api-key': 'api_key'
};
var request = http.Request('PUT', Uri.parse('https://partner.oyindonesia.com/api/account-receivable/invoices/c6733a50-f93b-489f-b12b-48f8cc67735e'));
request.body = '''''';
request.headers.addAll(headers);

http.StreamedResponse response = await request.send();

if (response.statusCode == 200) {
  print(await response.stream.bytesToString());
}
else {
  print(response.reasonPhrase);
}
package main

import (
  "fmt"
  "strings"
  "net/http"
  "io/ioutil"
)

func main() {

  url := "https://partner.oyindonesia.com/api/account-receivable/invoices/c6733a50-f93b-489f-b12b-48f8cc67735e"
  method := "PUT"

  payload := strings.NewReader(``)

  client := &http.Client {
  }
  req, err := http.NewRequest(method, url, payload)

  if err != nil {
    fmt.Println(err)
    return
  }
  req.Header.Add("x-oy-username", "username")
  req.Header.Add("x-api-key", "api_key")

  res, err := client.Do(req)
  if err != nil {
    fmt.Println(err)
    return
  }
  defer res.Body.Close()

  body, err := ioutil.ReadAll(res.Body)
  if err != nil {
    fmt.Println(err)
    return
  }
  fmt.Println(string(body))
}
OkHttpClient client = new OkHttpClient().newBuilder()
  .build();
  MediaType mediaType = MediaType.parse("text/plain");
  RequestBody body = RequestBody.create(mediaType, "");
  Request request = new Request.Builder()
  .url("https://partner.oyindonesia.com/api/account-receivable/invoices/c6733a50-f93b-489f-b12b-48f8cc67735e")
  .method("PUT", body)
  .addHeader("x-oy-username", "username")
  .addHeader("x-api-key", "api_key")
  .build();
  Response response = client.newCall(request).execute();
var data = "";

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function() {
  if(this.readyState === 4) {
    console.log(this.responseText);
  }
});

xhr.open("PUT", "https://partner.oyindonesia.com/api/account-receivable/invoices/c6733a50-f93b-489f-b12b-48f8cc67735e");
xhr.setRequestHeader("x-oy-username", "username");
xhr.setRequestHeader("x-api-key", "api_key");

xhr.send(data);
<?php
require_once 'HTTP/Request2.php';
$request = new HTTP_Request2();
$request->setUrl('https://partner.oyindonesia.com/api/account-receivable/invoices/c6733a50-f93b-489f-b12b-48f8cc67735e');
$request->setMethod(HTTP_Request2::METHOD_PUT);
$request->setConfig(array(
  'follow_redirects' => TRUE
));
$request->setHeader(array(
  'x-oy-username' => 'username',
  'x-api-key' => 'api_key'
));
$request->setBody('');
try {
  $response = $request->send();
  if ($response->getStatus() == 200) {
    echo $response->getBody();
  }
  else {
    echo 'Unexpected HTTP status: ' . $response->getStatus() . ' ' .
    $response->getReasonPhrase();
  }
}
catch(HTTP_Request2_Exception $e) {
  echo 'Error: ' . $e->getMessage();
}
import http.client

conn = http.client.HTTPSConnection("partner.oyindonesia.com")
payload = ''
headers = {
  'x-oy-username': 'username',
  'x-api-key': 'api_key'
}
conn.request("PUT", "/api/account-receivable/invoices/c6733a50-f93b-489f-b12b-48f8cc67735e", payload, headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))

The above command returns JSON structured similar like this:

{
  "success": true,
  "error": null,
  "data": "c6733a50-f93b-489f-b12b-48f8cc67735e",
  "reason": null,
  "status_code": 200
}

HTTPS Request

[Production] PUT https://partner.oyindonesia.com/api/account-receivable/invoices/:id
[Staging] PUT https://api-stg.oyindonesia.com/api/account-receivable/invoices/:id

Request Parameters

Parameters Type Required Description
id String TRUE Unique Payment ID for a specific invoice, that is generated after successful invoice creation.

Response Parameters

Parameters Type Description
success Boolean Determine result of endpoint
error Object If success, this field is null
data String Return invoice id that being cancelled
code String Success status code
message String Success reason message
reason String Reserve field to add additional notes for the response
status_code Integer Response Status code

Get Invoice Details

An endpoints that can provide details of an invoice including amount and status.

curl --location --request GET 'https://partner.oyindonesia.com/api/account-receivable/invoices/c6733a50-f93b-489f-b12b-48f8cc67735e' \
--header 'x-oy-username: username' \
--header 'x-api-key: api_key'
var headers = {
  'x-oy-username': 'username',
  'x-api-key': 'api_key'
};
var request = http.Request('GET', Uri.parse('https://partner.oyindonesia.com/api/account-receivable/invoices/c6733a50-f93b-489f-b12b-48f8cc67735e'));

request.headers.addAll(headers);

http.StreamedResponse response = await request.send();

if (response.statusCode == 200) {
  print(await response.stream.bytesToString());
}
else {
  print(response.reasonPhrase);
}
package main

import (
  "fmt"
  "net/http"
  "io/ioutil"
)

func main() {

  url := "https://partner.oyindonesia.com/api/account-receivable/invoices/c6733a50-f93b-489f-b12b-48f8cc67735e"
  method := "GET"

  client := &http.Client {
  }
  req, err := http.NewRequest(method, url, nil)

  if err != nil {
    fmt.Println(err)
    return
  }
  req.Header.Add("x-oy-username", "username")
  req.Header.Add("x-api-key", "api_key")

  res, err := client.Do(req)
  if err != nil {
    fmt.Println(err)
    return
  }
  defer res.Body.Close()

  body, err := ioutil.ReadAll(res.Body)
  if err != nil {
    fmt.Println(err)
    return
  }
  fmt.Println(string(body))
}
OkHttpClient client = new OkHttpClient().newBuilder()
  .build();
  MediaType mediaType = MediaType.parse("text/plain");
  RequestBody body = RequestBody.create(mediaType, "");
  Request request = new Request.Builder()
  .url("https://partner.oyindonesia.com/api/account-receivable/invoices/c6733a50-f93b-489f-b12b-48f8cc67735e")
  .method("GET", body)
  .addHeader("x-oy-username", "username")
  .addHeader("x-api-key", "api_key")
  .build();
  Response response = client.newCall(request).execute();
// WARNING: For GET requests, body is set to null by browsers.

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function() {
  if(this.readyState === 4) {
    console.log(this.responseText);
  }
});

xhr.open("GET", "https://partner.oyindonesia.com/api/account-receivable/invoices/c6733a50-f93b-489f-b12b-48f8cc67735e");
xhr.setRequestHeader("x-oy-username", "username");
xhr.setRequestHeader("x-api-key", "api_key");

xhr.send();
<?php
require_once 'HTTP/Request2.php';
$request = new HTTP_Request2();
$request->setUrl('https://partner.oyindonesia.com/api/account-receivable/invoices/c6733a50-f93b-489f-b12b-48f8cc67735e');
$request->setMethod(HTTP_Request2::METHOD_GET);
$request->setConfig(array(
  'follow_redirects' => TRUE
));
$request->setHeader(array(
  'x-oy-username' => 'username',
  'x-api-key' => 'api_key'
));
try {
  $response = $request->send();
  if ($response->getStatus() == 200) {
    echo $response->getBody();
  }
  else {
    echo 'Unexpected HTTP status: ' . $response->getStatus() . ' ' .
    $response->getReasonPhrase();
  }
}
catch(HTTP_Request2_Exception $e) {
  echo 'Error: ' . $e->getMessage();
}
import http.client

conn = http.client.HTTPSConnection("partner.oyindonesia.com")
payload = ''
headers = {
  'x-oy-username': 'username',
  'x-api-key': 'api_key'
}
conn.request("GET", "/api/account-receivable/invoices/c6733a50-f93b-489f-b12b-48f8cc67735e", payload, headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))

The above command returns JSON structured similar like this:

{
  "success": true,
  "error": null,
  "data": {
    "id": "c6733a50-f93b-489f-b12b-48f8cc67735e",
    "status": "CANCELLED",
    "customer_id": "8b57cbb0-41f9-48f2-b092-5fa999ddcb15",
    "customer_name": "Acumen Metros",
    "customer_email": "new_email@address.com",
    "customer_phone_number": "082143207721",
    "invoice_number": "INV/2022/12/210205",
    "source_data": "API",
    "message": null,
    "attachments": [],
    "invoice_date": "2022-12-21",
    "payment_date": "2022-12-21 02:22:19",
    "due_date": "2022-12-25",
    "expiration_date": "2022-12-25 12:58:01",
    "amount_billed": 93304.0000,
    "amount_received": 0,
    "admin_fee": null,
    "payment_method": null,
    "payment_url": "https://pay-dev.oyindonesia.com/invoice/c6733a50-f93b-489f-b12b-48f8cc67735e",
    "invoice_items": [
      {
        "description": "kopi susu",
        "quantity": 4,
        "price_per_item": 25600
      }
    ],
    "timeline_invoices": [
      {
        "status": "CREATED",
        "action_stakeholder": "fajardev",
        "action_date": "2022-12-21 02:07:00"
      },
      {
        "status": "CANCELLED",
        "action_stakeholder": "Acumen Metros",
        "action_date": "2022-12-21 02:22:19"
      }
    ]
  },
  "reason": null,
  "status_code": 200
}

HTTPS Request

[Production] GET https://partner.oyindonesia.com/api/account-receivable/invoices/:id
[Staging] GET https://api-stg.oyindonesia.com/api/account-receivable/invoices/:id

Request Parameters

Parameters Type Required Description
id String TRUE Unique Payment ID for a specific invoice, that is generated after successful invoice creation.

Response Parameters

Parameters Type Description
success Boolean To determine result of endpoint
error Object Specific code for cause of error and error message
data Object Status of response in Object {id: , partner_customer_id: , status: , tax_type: , address:
, email: , pic_name: , phone_number: , pph_tax: }
id String Unique Payment ID for a specific invoice, that is generated after successful invoice creation.
status String Default status first time invoice created
customer_id String Customer id for this invoice
customer_name String Inputted Customer name
customer_email String Customer email
customer_phone_number String Customer phone number
invoice_number String Inputted invoice number
source_data String Default value will be "API" when create invoice through API
invoice_date Date string with pattern yyyy-MM-dd Inputted invoice date
payment_date Date string with pattern yyyy-MM-dd HH:mm:ss Date when invoice reach final status(CANCELLED or PAID)
due_date Date string with pattern yyyy-MM-dd Inputted due date
expiration_date Date string with pattern yyyy-MM-dd HH:mm:ss Inputted experation date
amount_billed Integer Sum of billed invoice price
amount_received Integer Sum of paid invoice
invoice_items List Object of invoice items Inputted invoice items
price_per_item Integer Inputed price per items
description String Inputed description
quantity Integer Inputed quantity
message String Inputed message
attachments String inputted attachments
payment_url String Payment link to pay this invoice
timeline_invoices List of object History list of invoice timeline. Object {status:, action_stakeholder: , action_date:}
status String Status of the invoice at a point of time
action_stakeholder String Stakeholder that creates milestones
action_date date date of milestones (when it was create, cancelled, paid)
reason String Reserve Parameter to add additional notes for the response
status_code Integer Response Status code

Filter and Search Invoice

This endpoint allows Partners to filter and search invoices based on certain criteria

curl --location --request GET 'https://partner.oyindonesia.com/api/account-receivable/invoices?limit=10&offset=0&source_data=API' \
--header 'x-oy-username: username' \
--header 'x-api-key: api_key' \
--data-raw ''
var headers = {
  'x-oy-username': 'username',
  'x-api-key': 'api_key'
};
var request = http.Request('GET', Uri.parse('https://partner.oyindonesia.com/api/account-receivable/invoices?limit=10&offset=0&source_data=API'));
request.body = '''''';
request.headers.addAll(headers);

http.StreamedResponse response = await request.send();

if (response.statusCode == 200) {
  print(await response.stream.bytesToString());
}
else {
  print(response.reasonPhrase);
}
package main

import (
  "fmt"
  "strings"
  "net/http"
  "io/ioutil"
)

func main() {

  url := "https://partner.oyindonesia.com/api/account-receivable/invoices?limit=10&offset=0&source_data=API"
  method := "GET"

  payload := strings.NewReader(``)

  client := &http.Client {
  }
  req, err := http.NewRequest(method, url, payload)

  if err != nil {
    fmt.Println(err)
    return
  }
  req.Header.Add("x-oy-username", "username")
  req.Header.Add("x-api-key", "api_key")


  res, err := client.Do(req)
  if err != nil {
    fmt.Println(err)
    return
  }
  defer res.Body.Close()

  body, err := ioutil.ReadAll(res.Body)
  if err != nil {
    fmt.Println(err)
    return
  }
  fmt.Println(string(body))
}
OkHttpClient client = new OkHttpClient().newBuilder()
  .build();
  MediaType mediaType = MediaType.parse("text/plain");
  RequestBody body = RequestBody.create(mediaType, "");
  Request request = new Request.Builder()
  .url("https://partner.oyindonesia.com/api/account-receivable/invoices?limit=10&offset=0&source_data=API")
  .method("GET", body)
  .addHeader("x-oy-username", "username")
  .addHeader("x-api-key", "api_key")
  .build();
  Response response = client.newCall(request).execute();
// WARNING: For GET requests, body is set to null by browsers.
var data = "";

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function() {
  if(this.readyState === 4) {
    console.log(this.responseText);
  }
});

xhr.open("GET", "https://partner.oyindonesia.com/api/account-receivable/invoices?limit=10&offset=0&source_data=API");
xhr.setRequestHeader("x-oy-username", "username");
xhr.setRequestHeader("x-api-key", "api_key");

xhr.send(data);
<?php
require_once 'HTTP/Request2.php';
$request = new HTTP_Request2();
$request->setUrl('https://partner.oyindonesia.com/api/account-receivable/invoices?limit=10&offset=0&source_data=API');
$request->setMethod(HTTP_Request2::METHOD_GET);
$request->setConfig(array(
  'follow_redirects' => TRUE
));
$request->setHeader(array(
  'x-oy-username' => 'username',
  'x-api-key' => 'api_key'
));
$request->setBody('');
try {
  $response = $request->send();
  if ($response->getStatus() == 200) {
    echo $response->getBody();
  }
  else {
    echo 'Unexpected HTTP status: ' . $response->getStatus() . ' ' .
    $response->getReasonPhrase();
  }
}
catch(HTTP_Request2_Exception $e) {
  echo 'Error: ' . $e->getMessage();
}
import http.client

conn = http.client.HTTPSConnection("partner.oyindonesia.com")
payload = ''
headers = {
  'x-oy-username': 'username',
  'x-api-key': 'api_key'
}
conn.request("GET", "/api/account-receivable/invoices?limit=10&offset=0&source_data=API", payload, headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))

The above command returns JSON structured similar like this:

{
  "success": true,
  "error": null,
  "data": {
    "page": 0,
    "total": 1,
    "limit": 10,
    "data": [{
      "id": "c6733a50-f93b-489f-b12b-48f8cc67735e",
      "status": "CANCELLED",
      "customer_id": "8b57cbb0-41f9-48f2-b092-5fa999ddcb15",
      "customer_name": "Acumen Metros",
      "customer_phone_number": "082143207721",
      "invoice_number": "INV/2022/12/210205",
      "source_data": "API",
      "invoice_date": 1671555600000,
      "due_date": 1671901200000,
      "expiration_date": 1671947881000,
      "invoice_items": [{
        "description": "kopi susu",
        "quantity": 4,
        "price_per_item": 25600
      }],
      "message": null,
      "attachments": null,
      "payment_url": "https://pay-dev.oyindonesia.com/invoice/c6733a50-f93b-489f-b12b-48f8cc67735e",
      "payment_date": null,
      "admin_fee": null,
      "amount_billed": 93304,
      "amount_received": 0,
      "customer_email": "new_email@address.com"
    }
    ]
  },
  "reason": null,
  "status_code": 200
}

HTTPS Request

[Production] GET https://partner.oyindonesia.com/api/account-receivable/invoices?*parameter*
[Staging] GET https://api-stg.oyindonesia.com/api/account-receivable/invoices?*parameter*

Request Parameters

Parameters Required Description Example value
limit FALSE Number of records that should be returned to the API 10
offset FALSE Offset number of records 0
source_data FALSE Enum to choose source creation invoice API/DASHBOARD
invoice_number FALSE Filter invoice using invoice number, it can be filtering using spesific value or just contain some text 2022
customer_name FALSE Filter invoice using customer name, it can be filtering using spesific value or just contain some text dev 2
status FALSE Filter invoice using invoice status possible value: CREATED, OVERDUE, PAID, CANCELLED
min_invoice_amount FALSE Filter invoice using minimum invoice amount 10000
max_invoice_amount FALSE Filter invoice using maximum invoice amount 100000

Response Parameters

Parameters Type Description
success Boolean Determine result of endpoint
error Object If success, this field is null
data List of object List of invoice based on filter
code String Success status code
message String Success reason message
reason String Reserve field to add additional notes for the response
status_code Integer Succes status code

Resend Invoice

This endpoint enables Partners to resend their invoices for reminder purposes. The API can be triggered to Email or Whatsapp. For Whatsapp, fees may occur.

curl --location --request POST 'http://172.11.25.113:8080/api/account-receivable/invoices/d24ee55f-7eaf-4269-b932-f123dec6f863/send' \
--header 'x-oy-username: username' \
--header 'x-api-key: api_key' \
--header 'Content-Type: application/json' \
--data-raw '{
    "channel" : "EMAIL"
}'
var headers = {
  'x-oy-username': 'username',
  'x-api-key': 'api_key',
  'Content-Type': 'application/json'
};
var request = http.Request('POST', Uri.parse('https://partner.oyindonesia.com/api/account-receivable/invoices/d24ee55f-7eaf-4269-b932-f123dec6f863/send'));
request.body = json.encode({
  "channel": "EMAIL"
});
request.headers.addAll(headers);

http.StreamedResponse response = await request.send();

if (response.statusCode == 200) {
  print(await response.stream.bytesToString());
}
else {
  print(response.reasonPhrase);
}
package main

import (
  "fmt"
  "strings"
  "net/http"
  "io/ioutil"
)

func main() {

  url := "https://partner.oyindonesia.com/api/account-receivable/invoices/d24ee55f-7eaf-4269-b932-f123dec6f863/send"
  method := "POST"

  payload := strings.NewReader(`{
    "channel" : "EMAIL"
}`)

  client := &http.Client {
  }
  req, err := http.NewRequest(method, url, payload)

  if err != nil {
    fmt.Println(err)
    return
  }
  req.Header.Add("x-oy-username", "username")
  req.Header.Add("x-api-key", "api_key")
  req.Header.Add("Content-Type", "application/json")

  res, err := client.Do(req)
  if err != nil {
    fmt.Println(err)
    return
  }
  defer res.Body.Close()

  body, err := ioutil.ReadAll(res.Body)
  if err != nil {
    fmt.Println(err)
    return
  }
  fmt.Println(string(body))
}
OkHttpClient client = new OkHttpClient().newBuilder()
  .build();
  MediaType mediaType = MediaType.parse("application/json");
  RequestBody body = RequestBody.create(mediaType, "{\n    \"channel\" : \"EMAIL\"\n}");
  Request request = new Request.Builder()
  .url("https://partner.oyindonesia.com/api/account-receivable/invoices/d24ee55f-7eaf-4269-b932-f123dec6f863/send")
  .method("POST", body)
  .addHeader("x-oy-username", "username")
  .addHeader("x-api-key", "api_key")
  .addHeader("Content-Type", "application/json")
  .build();
  Response response = client.newCall(request).execute();
// WARNING: For POST requests, body is set to null by browsers.
var data = JSON.stringify({
  "channel": "EMAIL"
});

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function() {
  if(this.readyState === 4) {
    console.log(this.responseText);
  }
});

xhr.open("POST", "https://partner.oyindonesia.com/api/account-receivable/invoices/d24ee55f-7eaf-4269-b932-f123dec6f863/send");
xhr.setRequestHeader("x-oy-username", "username");
xhr.setRequestHeader("x-api-key", "api_key");
xhr.setRequestHeader("Content-Type", "application/json");

xhr.send(data);
<?php
require_once 'HTTP/Request2.php';
$request = new HTTP_Request2();
$request->setUrl('https://partner.oyindonesia.com/api/account-receivable/invoices/d24ee55f-7eaf-4269-b932-f123dec6f863/send');
$request->setMethod(HTTP_Request2::METHOD_POST);
$request->setConfig(array(
  'follow_redirects' => TRUE
));
$request->setHeader(array(
  'x-oy-username' => 'username',
  'x-api-key' => 'api_key',
  'Content-Type' => 'application/json'
));
$request->setBody('{\n    "channel" : "EMAIL"\n}');
try {
  $response = $request->send();
  if ($response->getStatus() == 200) {
    echo $response->getBody();
  }
  else {
    echo 'Unexpected HTTP status: ' . $response->getStatus() . ' ' .
    $response->getReasonPhrase();
  }
}
catch(HTTP_Request2_Exception $e) {
  echo 'Error: ' . $e->getMessage();
}
import http.client
import json

conn = http.client.HTTPSConnection("partner.oyindonesia.com")
payload = json.dumps({
  "channel": "EMAIL"
})
headers = {
  'x-oy-username': 'username',
  'x-api-key': 'api_key',
  'Content-Type': 'application/json'
}
conn.request("POST", "/api/account-receivable/invoices/d24ee55f-7eaf-4269-b932-f123dec6f863/send", payload, headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))

The above command returns JSON structured similar like this:

{
  "success":true,
  "error":null,
  "data": {
    "channel" : "EMAIL",
    "id": "d24ee55f-7eaf-4269-b932-f123dec6f863"
  },
  "reason":null,
  "status_code":200
}

HTTPS Request

[Production] POST https://partner.oyindonesia.com//api/account-receivable/invoices/b97a9a0d-d635-4e19-9086-031ef541c8c5/send
[Staging] POST https://api-stg.oyindonesia.com//api/account-receivable/invoices/b97a9a0d-d635-4e19-9086-031ef541c8c5/send

Request Parameters

Parameters Type Required Description
channel String True EMAIL-> using partner email; WHATSAPP-> using partner phone number, but there is limit how many partner can use whatspp per day

Response Parameters

Parameters Type Description
success Boolean To determine result of endpoint
error Object Specific code for cause of error and error message
data Object Status of response in Object {id: , channel: }
id String invoice id used in request
channel String Channel used in request (EMAIL or WHATSAPP)
reason String Reserved field to add additional notes for the response
status_code Integer Response Status code

Response Code

Code Description
000 Success
204 Tx Id is not found
210 Billed invoice less than threshold : Rp 10000
223 Invoice status not eligible to cancel
247 Email is not valid
247 Phone number is not valid
300 Failed to cancel invoice with id, please try again
400 Payment configuration can't be null
400 Invoice date can't be null or empty
400 Invoice date is less than today
400 Customer id can't be null or empty
400 Customer ID Not Found
400 Due date can't be null or empty
400 Due date can't before invoice date
400 Invalid expired Date time
400 User is not active
400 Please fix negative price in invoice items
400 Attachments maximum is 4 item
400 Tax type value is invalid
400 Invalid tax type input
400 Pph tax type value is invalid
400 Pph tax can't be null
400 Email address limit is 6
400 Name cannot be null or empty
901 Expiration date exceed invoice time

Default Failed Responses in Each API

These parameters will show up as part of the response parameter.

Parameters Type Description
success Boolean Determine result of endpoint
error Object Specific code for cause of error and error message
data Object Always null, use success to determine the result of request
reason String Reserved field to add additional notes for the response
status_code Integer Response Status code

API Offline

API Offline enables your users to withdraw and deposit money from OY offline channel such as Cash Recycle Machine (CRM) and convenience store.

Initiate Transaction

curl -X \
POST https://partner.oyindonesia.com/api/offline-create \
-H 'content-type: application/json' \
-H 'accept: application/json' \
-H 'x-oy-username:myuser' \
-H 'x-api-key:7654321' \
-d '{
   "partner_trx_id":"withdraw_request_123",
   "receiver_phone_number":"081234567890",
   "customer_id":"customer01",
   "amount":50000,
   "notes":"tagihan21",
   "transaction_type":"CASH_IN",
   "offline_channel":"INDOMARET"
}'
var headers = {
  'Content-Type': 'application/json',
  'x-oy-username': '{{username}}',
  'x-api-key': '{{api-key}}'
};
var request = http.Request('POST', Uri.parse('{{base_url}}/api/offline-create'));
request.body = json.encode({
  "partner_trx_id": "oyonoy-00007",
  "receiver_phone_number": "081234567890",
  "customer_id": "customer01",
  "amount": 50000,
  "notes":"tagihan21",
  "transaction_type": "CASH_IN",
  "offline_channel": "INDOMARET"
});
request.headers.addAll(headers);

http.StreamedResponse response = await request.send();

if (response.statusCode == 200) {
  print(await response.stream.bytesToString());
}
else {
  print(response.reasonPhrase);
}
package main

import (
  "fmt"
  "strings"
  "net/http"
  "io/ioutil"
)

func main() {

  url := "%7B%7Bbase_url%7D%7D/api/offline-create"
  method := "POST"

  payload := strings.NewReader(`{
    "partner_trx_id": "oyonoy-00007",
    "receiver_phone_number": "081234567890",
    "customer_id": "customer01",
    "amount": 50000,
    "notes":"tagihan21",
    "transaction_type": "CASH_IN",
    "offline_channel": "INDOMARET"
}`)

  client := &http.Client {
  }
  req, err := http.NewRequest(method, url, payload)

  if err != nil {
    fmt.Println(err)
    return
  }
  req.Header.Add("Content-Type", "application/json")
  req.Header.Add("x-oy-username", "{{username}}")
  req.Header.Add("x-api-key", "{{api-key}}")

  res, err := client.Do(req)
  if err != nil {
    fmt.Println(err)
    return
  }
  defer res.Body.Close()

  body, err := ioutil.ReadAll(res.Body)
  if err != nil {
    fmt.Println(err)
    return
  }
  fmt.Println(string(body))
}
OkHttpClient client = new OkHttpClient().newBuilder()
  .build();
MediaType mediaType = MediaType.parse("application/json");
RequestBody body = RequestBody.create(mediaType, "{\n    \"partner_trx_id\": \"oyonoy-00007\",\n    \"receiver_phone_number\": \"081223738047\",\n    \"customer_id\": \"customer01\",\n    \"amount\": 50000,\n    \"notes\": \"tagihan21\",\n    \"transaction_type\": \"CASH_IN\",\n    \"offline_channel\": \"INDOMARET\"\n}");
Request request = new Request.Builder()
  .url("{{base_url}}/api/offline-create")
  .method("POST", body)
  .addHeader("Content-Type", "application/json")
  .addHeader("x-oy-username", "{{username}}")
  .addHeader("x-api-key", "{{api-key}}")
  .build();
Response response = client.newCall(request).execute();
var data = JSON.stringify({
  "partner_trx_id": "oyonoy-00007",
  "receiver_phone_number": "081223738047",
  "amount": 50000,
  "notes":"tagihan21",
  "transaction_type": "CASH_IN",
  "offline_channel": "INDOMARET"
});

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function() {
  if(this.readyState === 4) {
    console.log(this.responseText);
  }
});

xhr.open("POST", "%7B%7Bbase_url%7D%7D/api/offline-create");
xhr.setRequestHeader("Content-Type", "application/json");
xhr.setRequestHeader("x-oy-username", "{{username}}");
xhr.setRequestHeader("x-api-key", "{{api-key}}");

xhr.send(data);
<?php
require_once 'HTTP/Request2.php';
$request = new HTTP_Request2();
$request->setUrl('{{base_url}}/api/offline-create');
$request->setMethod(HTTP_Request2::METHOD_POST);
$request->setConfig(array(
  'follow_redirects' => TRUE
));
$request->setHeader(array(
  'Content-Type' => 'application/json',
  'x-oy-username' => '{{username}}',
  'x-api-key' => '{{api-key}}'
));
$request->setBody('{\n    "partner_trx_id": "oyonoy-00007",\n    "receiver_phone_number": "081223738047",\n    "amount": 50000,\n    "notes": "tagihan21",\n    "transaction_type": "CASH_IN",\n    "offline_channel": "INDOMARET"\n}');
try {
  $response = $request->send();
  if ($response->getStatus() == 200) {
    echo $response->getBody();
  }
  else {
    echo 'Unexpected HTTP status: ' . $response->getStatus() . ' ' .
    $response->getReasonPhrase();
  }
}
catch(HTTP_Request2_Exception $e) {
  echo 'Error: ' . $e->getMessage();
}
import http.client
import json

conn = http.client.HTTPSConnection("{{base_url}}")
payload = json.dumps({
  "partner_trx_id": "oyonoy-00007",
  "receiver_phone_number": "081223738047",
  "customer_id": "customer01",
  "amount": 50000,
  "notes":"tagihan21",
  "transaction_type": "CASH_IN",
  "offline_channel": "INDOMARET"
})
headers = {
  'Content-Type': 'application/json',
  'x-oy-username': '{{username}}',
  'x-api-key': '{{api-key}}'
}
conn.request("POST", "/api/offline-create", payload, headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))

The above command returns JSON structured similar like this:

{
    "status": {
        "code": "100",
        "message": "In Progress"
    },
    "amount": 50000,
    "admin_fee": 451,
    "tax_fee": 49,
    "total_amount": 50500,
    "code": "12312313132131",
    "timestamp": "14-10-2020 17:12:16",
    "receiver_phone_number": "+6281234567890",
    "customer_id": "customer01",
    "partner_trx_id": "oyonoy-00007",
    "trx_id": "1234-5678",
    "transaction_type": "CASH_IN",
    "inactive_at": "2020-10-15 10:12:16.786",
    "expired_at": "2020-10-15 10:12:16.786"
}

HTTPS Request

[Production] POST https://partner.oyindonesia.com/api/offline-create
[Staging] TBD

Request Parameters

Parameter Type Required Description
partner_trx_id String(255) TRUE Unique Payout ID for a specific request, generated by partner
receiver_phone_number String(255) FALSE User's phone number
customer_id String(255) TRUE Customer's ID that will be used for withdraw or deposit process
amount BigDecimal TRUE The amount that will be withdrawn or deposit (Only accepts multiplier of 50.000 for cash-out transaction)
notes String(40) FALSE Add notes/description to the transaction.
transaction_type String(255) TRUE Type of transaction. CASH_OUT for withdrawal and CASH_IN for deposit.
offline_channel String(255) TRUE Offline Channel which the transaction will be processed.

Response Parameters

Parameter Type Description
status Object Status of Payout in Object {code: <status_code>, message: <status_message>}
partner_trx_id String(255) Unique Payout ID for a specific request, generated by partner.
trx_id String(36) Unique Payout ID from OY!. Partner can use this ID for settlement.
amount BigDecimal Amount of transaction
tax_fee BigDecimal Amount of tax
admin_fee BigDecimal Amount of admin fee
total_amount BigDecimal Sum of amount, admin fee and tax fee
code String(6) Required unique code for Deposit or Withdrawal process
receiver_phone_number String(255) User's phone number
customer_id String(255) Customer's ID that will be used for withdraw or deposit process
transaction_type String(255) Type of transaction. CASH_OUT for withdrawal and CASH_IN for deposit.
timestamp String(19) Execution time of the request in OY! system ("yyyy-MM-dd HH:mm:ss.SSS")
inactive_at String(19) The time that the unique code will expire and need to be refreshed ("yyyy-MM-dd HH:mm:ss.SSS")
expired_at String(19) The time that the transaction will expire and won't be able to be withdrawn or deposited ("yyyy-MM-dd HH:mm:ss.SSS")

Important Notes inactive_at is only applicable for Alfamart Cash-Out & CRM. Cash-In (Alfamart & Indomaret) code stays valid for 24 hours

Cash-In transaction receives any cash denom starting from 2.000 to 100.000 with minimum amount of 10.000 and maximum amount of 5.000.000 (including admin fee)

admin_fee will be available to you in each transaction and total_amount will reflect the sum of admin_fee, tax and amount

Cancel Transaction

curl -X \
POST https://partner.oyindonesia.com/api/offline-cancel \
-H 'content-type: application/json' \
-H 'accept: application/json' \
-H 'x-oy-username:myuser' \
-H 'x-api-key:7654321' \
-d '{
   "partner_trx_id":"withdraw_request_123"
}'
var headers = {
  'Content-Type': 'application/json',
  'x-oy-username': '{{username}}',
  'x-api-key': '{{api-key}}'
};
var request = http.Request('POST', Uri.parse('{{base_url}}/api/offline-cancel'));
request.body = json.encode({
  "partner_trx_id": "oyonoy-00003"
});
request.headers.addAll(headers);

http.StreamedResponse response = await request.send();

if (response.statusCode == 200) {
  print(await response.stream.bytesToString());
}
else {
  print(response.reasonPhrase);
}
package main

import (
  "fmt"
  "strings"
  "net/http"
  "io/ioutil"
)

func main() {

  url := "%7B%7Bbase_url%7D%7D/api/offline-cancel"
  method := "POST"

  payload := strings.NewReader(`{
    "partner_trx_id": "oyonoy-00003"
}`)

  client := &http.Client {
  }
  req, err := http.NewRequest(method, url, payload)

  if err != nil {
    fmt.Println(err)
    return
  }
  req.Header.Add("Content-Type", "application/json")
  req.Header.Add("x-oy-username", "{{username}}")
  req.Header.Add("x-api-key", "{{api-key}}")

  res, err := client.Do(req)
  if err != nil {
    fmt.Println(err)
    return
  }
  defer res.Body.Close()

  body, err := ioutil.ReadAll(res.Body)
  if err != nil {
    fmt.Println(err)
    return
  }
  fmt.Println(string(body))
}
OkHttpClient client = new OkHttpClient().newBuilder()
  .build();
MediaType mediaType = MediaType.parse("application/json");
RequestBody body = RequestBody.create(mediaType, "{\n    \"partner_trx_id\": \"oyonoy-00003\"\n}");
Request request = new Request.Builder()
  .url("{{base_url}}/api/offline-cancel")
  .method("POST", body)
  .addHeader("Content-Type", "application/json")
  .addHeader("x-oy-username", "{{username}}")
  .addHeader("x-api-key", "{{api-key}}")
  .build();
Response response = client.newCall(request).execute();
var data = JSON.stringify({
  "partner_trx_id": "oyonoy-00003"
});

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function() {
  if(this.readyState === 4) {
    console.log(this.responseText);
  }
});

xhr.open("POST", "%7B%7Bbase_url%7D%7D/api/offline-cancel");
xhr.setRequestHeader("Content-Type", "application/json");
xhr.setRequestHeader("x-oy-username", "{{username}}");
xhr.setRequestHeader("x-api-key", "{{api-key}}");

xhr.send(data);
<?php
require_once 'HTTP/Request2.php';
$request = new HTTP_Request2();
$request->setUrl('{{base_url}}/api/offline-cancel');
$request->setMethod(HTTP_Request2::METHOD_POST);
$request->setConfig(array(
  'follow_redirects' => TRUE
));
$request->setHeader(array(
  'Content-Type' => 'application/json',
  'x-oy-username' => '{{username}}',
  'x-api-key' => '{{api-key}}'
));
$request->setBody('{\n    "partner_trx_id": "oyonoy-00003"\n}');
try {
  $response = $request->send();
  if ($response->getStatus() == 200) {
    echo $response->getBody();
  }
  else {
    echo 'Unexpected HTTP status: ' . $response->getStatus() . ' ' .
    $response->getReasonPhrase();
  }
}
catch(HTTP_Request2_Exception $e) {
  echo 'Error: ' . $e->getMessage();
}
import http.client
import json

conn = http.client.HTTPSConnection("{{base_url}}")
payload = json.dumps({
  "partner_trx_id": "oyonoy-00003"
})
headers = {
  'Content-Type': 'application/json',
  'x-oy-username': '{{username}}',
  'x-api-key': '{{api-key}}'
}
conn.request("POST", "/api/offline-cancel", payload, headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))

The above command returns JSON structured similar like this:

{
    "status": {
        "code":"299",
        "message":"Transaction Canceled"
    },
    "partner_trx_id":"withdraw_request_123",
    "timestamp":"2021-04-05 20:38:23.953"
}

HTTPS Request

[Production] POST https://partner.oyindonesia.com/api/offline-cancel
[Staging] TBD

Request Parameters

Parameter Type Required Description
partner_trx_id String(255) TRUE Unique Payout ID for a specific request, generated by partner

Response Parameters

Parameter Type Description
status Object Status of Payout in Object {code: <status_code>, message: <status_message>}
partner_trx_id String(255) Unique Payout ID for a specific request, generated by partner.
timestamp String(19) Execution time of the request in OY! system ("yyyy-MM-dd HH:mm:ss.SSS")

Important Notes

Cancellation is only applicable for Alfamart Cash-Out & CRM transactions, Cash-In transactions cannot be cancelled.

Transaction Info

curl -X \
POST https://partner.oyindonesia.com/api/offline-info \
-H 'content-type: application/json' \
-H 'accept: application/json' \
-H 'x-oy-username:myuser' \
-H 'x-api-key:7654321' \
-d '{
   "partner_trx_id":"oyonoy-00002",
   "send_callback":"true"
}'
var headers = {
  'Content-Type': 'application/json',
  'x-oy-username': '{{username}}',
  'x-api-key': '{{api-key}}'
};
var request = http.Request('POST', Uri.parse('{{base_url}}/api-offline/tx-info'));
request.body = json.encode({
  "partner_trx_id": "oyonoy-00002",
  "send_callback": false
});
request.headers.addAll(headers);

http.StreamedResponse response = await request.send();

if (response.statusCode == 200) {
  print(await response.stream.bytesToString());
}
else {
  print(response.reasonPhrase);
}
package main

import (
  "fmt"
  "strings"
  "net/http"
  "io/ioutil"
)

func main() {

  url := "%7B%7Bbase_url%7D%7D/api-offline/tx-info"
  method := "POST"

  payload := strings.NewReader(`{
    "partner_trx_id": "oyonoy-00002",
    "send_callback": false
}`)

  client := &http.Client {
  }
  req, err := http.NewRequest(method, url, payload)

  if err != nil {
    fmt.Println(err)
    return
  }
  req.Header.Add("Content-Type", "application/json")
  req.Header.Add("x-oy-username", "{{username}}")
  req.Header.Add("x-api-key", "{{api-key}}")

  res, err := client.Do(req)
  if err != nil {
    fmt.Println(err)
    return
  }
  defer res.Body.Close()

  body, err := ioutil.ReadAll(res.Body)
  if err != nil {
    fmt.Println(err)
    return
  }
  fmt.Println(string(body))
}
OkHttpClient client = new OkHttpClient().newBuilder()
  .build();
MediaType mediaType = MediaType.parse("application/json");
RequestBody body = RequestBody.create(mediaType, "{\n    \"partner_trx_id\": \"oyonoy-00002\",\n    \"send_callback\": false\n}");
Request request = new Request.Builder()
  .url("{{base_url}}/api-offline/tx-info")
  .method("POST", body)
  .addHeader("Content-Type", "application/json")
  .addHeader("x-oy-username", "{{username}}")
  .addHeader("x-api-key", "{{api-key}}")
  .build();
Response response = client.newCall(request).execute();
var data = JSON.stringify({
  "partner_trx_id": "oyonoy-00002",
  "send_callback": false
});

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function() {
  if(this.readyState === 4) {
    console.log(this.responseText);
  }
});

xhr.open("POST", "%7B%7Bbase_url%7D%7D/api-offline/tx-info");
xhr.setRequestHeader("Content-Type", "application/json");
xhr.setRequestHeader("x-oy-username", "{{username}}");
xhr.setRequestHeader("x-api-key", "{{api-key}}");

xhr.send(data);
<?php
require_once 'HTTP/Request2.php';
$request = new HTTP_Request2();
$request->setUrl('{{base_url}}/api-offline/tx-info');
$request->setMethod(HTTP_Request2::METHOD_POST);
$request->setConfig(array(
  'follow_redirects' => TRUE
));
$request->setHeader(array(
  'Content-Type' => 'application/json',
  'x-oy-username' => '{{username}}',
  'x-api-key' => '{{api-key}}'
));
$request->setBody('{\n    "partner_trx_id": "oyonoy-00002",\n    "send_callback": false\n}');
try {
  $response = $request->send();
  if ($response->getStatus() == 200) {
    echo $response->getBody();
  }
  else {
    echo 'Unexpected HTTP status: ' . $response->getStatus() . ' ' .
    $response->getReasonPhrase();
  }
}
catch(HTTP_Request2_Exception $e) {
  echo 'Error: ' . $e->getMessage();
}
import http.client
import json

conn = http.client.HTTPSConnection("{{base_url}}")
payload = json.dumps({
  "partner_trx_id": "oyonoy-00002",
  "send_callback": False
})
headers = {
  'Content-Type': 'application/json',
  'x-oy-username': '{{username}}',
  'x-api-key': '{{api-key}}'
}
conn.request("POST", "/api-offline/tx-info", payload, headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))

The above command returns JSON structured similar like this:

{
    "status": {
        "code": "000",
        "message": "Success"
    },
    "partner_trx_id": "oyonoy-00002",
    "trx_id": "4c466140-6b15-41c7-9499-a01e2978f9ec",
    "amount": 100000.0000,
    "code": "1911452620835003",
    "receiver_phone_number": "+62812123890",
    "customer_id": "customer01",
    "transaction_type": "CASH_IN",
    "offline_channel": "INDOMARET",
    "timestamp": "2022-01-27 15:49:53.707",
    "admin_fee": 4505.0000,
    "tax_fee": 495.0000,
    "total_amount": 105000.0000,
    "inactive_at": "2022-01-26 13:18:52.541",
    "expired_at": "2022-01-26 13:18:52.541"
}

To get status of a transaction request, you can call this API. You may need to call this API few times until getting a final status (success / failed) or you can implement callback transaction.

This API offers an option to send you a callback status of the transaction request to a specific URL. Please contact us and submit a callback URL if you need a callback status of a transaction request.

HTTPS Request

[Production] POST https://partner.oyindonesia.com/api/offline-info
[Staging] TBD

Request Parameters

Parameter Type Required Description
partner_trx_id String(255) TRUE Unique Payout ID for a specific request, generated by partner
send_callback Boolean FALSE A flag to indiciate if the status of the transaction request need to be re-sent as a callback or not

Response Parameters

Parameter Type Description
status Object Status of Payout in Object {code: <status_code>, message: <status_message>}
partner_trx_id String(255) Unique Payout ID for a specific request, generated by partner.
trx_id String(36) Unique Payout ID from OY!. Partner can use this ID for settlement.
amount BigDecimal Amount of transaction
admin_fee BigDecimal Amount of admin fee
tax_fee BigDecimal Amount of tax
total_amount BigDecimal Sum of amount, tax fee and admin fee
code String(6) Required unique code for Deposit or Withdrawal Process
receiver_phone_number String(255) User's phone number
customer_id String(255) Customer's ID that will be used for withdraw or deposit process
transaction_type String(255) Type of transaction. CASH_OUT for withdrawal and CASH_IN for deposit.
offline_channel String(255) Offline channel for transaction. (e.g ALFAMART, INDOMARET or CRM)
timestamp String(19) Execution time of the request in OY! system ("yyyy-MM-dd HH:mm:ss.SSS")
inactive_at String(19) The time that the unique code will expire and need to be refreshed ("yyyy-MM-dd HH:mm:ss.SSS")
expired_at String(19) The time that the transaction will expire and won't be able to be withdrawn or deposited ("yyyy-MM-dd HH:mm:ss.SSS")

Important Notes

inactive_at is only applicable for Alfamart Cash-Out & CRM. Cash-In code stays valid for 24 hours.

Refresh Code

curl -X \
POST https://partner.oyindonesia.com/api/offline-refresh-code \
-H 'content-type: application/json' \
-H 'accept: application/json' \
-H 'x-oy-username:myuser' \
-H 'x-api-key:7654321' \
-d '{
   "partner_trx_id":"withdraw_request_123"
}'
var headers = {
  'Content-Type': 'application/json',
  'x-oy-username': '{{username}}',
  'x-api-key': '{{api-key}}'
};
var request = http.Request('POST', Uri.parse('{{base_url}}/api-offline/refresh-code'));
request.body = json.encode({
  "partner_trx_id": "oyonoy-00002"
});
request.headers.addAll(headers);

http.StreamedResponse response = await request.send();

if (response.statusCode == 200) {
  print(await response.stream.bytesToString());
}
else {
  print(response.reasonPhrase);
}

package main

import (
  "fmt"
  "strings"
  "net/http"
  "io/ioutil"
)

func main() {

  url := "%7B%7Bbase_url%7D%7D/api-offline/refresh-code"
  method := "POST"

  payload := strings.NewReader(`{
    "partner_trx_id": "oyonoy-00002"
}`)

  client := &http.Client {
  }
  req, err := http.NewRequest(method, url, payload)

  if err != nil {
    fmt.Println(err)
    return
  }
  req.Header.Add("Content-Type", "application/json")
  req.Header.Add("x-oy-username", "{{username}}")
  req.Header.Add("x-api-key", "{{api-key}}")

  res, err := client.Do(req)
  if err != nil {
    fmt.Println(err)
    return
  }
  defer res.Body.Close()

  body, err := ioutil.ReadAll(res.Body)
  if err != nil {
    fmt.Println(err)
    return
  }
  fmt.Println(string(body))
}
OkHttpClient client = new OkHttpClient().newBuilder()
  .build();
MediaType mediaType = MediaType.parse("application/json");
RequestBody body = RequestBody.create(mediaType, "{\n    \"partner_trx_id\": \"oyonoy-00002\"\n}");
Request request = new Request.Builder()
  .url("{{base_url}}/api-offline/refresh-code")
  .method("POST", body)
  .addHeader("Content-Type", "application/json")
  .addHeader("x-oy-username", "{{username}}")
  .addHeader("x-api-key", "{{api-key}}")
  .build();
Response response = client.newCall(request).execute();
var data = JSON.stringify({
  "partner_trx_id": "oyonoy-00002"
});

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function() {
  if(this.readyState === 4) {
    console.log(this.responseText);
  }
});

xhr.open("POST", "%7B%7Bbase_url%7D%7D/api-offline/refresh-code");
xhr.setRequestHeader("Content-Type", "application/json");
xhr.setRequestHeader("x-oy-username", "{{username}}");
xhr.setRequestHeader("x-api-key", "{{api-key}}");

xhr.send(data);
<?php
<?php
require_once 'HTTP/Request2.php';
$request = new HTTP_Request2();
$request->setUrl('{{base_url}}/api-offline/refresh-code');
$request->setMethod(HTTP_Request2::METHOD_POST);
$request->setConfig(array(
  'follow_redirects' => TRUE
));
$request->setHeader(array(
  'Content-Type' => 'application/json',
  'x-oy-username' => '{{username}}',
  'x-api-key' => '{{api-key}}'
));
$request->setBody('{\n    "partner_trx_id": "oyonoy-00002"\n}');
try {
  $response = $request->send();
  if ($response->getStatus() == 200) {
    echo $response->getBody();
  }
  else {
    echo 'Unexpected HTTP status: ' . $response->getStatus() . ' ' .
    $response->getReasonPhrase();
  }
}
catch(HTTP_Request2_Exception $e) {
  echo 'Error: ' . $e->getMessage();
}
import http.client
import json

conn = http.client.HTTPSConnection("{{base_url}}")
payload = json.dumps({
  "partner_trx_id": "oyonoy-00002"
})
headers = {
  'Content-Type': 'application/json',
  'x-oy-username': '{{username}}',
  'x-api-key': '{{api-key}}'
}
conn.request("POST", "/api-offline/refresh-code", payload, headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))

The above command returns JSON structured similar like this:

{
    "status": {
        "code": "000",
        "message": "Success"
    },
    "code": "970524",
    "partner_trx_id": "withdraw_request_123",
    "inactive_at": "2020-10-14 13:12:16.786",
    "expired_at": "2020-10-15 10:12:16.786"
}

A transaction is valid for 24 hours with a default 3-hours validity for each unique code (Applicable for CRM transaction). Use this API to refresh the unique code that have expired in which transaction is still valid.

HTTPS Request

[Production] POST https://partner.oyindonesia.com/api/offline-refresh-code
[Staging] TBD

Request Parameters

Parameter Type Required Description
partner_trx_id String(255) TRUE Unique Payout ID for a specific request, generated by partner

Response Parameters

Parameter Type Description
status Object Status of refresh code request in Object {code: <status_code>, message: <status_message>}
code String(6) Required unique code for Deposit or Withdrawal Process
partner_trx_id String(255) Unique Payout ID for a specific request, generated by partner
inactive_at String(19) The time that the unique code will expire and need to be refreshed ("yyyy-MM-dd HH:mm:ss.SSS")
expired_at String(19) The time that the transaction will expire and won't be able to be withdrawn or deposited ("yyyy-MM-dd HH:mm:ss.SSS")

Important Notes

Refresh code is only applicable for Alfamart Cash-Out & CRM transactions, Cash-In transactions cannot be refreshed.

Callback

Response callback:

{
    "status": {
        "code": "000",
        "message": "Success"
    },
    "partner_trx_id": "568c3e91-ffec-446e-8684-5c696eeba2da",
    "trx_id": "4c466140-6b15-41c7-9499-a01e2978f9ec",
    "amount": 100000.0000,
    "code": "1911452620835003",
    "receiver_phone_number": "+62812123890",
    "customer_id": "customer01",
    "transaction_type": "CASH_IN",
    "offline_channel": "INDOMARET",
    "timestamp": "2022-01-27 15:49:53.707",
    "admin_fee": 4505.0000,
    "tax_fee": 495.0000,
    "total_amount": 105000.0000,
    "inactive_at": "2022-01-26 13:18:52.541",
    "expired_at": "2022-01-26 13:18:52.541"
}

Once a transaction request is finished, our system will make a callback status of that transaction request to your system

Please contact us and submit a callback URL if you need a callback status of a transaction request.

Callback Parameters

Parameter Type Description
status Object Status of Payout in Object {code: <status_code>, message: <status_message>}
partner_trx_id String(255) Unique Payout ID for a specific request, generated by partner.
trx_id String(36) Unique Payout ID from OY!. Partner can use this ID for settlement.
amount BigDecimal Amount of transaction
admin_fee BigDecimal Amount of admin fee
tax_fee BigDecimal Amount of tax
total_amount BigDecimal Sum of amount, tax_fee and admin fee
code String(6) Required unique code for Deposit or Withdrawal process
receiver_phone_number String(255) User's phone number
customer_id String(255) Customer's ID that will be used for withdraw or deposit process
transaction_type String(255) Type of transaction. CASH_OUT for withdrawal and CASH_IN for deposit.
offline_channel String(255) Offlien channel of transaction. (e.g ALFAMART, INDOMARET or CRM)
timestamp String(19) Execution time of the request in OY! system ("yyyy-MM-dd HH:mm:ss.SSS")
created_date String(19) Executionn time of trasaction in OY! system ("yyyy-MM-dd HH:mm:ss.SSS")
last_updated_date String(19) Latest status change of a transaction. Example from 'Pending' to 'Success' ("yyyy-MM-dd HH:mm:ss.SSS")

API Offline Response Codes

These are the list of possible status codes for API Offline:

Payment Status State Meaning
000 Final Transaction Request has been completed (SUCCESS)
102 Non-Final Request is In Progress (Waiting for Deposit or Withdrawal)
222 Final Transaction Expired (EXPIRED)
297 Non-Final Cash out/in in-progress
299 Final Transaction Canceled (CANCELED)
300 Final Transaction Failed (FAILED)

The following status codes are for rejected requests

Payment Status State Meaning
201 Final Request is Rejected (User ID is not Found)
202 Final Request is Rejected (User ID is not Active)
203 Final Request is Rejected (Duplicate Partner Tx ID)
204 Final Request is Rejected (Partner Tx ID is Not Found)
206 Final Request is Rejected (Partner Deposit Balance is Not Enough)
207 Final Request is Rejected (Request IP Address is not Registered)
208 Final Request is Rejected (API Key is not Valid)
215 Final Request is Rejected (Invalid denom amount request)
220 Final Request is Rejected (Offline channel is not valid or not elegible to process Withdrawal/Deposit Transaction)
221 Final Request is Rejected (Invalid transaction type)
224 Final Request is Rejected (Amount disburse does not reach Min amount)
225 Final Request is Rejected (Max amount per transaction exceed for disburse)
296 Non-Final There is still an active transaction for this phone number
298 Non-Final Transaction cannot be cancelled
429 Final Request Rejected (Too Many Request to specific endpoint)
990 Final Parameter / object is not valid
999 Final Internal Server Error

API Offline Channel

These are the list of OY! offline channel

Offline Channel Transaction Type
CRM CASH IN, CASH OUT
ALFAMART CASH IN, CASH OUT
INDOMARET CASH IN

and their respective maximum amount per transaction is as follows

Offline Channel Cash Out Cash In
CRM 5.000.000 5.000.000
ALFAMART 2.500.000 5.000.000
INDOMARET N/A 5.000.000

API Transactions Data

API Transactions Data allows you to retrieve your user bank account statement data whom has successfully linked their bank account(s) to OY

import

Account Linking Process

curl --location --request \
POST 'https://partner.oyindonesia.com/api/transaction-data/account/register' \
--header 'X-Api-Key: 1234' \
--header 'x-oy-username: satsat' \
--header 'Content-Type: application/json' \
--data-raw '{
    "partner_user_id": "username0001"
}'
var headers = {
  'X-Oy-Username': '{{username}}',
  'X-Api-Key': '{{api-key}}',
  'Content-Type': 'application/json'
};
var request = http.Request('POST', Uri.parse('{{base_url}}/api/transaction-data/account/register'));
request.body = json.encode({
  "partner_user_id": "bcaaselaasdasd"
});
request.headers.addAll(headers);

http.StreamedResponse response = await request.send();

if (response.statusCode == 200) {
  print(await response.stream.bytesToString());
}
else {
  print(response.reasonPhrase);
}
package main

import (
  "fmt"
  "strings"
  "net/http"
  "io/ioutil"
)

func main() {

  url := "%7B%7Bbase_url%7D%7D/api/transaction-data/account/register"
  method := "POST"

  payload := strings.NewReader(`{
    "partner_user_id": "bcaaselaasdasd"
}`)

  client := &http.Client {
  }
  req, err := http.NewRequest(method, url, payload)

  if err != nil {
    fmt.Println(err)
    return
  }
  req.Header.Add("X-Oy-Username", "{{username}}")
  req.Header.Add("X-Api-Key", "{{api-key}}")
  req.Header.Add("Content-Type", "application/json")

  res, err := client.Do(req)
  if err != nil {
    fmt.Println(err)
    return
  }
  defer res.Body.Close()

  body, err := ioutil.ReadAll(res.Body)
  if err != nil {
    fmt.Println(err)
    return
  }
  fmt.Println(string(body))
}
OkHttpClient client = new OkHttpClient().newBuilder()
  .build();
MediaType mediaType = MediaType.parse("application/json");
RequestBody body = RequestBody.create(mediaType, "{\n    \"partner_user_id\": \"bcaaselaasdasd\"\n}");
Request request = new Request.Builder()
  .url("{{base_url}}/api/transaction-data/account/register")
  .method("POST", body)
  .addHeader("X-Oy-Username", "{{username}}")
  .addHeader("X-Api-Key", "{{api-key}}")
  .addHeader("Content-Type", "application/json")
  .build();
Response response = client.newCall(request).execute();
var data = JSON.stringify({
  "partner_user_id": "bcaaselaasdasd"
});

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function() {
  if(this.readyState === 4) {
    console.log(this.responseText);
  }
});

xhr.open("POST", "%7B%7Bbase_url%7D%7D/api/transaction-data/account/register");
xhr.setRequestHeader("X-Oy-Username", "{{username}}");
xhr.setRequestHeader("X-Api-Key", "{{api-key}}");
xhr.setRequestHeader("Content-Type", "application/json");

xhr.send(data);
<?php
require_once 'HTTP/Request2.php';
$request = new HTTP_Request2();
$request->setUrl('{{base_url}}/api/transaction-data/account/register');
$request->setMethod(HTTP_Request2::METHOD_POST);
$request->setConfig(array(
  'follow_redirects' => TRUE
));
$request->setHeader(array(
  'X-Oy-Username' => '{{username}}',
  'X-Api-Key' => '{{api-key}}',
  'Content-Type' => 'application/json'
));
$request->setBody('{\n    "partner_user_id": "bcaaselaasdasd"\n}');
try {
  $response = $request->send();
  if ($response->getStatus() == 200) {
    echo $response->getBody();
  }
  else {
    echo 'Unexpected HTTP status: ' . $response->getStatus() . ' ' .
    $response->getReasonPhrase();
  }
}
catch(HTTP_Request2_Exception $e) {
  echo 'Error: ' . $e->getMessage();
}
import http.client
import json

conn = http.client.HTTPSConnection("{{base_url}}")
payload = json.dumps({
  "partner_user_id": "bcaaselaasdasd"
})
headers = {
  'X-Oy-Username': '{{username}}',
  'X-Api-Key': '{{api-key}}',
  'Content-Type': 'application/json'
}
conn.request("POST", "/api/transaction-data/account/register", payload, headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))

The above command returns JSON structured similar like this:

{
   {
    "registration_link": "register-transactions.oyindonesia.com/register-transactions/a3cfeaf9c84047708545cbd650b47afe",
    "token": "a3cfeaf9c84047708545cbd650b47afe",
    "status": {
        "code": "000",
        "message": "Success"
    }
}
}

Use this API to link a bank account so it's historical transaction data can be retrieved.

HTTPS Request

[Production] POST https://partner.oyindonesia.com/api/transaction-data/account/register
[Staging] UPCOMING

Header Parameters

Parameter Type Required Description
X-Oy-Username String TRUE Partner username
X-Api-Key String TRUE Partner API Key

Request Parameters

Parameter Type Required Description
partner_user_id String TRUE A unique identifier of a user which transaction data will be retrieved

Response Parameters

Parameter Type Description
registration_link String Registration link
token String Registration link token to validate the registration link
status Object Status of request registration link {code: <status_code>, message: <status_message>}

Once a link is returned with its temporary token, user will need to access the link and input their banking credentials by checking the consent check box for the product’s terms and condition and clicking the “Register” button.

User will be prompted with a page to notify that the linking process is still in progress since the process might take a few minutes. User can safely close the pop-up and linking status can be checked using API Check Registration Status endpoint.

List of Response Codes

Code Description
000 Success
201 User is not found
202 User is not active
207 IP Address is not registered
208 API Key is not valid
900 Unexpected error

Check Registration Status

  curl --location --request \
  POST 'https://partner.oyindonesia.com/api/transaction-data/account/check-registration-status' \
--header 'X-Api-Key: 1234' \
--header 'x-oy-username: satsat' \
--header 'Content-Type: application/json' \
--data-raw '{
    "registration_token": "a3cfeaf9c84047708545cbd650b47afe"
}'
var headers = {
  'X-Api-Key': '{{api-key}}',
  'X-Oy-Username': '{{username}}',
  'Content-Type': 'application/json'
};
var request = http.Request('POST', Uri.parse('{{base_url}}/api/transaction-data/account/check-registration-status'));
request.body = json.encode({
  "registration_token": "92b63472b854432cbce516eda3a1dab3"
});
request.headers.addAll(headers);

http.StreamedResponse response = await request.send();

if (response.statusCode == 200) {
  print(await response.stream.bytesToString());
}
else {
  print(response.reasonPhrase);
}
package main

import (
  "fmt"
  "strings"
  "net/http"
  "io/ioutil"
)

func main() {

  url := "%7B%7Bbase_url%7D%7D/api/transaction-data/account/check-registration-status"
  method := "POST"

  payload := strings.NewReader(`{
    "registration_token": "92b63472b854432cbce516eda3a1dab3"
}`)

  client := &http.Client {
  }
  req, err := http.NewRequest(method, url, payload)

  if err != nil {
    fmt.Println(err)
    return
  }
  req.Header.Add("X-Api-Key", "{{api-key}}")
  req.Header.Add("X-Oy-Username", "{{username}}")
  req.Header.Add("Content-Type", "application/json")

  res, err := client.Do(req)
  if err != nil {
    fmt.Println(err)
    return
  }
  defer res.Body.Close()

  body, err := ioutil.ReadAll(res.Body)
  if err != nil {
    fmt.Println(err)
    return
  }
  fmt.Println(string(body))
}
OkHttpClient client = new OkHttpClient().newBuilder()
  .build();
MediaType mediaType = MediaType.parse("application/json");
RequestBody body = RequestBody.create(mediaType, "{\n    \"registration_token\": \"92b63472b854432cbce516eda3a1dab3\"\n}");
Request request = new Request.Builder()
  .url("{{base_url}}/api/transaction-data/account/check-registration-status")
  .method("POST", body)
  .addHeader("X-Api-Key", "{{api-key}}")
  .addHeader("X-Oy-Username", "{{username}}")
  .addHeader("Content-Type", "application/json")
  .build();
Response response = client.newCall(request).execute();
var data = JSON.stringify({
  "registration_token": "92b63472b854432cbce516eda3a1dab3"
});

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function() {
  if(this.readyState === 4) {
    console.log(this.responseText);
  }
});

xhr.open("POST", "%7B%7Bbase_url%7D%7D/api/transaction-data/account/check-registration-status");
xhr.setRequestHeader("X-Api-Key", "{{api-key}}");
xhr.setRequestHeader("X-Oy-Username", "{{username}}");
xhr.setRequestHeader("Content-Type", "application/json");

xhr.send(data);
<?php
require_once 'HTTP/Request2.php';
$request = new HTTP_Request2();
$request->setUrl('{{base_url}}/api/transaction-data/account/check-registration-status');
$request->setMethod(HTTP_Request2::METHOD_POST);
$request->setConfig(array(
  'follow_redirects' => TRUE
));
$request->setHeader(array(
  'X-Api-Key' => '{{api-key}}',
  'X-Oy-Username' => '{{username}}',
  'Content-Type' => 'application/json'
));
$request->setBody('{\n    "registration_token": "92b63472b854432cbce516eda3a1dab3"\n}');
try {
  $response = $request->send();
  if ($response->getStatus() == 200) {
    echo $response->getBody();
  }
  else {
    echo 'Unexpected HTTP status: ' . $response->getStatus() . ' ' .
    $response->getReasonPhrase();
  }
}
catch(HTTP_Request2_Exception $e) {
  echo 'Error: ' . $e->getMessage();
}
import http.client
import json

conn = http.client.HTTPSConnection("{{base_url}}")
payload = json.dumps({
  "registration_token": "92b63472b854432cbce516eda3a1dab3"
})
headers = {
  'X-Api-Key': '{{api-key}}',
  'X-Oy-Username': '{{username}}',
  'Content-Type': 'application/json'
}
conn.request("POST", "/api/transaction-data/account/check-registration-status", payload, headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))

The above command returns JSON structured similar like this, when the registration is in process:

{
    "permanent_token": null,
    "status": {
        "code": "102",
        "message": "Request is In progress"
    }
}

The above command returns JSON structured similar like this, when token on the payload is invalid:

{
    "permanent_token": null,
    "status": {
        "code": "237",
        "message": "Temporary token is invalid"
    }
}

The above command returns JSON structured similar like this, when the registration is success:

{
    "permanent_token": "f2eaf327ec23dac249d82dc75734941b5e3752f9583ab5752ca9292d6d4eb1dc",
    "status": {
        "code": "000",
        "message": "Success"
    }
}

Use this API to check the status of a bank account registration/linking process

HTTPS Request

[Production] POST https://partner.oyindonesia.com/api/transaction-data/account/check-registration-status
[Staging] UPCOMING

Header Parameters

Parameter Type Required Description
X-Oy-Username String TRUE Partner username
X-Api-Key String TRUE Partner API Key

Request Parameters

Parameter Type Required Description
registration_token string TRUE Registration token

Response Parameters

Parameter Type Description
permanent_token String The token to be used to retrieve users' banking historical transaction data
status Object The status of a bank account registration/linking process {code: <status_code>, message: <status_message>}

List of Response Codes

Code Description
000 Success
102 In progress
201 User is not found
202 User is not active
207 IP Address is not registered
208 API Key is not valid
237 Invalid temporary token
300 Failed
900 Unexpected error

List of Registered Accounts

  curl --location --request \
  POST 'https://partner.oyindonesia.com/api/transaction-data/account/registered-accounts' \
--header 'X-Api-Key: 1234' \
--header 'x-oy-username: satsat' \
--header 'Content-Type: application/json' \
--data-raw '{
    "partner_user_id": "username0001"
}'
var headers = {
  'X-Api-Key': '{{api-key}}',
  'x-oy-username': '{{username}}',
  'Content-Type': 'application/json'
};
var request = http.Request('POST', Uri.parse('{{base_url}}/api/transaction-data/account/registered-accounts'));
request.body = json.encode({
  "partner_user_id": "satria123"
});
request.headers.addAll(headers);

http.StreamedResponse response = await request.send();

if (response.statusCode == 200) {
  print(await response.stream.bytesToString());
}
else {
  print(response.reasonPhrase);
}
package main

import (
  "fmt"
  "strings"
  "net/http"
  "io/ioutil"
)

func main() {

  url := "%7B%7Bbase_url%7D%7D/api/transaction-data/account/registered-accounts"
  method := "POST"

  payload := strings.NewReader(`{
    "partner_user_id": "satria123"
}`)

  client := &http.Client {
  }
  req, err := http.NewRequest(method, url, payload)

  if err != nil {
    fmt.Println(err)
    return
  }
  req.Header.Add("X-Api-Key", "{{api-key}}")
  req.Header.Add("x-oy-username", "{{username}}")
  req.Header.Add("Content-Type", "application/json")

  res, err := client.Do(req)
  if err != nil {
    fmt.Println(err)
    return
  }
  defer res.Body.Close()

  body, err := ioutil.ReadAll(res.Body)
  if err != nil {
    fmt.Println(err)
    return
  }
  fmt.Println(string(body))
}
OkHttpClient client = new OkHttpClient().newBuilder()
  .build();
MediaType mediaType = MediaType.parse("application/json");
RequestBody body = RequestBody.create(mediaType, "{\n    \"partner_user_id\": \"satria123\"\n}");
Request request = new Request.Builder()
  .url("{{base_url}}/api/transaction-data/account/registered-accounts")
  .method("POST", body)
  .addHeader("X-Api-Key", "{{api-key}}")
  .addHeader("x-oy-username", "{{username}}")
  .addHeader("Content-Type", "application/json")
  .build();
Response response = client.newCall(request).execute();
var data = JSON.stringify({
  "partner_user_id": "satria123"
});

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function() {
  if(this.readyState === 4) {
    console.log(this.responseText);
  }
});

xhr.open("POST", "%7B%7Bbase_url%7D%7D/api/transaction-data/account/registered-accounts");
xhr.setRequestHeader("X-Api-Key", "{{api-key}}");
xhr.setRequestHeader("x-oy-username", "{{username}}");
xhr.setRequestHeader("Content-Type", "application/json");

xhr.send(data);
<?php
require_once 'HTTP/Request2.php';
$request = new HTTP_Request2();
$request->setUrl('{{base_url}}/api/transaction-data/account/registered-accounts');
$request->setMethod(HTTP_Request2::METHOD_POST);
$request->setConfig(array(
  'follow_redirects' => TRUE
));
$request->setHeader(array(
  'X-Api-Key' => '{{api-key}}',
  'x-oy-username' => '{{username}}',
  'Content-Type' => 'application/json'
));
$request->setBody('{\n    "partner_user_id": "satria123"\n}');
try {
  $response = $request->send();
  if ($response->getStatus() == 200) {
    echo $response->getBody();
  }
  else {
    echo 'Unexpected HTTP status: ' . $response->getStatus() . ' ' .
    $response->getReasonPhrase();
  }
}
catch(HTTP_Request2_Exception $e) {
  echo 'Error: ' . $e->getMessage();
}
import http.client
import json

conn = http.client.HTTPSConnection("{{base_url}}")
payload = json.dumps({
  "partner_user_id": "satria123"
})
headers = {
  'X-Api-Key': '{{api-key}}',
  'x-oy-username': '{{username}}',
  'Content-Type': 'application/json'
}
conn.request("POST", "/api/transaction-data/account/registered-accounts", payload, headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))

The above command returns JSON structured similar like this:

{
    "data": [
        {
            "bank_code": "014",
            "account_numbers": [
                "0952736319"
            ],
            "permanent_token": "69e6a50a90d71f2191aab78b1a184acbb96b898a0b0833361cc45e9a0b5d7fcb",
            "linking_date": "2021-04-30 03:11:03",
            "account_status": "ACTIVE",
            "account_type": "INDIVIDUAL"
        },
        {
            "bank_code": "014",
            "account_numbers": [
                "0952736319"
            ],
            "permanent_token": "d2f61174a3c0c98c8f736a964e13b06865bde95cf88aebc264732593ebfe4a1e",
            "linking_date": "2021-04-29 06:47:45",
            "account_status": "ACTIVE",
            "account_type": "INDIVIDUAL"
        },
    ],
    "status": {
        "code": "000",
        "message": "Success"
    }
}

Use this API to retrieve bank accounts related information of a user ID that has been successfully linked to a user ID

HTTPS Request

[Production] POST https://partner.oyindonesia.com/api/transaction-data/account/registered-accounts
[Staging] UPCOMING

Header Parameters

Parameter Type Required Description
X-Oy-Username String TRUE Partner username
X-Api-Key String TRUE Partner API Key

Request Parameters

Parameter Type Required Description
partner_user_id String TRUE A unique identifier of a user which transaction data will be retrieved

Response Parameters

Parameter Type Description
data array of Object Array of registered account data { bank_code: string, bank_account_number: string[], permanent_token: string linking_date: string, account_status: string }
status Object The status of a bank account registration/linking process {code: <status_code>, message: <status_message>}

List of Response Codes

Code Description
000 Success
201 User is not found
202 User is not active
207 IP Address is not registered
208 API Key is not valid
244 Invalid partner user id
900 Unexpected error

Bank Codes

These are the lis of available bank on our API Transactions Data service:

Bank Code Bank Name Limitation
008 Mandiri Maximum of 12 months historical account statement data
014 BCA Maximum of 3 months historical account statement data
009 BNI Maximum of 6 months historical account statement data

Initialize Account Statement

  curl --location --request \
  POST 'https://partner.oyindonesia.com/api/transaction-data/account-statement/init' \
--header 'X-Api-Key: 1234' \
--header 'X-Oy-Username: satsat' \
--header 'Content-Type: application/json' \
--data-raw '{
    "account_number": "8691502376",
    "bank_code": "014",
    "account_type": "INDIVIDUAL",
    "start_date": "2021-02-13",
    "end_date": "2021-04-13",
    "permanent_token": "f2eaf327ec23dac249d82dc75734941b5e3752f9583ab5752ca9292d6d4eb1dc",
var headers = {
  'X-Api-Key': '{{api-key}}',
  'X-Oy-Username': '{{username}}',
  'Content-Type': 'application/json'
};
var request = http.Request('POST', Uri.parse('{{base_url}}/api/transaction-data/account-statement/init'));
request.body = json.encode({
  "account_number": "8691502376",
  "bank_code": "014",
  "account_type": "INDIVIDUAL",
  "start_date": "2021-02-13",
  "end_date": "2021-04-13",
  "permanent_token": "e57ff5bc6e6c6aaa0a13a2418e69a5e2e0e4190b68662533688680fd2192d0a7",
  "ignore_start_date": true
});
request.headers.addAll(headers);

http.StreamedResponse response = await request.send();

if (response.statusCode == 200) {
  print(await response.stream.bytesToString());
}
else {
  print(response.reasonPhrase);
}
package main

import (
  "fmt"
  "strings"
  "net/http"
  "io/ioutil"
)

func main() {

  url := "%7B%7Bbase_url%7D%7D/api/transaction-data/account-statement/init"
  method := "POST"

  payload := strings.NewReader(`{
    "account_number": "8691502376",
    "bank_code": "014",
    "account_type": "INDIVIDUAL",
    "start_date": "2021-02-13",
    "end_date": "2021-04-13",
    "permanent_token": "e57ff5bc6e6c6aaa0a13a2418e69a5e2e0e4190b68662533688680fd2192d0a7",
    "ignore_start_date": true
}`)

  client := &http.Client {
  }
  req, err := http.NewRequest(method, url, payload)

  if err != nil {
    fmt.Println(err)
    return
  }
  req.Header.Add("X-Api-Key", "{{api-key}}")
  req.Header.Add("X-Oy-Username", "{{username}}")
  req.Header.Add("Content-Type", "application/json")

  res, err := client.Do(req)
  if err != nil {
    fmt.Println(err)
    return
  }
  defer res.Body.Close()

  body, err := ioutil.ReadAll(res.Body)
  if err != nil {
    fmt.Println(err)
    return
  }
  fmt.Println(string(body))
}
OkHttpClient client = new OkHttpClient().newBuilder()
  .build();
MediaType mediaType = MediaType.parse("application/json");
RequestBody body = RequestBody.create(mediaType, "{\n    \"account_number\": \"8691502376\",\n    \"bank_code\": \"014\",\n    \"account_type\": \"INDIVIDUAL\",\n    \"start_date\": \"2021-02-13\",\n    \"end_date\": \"2021-04-13\",\n    \"permanent_token\": \"e57ff5bc6e6c6aaa0a13a2418e69a5e2e0e4190b68662533688680fd2192d0a7\",\n    \"ignore_start_date\": true\n}");
Request request = new Request.Builder()
  .url("{{base_url}}/api/transaction-data/account-statement/init")
  .method("POST", body)
  .addHeader("X-Api-Key", "{{api-key}}")
  .addHeader("X-Oy-Username", "{{username}}")
  .addHeader("Content-Type", "application/json")
  .build();
Response response = client.newCall(request).execute();
var data = JSON.stringify({
  "account_number": "8691502376",
  "bank_code": "014",
  "account_type": "INDIVIDUAL",
  "start_date": "2021-02-13",
  "end_date": "2021-04-13",
  "permanent_token": "e57ff5bc6e6c6aaa0a13a2418e69a5e2e0e4190b68662533688680fd2192d0a7",
  "ignore_start_date": true
});

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function() {
  if(this.readyState === 4) {
    console.log(this.responseText);
  }
});

xhr.open("POST", "%7B%7Bbase_url%7D%7D/api/transaction-data/account-statement/init");
xhr.setRequestHeader("X-Api-Key", "{{api-key}}");
xhr.setRequestHeader("X-Oy-Username", "{{username}}");
xhr.setRequestHeader("Content-Type", "application/json");

xhr.send(data);
<?php
require_once 'HTTP/Request2.php';
$request = new HTTP_Request2();
$request->setUrl('{{base_url}}/api/transaction-data/account-statement/init');
$request->setMethod(HTTP_Request2::METHOD_POST);
$request->setConfig(array(
  'follow_redirects' => TRUE
));
$request->setHeader(array(
  'X-Api-Key' => '{{api-key}}',
  'X-Oy-Username' => '{{username}}',
  'Content-Type' => 'application/json'
));
$request->setBody('{\n    "account_number": "8691502376",\n    "bank_code": "014",\n    "account_type": "INDIVIDUAL",\n    "start_date": "2021-02-13",\n    "end_date": "2021-04-13",\n    "permanent_token": "e57ff5bc6e6c6aaa0a13a2418e69a5e2e0e4190b68662533688680fd2192d0a7",\n    "ignore_start_date": true\n}');
try {
  $response = $request->send();
  if ($response->getStatus() == 200) {
    echo $response->getBody();
  }
  else {
    echo 'Unexpected HTTP status: ' . $response->getStatus() . ' ' .
    $response->getReasonPhrase();
  }
}
catch(HTTP_Request2_Exception $e) {
  echo 'Error: ' . $e->getMessage();
}
import http.client
import json

conn = http.client.HTTPSConnection("{{base_url}}")
payload = json.dumps({
  "account_number": "8691502376",
  "bank_code": "014",
  "account_type": "INDIVIDUAL",
  "start_date": "2021-02-13",
  "end_date": "2021-04-13",
  "permanent_token": "e57ff5bc6e6c6aaa0a13a2418e69a5e2e0e4190b68662533688680fd2192d0a7",
  "ignore_start_date": True
})
headers = {
  'X-Api-Key': '{{api-key}}',
  'X-Oy-Username': '{{username}}',
  'Content-Type': 'application/json'
}
conn.request("POST", "/api/transaction-data/account-statement/init", payload, headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))

The above command returns JSON structured similar like this, when success:

{
    "account_statement_id": "ljhahd12je8sdca93",
    "status": {
        "code": "102",
        "message": "Preparing data"
    }
}

The above command returns JSON structured similar like this, when failed:

{
    "account_statement_id": null,
    "status": {
        "code": "101",
        "message": "Bank account not found"
    }
}

Use this API to initialize the account statement data to be fetched. Upon successful account statement initialization, Partner will receive a callback that a data is ready.

HTTPS Request

[Production] POST https://partner.oyindonesia.com/api/transaction-data/account-statement/init
[Staging] UPCOMING

Header Parameters

Parameter Type Required Description
X-Oy-Username String TRUE Partner username
X-Api-Key String TRUE Partner API Key

Request Parameters

Parameter Type Required Description
bank_code String TRUE The bank code of the user's bank account (please refer to the Bank Codes section)
account_type String TRUE Type of bank accounts (currently only "Individual" is available)
account_number String TRUE The account number which data will be retrieved that has been successfully linked
start_date String TRUE Start date of account statement in "YYYY-MM-dd" format
end_date String TRUE End date of account statement in "YYYY-MM-dd" format
permanent_token String TRUE Permanent token to access credentials related to account number

Response Parameters

Parameter Type Description
account_statement_id Array of Object ID of account statement used for fetching the data, if the data is available
status Object The status of initialization account statement process {code: <status_code>, message: <status_message>}

List of Response Codes

Code Description
000 Success
101 Request is processed
201 User is not found
202 User is not active
207 IP Address is not registered
208 API Key is not valid
211 Bank code is not available for this service
238 Invalid permanent token
242 Start date tx data unavailable
300 Failed
900 Unexpected error
990 Invalid object or parameter

Get Account Statement

  curl --location --request \
  GET 'https://partner.oyindonesia.com/api/transaction-data/account-statement/mutations?id=ljhahd12je8sdca93&page=1' \
--header 'x-oy-username: satsat3' \
--header 'x-api-key: 1234' \
var headers = {
  'X-Oy-Username': '{{username}}',
  'x-api-key': '{{api-key}}'
};
var request = http.Request('GET', Uri.parse('{{base_url}}/api/transaction-data/account-statement/mutations?id=f60e3cc3-2404-4c00-ba17-eacd690cf72b&page=1'));

request.headers.addAll(headers);

http.StreamedResponse response = await request.send();

if (response.statusCode == 200) {
  print(await response.stream.bytesToString());
}
else {
  print(response.reasonPhrase);
}
package main

import (
  "fmt"
  "net/http"
  "io/ioutil"
)

func main() {

  url := "%7B%7Bbase_url%7D%7D/api/transaction-data/account-statement/mutations?id=f60e3cc3-2404-4c00-ba17-eacd690cf72b&page=1"
  method := "GET"

  client := &http.Client {
  }
  req, err := http.NewRequest(method, url, nil)

  if err != nil {
    fmt.Println(err)
    return
  }
  req.Header.Add("X-Oy-Username", "{{username}}")
  req.Header.Add("x-api-key", "{{api-key}}")

  res, err := client.Do(req)
  if err != nil {
    fmt.Println(err)
    return
  }
  defer res.Body.Close()

  body, err := ioutil.ReadAll(res.Body)
  if err != nil {
    fmt.Println(err)
    return
  }
  fmt.Println(string(body))
}
OkHttpClient client = new OkHttpClient().newBuilder()
  .build();
Request request = new Request.Builder()
  .url("{{base_url}}/api/transaction-data/account-statement/mutations?id=f60e3cc3-2404-4c00-ba17-eacd690cf72b&page=1")
  .method("GET", null)
  .addHeader("X-Oy-Username", "{{username}}")
  .addHeader("x-api-key", "{{api-key}}")
  .build();
Response response = client.newCall(request).execute();

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function() {
  if(this.readyState === 4) {
    console.log(this.responseText);
  }
});

xhr.open("GET", "%7B%7Bbase_url%7D%7D/api/transaction-data/account-statement/mutations?id=f60e3cc3-2404-4c00-ba17-eacd690cf72b&page=1");
xhr.setRequestHeader("X-Oy-Username", "{{username}}");
xhr.setRequestHeader("x-api-key", "{{api-key}}");

xhr.send();
<?php
require_once 'HTTP/Request2.php';
$request = new HTTP_Request2();
$request->setUrl('{{base_url}}/api/transaction-data/account-statement/mutations?id=f60e3cc3-2404-4c00-ba17-eacd690cf72b&page=1');
$request->setMethod(HTTP_Request2::METHOD_GET);
$request->setConfig(array(
  'follow_redirects' => TRUE
));
$request->setHeader(array(
  'X-Oy-Username' => '{{username}}',
  'x-api-key' => '{{api-key}}'
));
try {
  $response = $request->send();
  if ($response->getStatus() == 200) {
    echo $response->getBody();
  }
  else {
    echo 'Unexpected HTTP status: ' . $response->getStatus() . ' ' .
    $response->getReasonPhrase();
  }
}
catch(HTTP_Request2_Exception $e) {
  echo 'Error: ' . $e->getMessage();
}
import http.client

conn = http.client.HTTPSConnection("{{base_url}}")
payload = ''
headers = {
  'X-Oy-Username': '{{username}}',
  'x-api-key': '{{api-key}}'
}
conn.request("GET", "/api/transaction-data/account-statement/mutations?id=f60e3cc3-2404-4c00-ba17-eacd690cf72b&page=1", payload, headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))

The above command returns JSON structured similar like this, when success:

{
  "data": [
    {
        "date": "2021-03-01",
        "description": "Transfer from Aldo Adiyasa",
        "type": "DB",
        "amount": 1000000
    }
  ],
  "status": {
    "code": "103",
    "message": "Data ready for retrieval"
  }
}

The above command returns JSON structured similar like this, when failed:

{
  "data": [],
  "status": {
    "code": "300",
    "message": "Failed"
  }
}

The above command returns JSON structured similar like this, when in progress:

{
  "data": [],
  "status": {
    "code": "102",
    "message": "Preparing data"
  }
}

Use this API to fetch transaction details based on initialized account statements

HTTPS Request

[Production] GET https://partner.oyindonesia.com/api/transaction-data/account-statement/mutations?id=[account_statement_id]&page=[page_number]
[Staging] UPCOMING

Header Parameters

Parameter Type Required Description
X-Oy-Username String TRUE Partner username
X-Api-Key String TRUE Partner API Key

Request Query Parameters

Parameter Type Required Description
id String TRUE Id of account statement
page Integer TRUE Pagination offset - each page contains max. of 1000 row of transactions

Response Parameters

Parameter Type Description
data Array of Object List of object { date: <timestamp>, id: <id>, description: <description>, type: <CR/DB>, amount: <amount> }
status Object The status of get account statement process {code: <status_code>, message: <status_message>}

List of Response Codes

Code Description
000 Success
101 Request is processed
201 User is not found
202 User is not active
207 IP Address is not registered
208 API Key is not valid
209 Bank account number is not found
211 Bank code is not available for this service
238 Invalid permanent token
239 Account statement is not found
240 Failed when trying to login to internet banking
242 Start date tx data unavailable
300 Failed
900 Unexpected error
990 Invalid object or parameter

Check Account Statement Status/Callback

  curl --location --request \
  POST 'https://partner.oyindonesia.com/api/transaction-data/account-statement/status' \
  --header 'X-Oy-Username: satsat' \
  --header 'x-api-key: 1234' \
  --header 'Content-Type: application/json' \
  --data-raw '{
      "id": "eb74c36d-efb3-4b98-97aa-ad23940e4cde",
      "send_callback": false
  }'
var headers = {
  'X-Oy-Username': '{{username}}',
  'x-api-key': '{{api-key}}',
  'Content-Type': 'application/json'
};
var request = http.Request('POST', Uri.parse('{{base_url}}/api/transaction-data/account-statement/status'));
request.body = json.encode({
  "id": "39064c75-6c46-48c3-9756-719e9b0d2081",
  "send_callback": false
});
request.headers.addAll(headers);

http.StreamedResponse response = await request.send();

if (response.statusCode == 200) {
  print(await response.stream.bytesToString());
}
else {
  print(response.reasonPhrase);
}
package main

import (
  "fmt"
  "strings"
  "net/http"
  "io/ioutil"
)

func main() {

  url := "%7B%7Bbase_url%7D%7D/api/transaction-data/account-statement/status"
  method := "POST"

  payload := strings.NewReader(`{
    "id": "39064c75-6c46-48c3-9756-719e9b0d2081",
    "send_callback": false
}`)

  client := &http.Client {
  }
  req, err := http.NewRequest(method, url, payload)

  if err != nil {
    fmt.Println(err)
    return
  }
  req.Header.Add("X-Oy-Username", "{{username}}")
  req.Header.Add("x-api-key", "{{api-key}}")
  req.Header.Add("Content-Type", "application/json")

  res, err := client.Do(req)
  if err != nil {
    fmt.Println(err)
    return
  }
  defer res.Body.Close()

  body, err := ioutil.ReadAll(res.Body)
  if err != nil {
    fmt.Println(err)
    return
  }
  fmt.Println(string(body))
}
OkHttpClient client = new OkHttpClient().newBuilder()
  .build();
MediaType mediaType = MediaType.parse("application/json");
RequestBody body = RequestBody.create(mediaType, "{\n    \"id\": \"39064c75-6c46-48c3-9756-719e9b0d2081\",\n    \"send_callback\": false\n}");
Request request = new Request.Builder()
  .url("{{base_url}}/api/transaction-data/account-statement/status")
  .method("POST", body)
  .addHeader("X-Oy-Username", "{{username}}")
  .addHeader("x-api-key", "{{api-key}}")
  .addHeader("Content-Type", "application/json")
  .build();
Response response = client.newCall(request).execute();
var data = JSON.stringify({
  "id": "39064c75-6c46-48c3-9756-719e9b0d2081",
  "send_callback": false
});

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function() {
  if(this.readyState === 4) {
    console.log(this.responseText);
  }
});

xhr.open("POST", "%7B%7Bbase_url%7D%7D/api/transaction-data/account-statement/status");
xhr.setRequestHeader("X-Oy-Username", "{{username}}");
xhr.setRequestHeader("x-api-key", "{{api-key}}");
xhr.setRequestHeader("Content-Type", "application/json");

xhr.send(data);
<?php
require_once 'HTTP/Request2.php';
$request = new HTTP_Request2();
$request->setUrl('{{base_url}}/api/transaction-data/account-statement/status');
$request->setMethod(HTTP_Request2::METHOD_POST);
$request->setConfig(array(
  'follow_redirects' => TRUE
));
$request->setHeader(array(
  'X-Oy-Username' => '{{username}}',
  'x-api-key' => '{{api-key}}',
  'Content-Type' => 'application/json'
));
$request->setBody('{\n    "id": "39064c75-6c46-48c3-9756-719e9b0d2081",\n    "send_callback": false\n}');
try {
  $response = $request->send();
  if ($response->getStatus() == 200) {
    echo $response->getBody();
  }
  else {
    echo 'Unexpected HTTP status: ' . $response->getStatus() . ' ' .
    $response->getReasonPhrase();
  }
}
catch(HTTP_Request2_Exception $e) {
  echo 'Error: ' . $e->getMessage();
}
import http.client
import json

conn = http.client.HTTPSConnection("{{base_url}}")
payload = json.dumps({
  "id": "39064c75-6c46-48c3-9756-719e9b0d2081",
  "send_callback": False
})
headers = {
  'X-Oy-Username': '{{username}}',
  'x-api-key': '{{api-key}}',
  'Content-Type': 'application/json'
}
conn.request("POST", "/api/transaction-data/account-statement/status", payload, headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))

The above command returns JSON structured similar like this:

{
    "total_transactions": 3000,
    "total_pages": 3,
    "status": {
        "code": "103",
        "message": "Data ready for retrieval"
    }
}

Use this API to check/re-send callbacks for initialized account statements. This endpoint should also be used to check how many pages an account statement has.

HTTPS Request

[Production] POST https://partner.oyindonesia.com/api/transaction-data/account-statement/status
[Staging] UPCOMING

Header Parameters

Parameter Type Required Description
X-Oy-Username String TRUE Partner username
X-Api-Key String TRUE Partner API Key

Request Parameters

Parameter Type Required Description
id String TRUE Id of account statement
send_callback Boolean TRUE Flag to indicate if callback need to be resend or not

Response Parameters

Parameter Type Description
total_transactions Integer Amount of transactions in account statement
total_pages Integer Amount of pages in account statement
status Object The status of check status of get account statement process {code: <status_code>, message: <status_message>}

List of Response Codes

Code Description
000 Success
101 Request is processed
201 User is not found
202 User is not active
207 IP Address is not registered
208 API Key is not valid
209 Bank account number is not found
211 Bank code is not available for this service
238 Invalid permanent token
239 Account statement is not found
240 Failed when trying to login to internet banking
242 Start date tx data unavailable
300 Failed
900 Unexpected error
990 Invalid object or parameter

Account Deactivate Process

  curl --location --request \
  POST 'https://partner.oyindonesia.com/api/transaction-data/account/unlink' \
  --header 'X-Api-Key: 1234' \
  --header 'x-oy-username: satsat' \
  --header 'Content-Type: application/json' \
  --data-raw '{
      "permanent_token": "f2eaf327ec23dac249d82dc75734941b5e3752f9583ab5752ca9292d6d4eb1dc",
      "partner_user_id": "username0001"
  }'
var headers = {
  'x-oy-username': '{{username}}',
  'x-api-key': '{{api-key}}',
  'Content-Type': 'application/json'
};
var request = http.Request('POST', Uri.parse('{{base_url}}/api/transaction-data/account/unlink'));
request.body = json.encode({
  "permanent_token": "f7ad0693c203017d7991dd016aa2dc492855f5e5b947932d09959fb466710bc9",
  "partner_user_id": "username123"
});
request.headers.addAll(headers);

http.StreamedResponse response = await request.send();

if (response.statusCode == 200) {
  print(await response.stream.bytesToString());
}
else {
  print(response.reasonPhrase);
}
package main

import (
  "fmt"
  "strings"
  "net/http"
  "io/ioutil"
)

func main() {

  url := "%7B%7Bbase_url%7D%7D/api/transaction-data/account/unlink"
  method := "POST"

  payload := strings.NewReader(`{
    "permanent_token": "f7ad0693c203017d7991dd016aa2dc492855f5e5b947932d09959fb466710bc9",
    "partner_user_id": "username123"
}`)

  client := &http.Client {
  }
  req, err := http.NewRequest(method, url, payload)

  if err != nil {
    fmt.Println(err)
    return
  }
  req.Header.Add("x-oy-username", "{{username}}")
  req.Header.Add("x-api-key", "{{api-key}}")
  req.Header.Add("Content-Type", "application/json")

  res, err := client.Do(req)
  if err != nil {
    fmt.Println(err)
    return
  }
  defer res.Body.Close()

  body, err := ioutil.ReadAll(res.Body)
  if err != nil {
    fmt.Println(err)
    return
  }
  fmt.Println(string(body))
}
OkHttpClient client = new OkHttpClient().newBuilder()
  .build();
MediaType mediaType = MediaType.parse("application/json");
RequestBody body = RequestBody.create(mediaType, "{\n    \"permanent_token\": \"f7ad0693c203017d7991dd016aa2dc492855f5e5b947932d09959fb466710bc9\",\n    \"partner_user_id\": \"username123\"\n}");
Request request = new Request.Builder()
  .url("{{base_url}}/api/transaction-data/account/unlink")
  .method("POST", body)
  .addHeader("x-oy-username", "{{username}}")
  .addHeader("x-api-key", "{{api-key}}")
  .addHeader("Content-Type", "application/json")
  .build();
Response response = client.newCall(request).execute();
var data = JSON.stringify({
  "permanent_token": "f7ad0693c203017d7991dd016aa2dc492855f5e5b947932d09959fb466710bc9",
  "partner_user_id": "username123"
});

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function() {
  if(this.readyState === 4) {
    console.log(this.responseText);
  }
});

xhr.open("POST", "%7B%7Bbase_url%7D%7D/api/transaction-data/account/unlink");
xhr.setRequestHeader("x-oy-username", "{{username}}");
xhr.setRequestHeader("x-api-key", "{{api-key}}");
xhr.setRequestHeader("Content-Type", "application/json");

xhr.send(data);
<?php
require_once 'HTTP/Request2.php';
$request = new HTTP_Request2();
$request->setUrl('{{base_url}}/api/transaction-data/account/unlink');
$request->setMethod(HTTP_Request2::METHOD_POST);
$request->setConfig(array(
  'follow_redirects' => TRUE
));
$request->setHeader(array(
  'x-oy-username' => '{{username}}',
  'x-api-key' => '{{api-key}}',
  'Content-Type' => 'application/json'
));
$request->setBody('{\n    "permanent_token": "f7ad0693c203017d7991dd016aa2dc492855f5e5b947932d09959fb466710bc9",\n    "partner_user_id": "username123"\n}');
try {
  $response = $request->send();
  if ($response->getStatus() == 200) {
    echo $response->getBody();
  }
  else {
    echo 'Unexpected HTTP status: ' . $response->getStatus() . ' ' .
    $response->getReasonPhrase();
  }
}
catch(HTTP_Request2_Exception $e) {
  echo 'Error: ' . $e->getMessage();
}
import http.client
import json

conn = http.client.HTTPSConnection("{{base_url}}")
payload = json.dumps({
  "permanent_token": "f7ad0693c203017d7991dd016aa2dc492855f5e5b947932d09959fb466710bc9",
  "partner_user_id": "username123"
})
headers = {
  'x-oy-username': '{{username}}',
  'x-api-key': '{{api-key}}',
  'Content-Type': 'application/json'
}
conn.request("POST", "/api/transaction-data/account/unlink", payload, headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))

The above command returns JSON structured similar like this:

{
     "status": {
        "code": "000",
        "message": "Success"
    }
}

Use this API to revoke access to a user’s banking credential. This endpoint is mandatory for Partner to provide to its users so they can revoke Partner’s access to user’s banking information at anytime.

HTTPS Request

[Production] POST https://partner.oyindonesia.com/api/transaction-data/account/unlink
[Staging] UPCOMING

Header Parameters

Parameter Type Required Description
X-Oy-Username String TRUE Partner username
X-Api-Key String TRUE Partner API Key

Request Parameters

Parameter Type Required Description
permanent_token String TRUE The token that is retrieved after successful linking
partner_user_id String TRUE A unique identifier of a user

Response Parameters

Parameter Type Description
status Object Status of account deactivate process {code: <status_code>, message: <status_message>}

List of Response Codes

Code Description
000 Success
201 User is not found
202 User is not active
207 IP Address is not registered
208 API Key is not valid
238 Invalid permanent token
900 Unexpected error

API E-Wallet Aggregator

E-Wallet Aggregator API allows partners to seamlessly charge and receive payments directly from top e-wallet issuers. With one integration, they are able to get access to all of OY’s available e-wallets ((OVO, ShopeePay, LinkAja, and DANA) and upcoming e-wallet integrations.

Create E-Wallet Transaction

Use this API to create an e-wallet transaction for your user

HTTPS Request

[Production] POST https://partner.oyindonesia.com/api/e-wallet-aggregator/create-transaction

[Staging] POST https://api-stg.oyindonesia.com/api/e-wallet-aggregator/create-transaction

Request Headers

Parameter Type Description
X-Api-Key String API Key used to connect to this particular endpoint
X-Oy-Username String Your OY! account username

Request Parameters

curl -X POST \
  <%= config[:endpoint_prod] %>/api/e-wallet-aggregator/create-transaction \
  -H 'content-type: application/json' \
  -H 'accept: application/json' \
  -H 'x-api-key: yourapikey' \
  -H 'x-oy-username: yourusername' \
  -d '{
        "customer_id": "your_customer_user_id",
        "partner_trx_id": "YAYBC123456527",
        "sub_merchant_id": "sprx88989F",
        "amount": 125000,
        "email": "mirajane@yahoo.com",
        "ewallet_code": "dana_ewallet",
        "mobile_number": "628091486790",
        "success_redirect_url":"https://yourweb.com/usertx/123456",
        "expiration_time": 120
    }'
var headers = {
  'Content-Type': 'application/json',
  'X-Oy-Username': '{{username}}',
  'X-Api-Key': '{{api-key}}'
};
var request = http.Request('POST', Uri.parse('{{base_url}}/api/e-wallet-aggregator/create-transaction'));
request.body = json.encode({
 "customer_id": "my_user_id",
 "partner_trx_id": "ABC123456527",
 "sub_merchant_id": "zx88989F",
 "amount": 75000,
 "email": "johndoe@gmail.com",
 "ewallet_code": "shopeepay_ewallet",
 "mobile_number": "6282114845847",
 "success_redirect_url":"https://myweb.com/usertx/123456",
 "expiration_time": 15
});
request.headers.addAll(headers);

http.StreamedResponse response = await request.send();

if (response.statusCode == 200) {
  print(await response.stream.bytesToString());
}
else {
  print(response.reasonPhrase);
}
package main

import (
  "fmt"
  "strings"
  "net/http"
  "io/ioutil"
)

func main() {

  url := "%7B%7Bbase_url%7D%7D/api/e-wallet-aggregator/create-transaction"
  method := "POST"

  payload := strings.NewReader(`{
     "customer_id": "my_user_id",
     "partner_trx_id": "ABC123456527",
     "sub_merchant_id": "zx88989F",
     "amount": 75000,
     "email": "johndoe@gmail.com",
     "ewallet_code": "shopeepay_ewallet",
     "mobile_number": "6282114845847",
     "success_redirect_url":"https://myweb.com/usertx/123456",
     "expiration_time": 15
}`)

  client := &http.Client {
  }
  req, err := http.NewRequest(method, url, payload)

  if err != nil {
    fmt.Println(err)
    return
  }
  req.Header.Add("Content-Type", "application/json")
  req.Header.Add("X-Oy-Username", "{{username}}")
  req.Header.Add("X-Api-Key", "{{api-key}}")

  res, err := client.Do(req)
  if err != nil {
    fmt.Println(err)
    return
  }
  defer res.Body.Close()

  body, err := ioutil.ReadAll(res.Body)
  if err != nil {
    fmt.Println(err)
    return
  }
  fmt.Println(string(body))
}
OkHttpClient client = new OkHttpClient().newBuilder()
  .build();
MediaType mediaType = MediaType.parse("application/json");
RequestBody body = RequestBody.create(mediaType, "{\n\t\"customer_id\": \"my_user_id\",\n\t\"partner_trx_id\": \"ABC123456527\",\n\t\"sub_merchant_id\": \"zx88989F\",\n\t\"amount\": 75000,\n\t\"email\": \"john.doe@email.com\",\n\t\"ewallet_code\": \"shopeepay_ewallet\",\n\t\"mobile_number\": \"6282114845847\",\n\t\"expiration_time\": 15,\n\t\"success_redirect_url\": \"https://myweb.com/usertx/123456\"\n}");
Request request = new Request.Builder()
  .url("{{base_url}}/api/e-wallet-aggregator/create-transaction")
  .method("POST", body)
  .addHeader("Content-Type", "application/json")
  .addHeader("X-Oy-Username", "{{username}}")
  .addHeader("X-Api-Key", "{{api-key}}")
  .build();
Response response = client.newCall(request).execute();
var data = JSON.stringify({
    "customer_id": "my_user_id",
    "partner_trx_id": "ABC123456527",
    "sub_merchant_id": "zx88989F",
    "amount": 75000,
    "email": "johndoe@gmail.com",
    "ewallet_code": "shopeepay_ewallet",
    "mobile_number": "6282114845847",
    "success_redirect_url":"https://myweb.com/usertx/123456",
    "expiration_time": 15
});

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function() {
  if(this.readyState === 4) {
    console.log(this.responseText);
  }
});

xhr.open("POST", "%7B%7Bbase_url%7D%7D/api/e-wallet-aggregator/create-transaction");
xhr.setRequestHeader("Content-Type", "application/json");
xhr.setRequestHeader("X-Oy-Username", "{{username}}");
xhr.setRequestHeader("X-Api-Key", "{{api-key}}");

xhr.send(data);
<?php
require_once 'HTTP/Request2.php';
$request = new HTTP_Request2();
$request->setUrl('{{base_url}}/api/e-wallet-aggregator/create-transaction');
$request->setMethod(HTTP_Request2::METHOD_POST);
$request->setConfig(array(
  'follow_redirects' => TRUE
));
$request->setHeader(array(
  'Content-Type' => 'application/json',
  'X-Oy-Username' => '{{username}}',
  'X-Api-Key' => '{{api-key}}'
));
$request->setBody('{\n  "customer_id": "my_user_id",\n "partner_trx_id": "ABC123456527",\n "sub_merchant_id": "zx88989F",\n "amount": 75000,\n  "email": "johndoe@gmail.com",\n "ewallet_code": "shopeepay_ewallet",\n  "mobile_number": "6282114845847",\n "success_redirect_url":"https://myweb.com/usertx/123456",\n "expiration_time": 15\n}');
try {
  $response = $request->send();
  if ($response->getStatus() == 200) {
    echo $response->getBody();
  }
  else {
    echo 'Unexpected HTTP status: ' . $response->getStatus() . ' ' .
    $response->getReasonPhrase();
  }
}
catch(HTTP_Request2_Exception $e) {
  echo 'Error: ' . $e->getMessage();
}
import http.client
import json

conn = http.client.HTTPSConnection("{{base_url}}")
payload = json.dumps({
  "customer_id": "my_user_id",
  "partner_trx_id": "ABC123456527",
  "sub_merchant_id": "zx88989F",
  "amount": 75000,
  "email": "johndoe@gmail.com",
  "ewallet_code": "shopeepay_ewallet",
  "mobile_number": "6282114845847",
  "success_redirect_url":"https://myweb.com/usertx/123456",
  "expiration_time": 15
})
headers = {
  'Content-Type': 'application/json',
  'X-Oy-Username': '{{username}}',
  'X-Api-Key': '{{api-key}}'
}
conn.request("POST", "/api/e-wallet-aggregator/create-transaction", payload, headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))

The above command returns JSON structured similar like this:

{
    "status": {
        "code": "000",
        "message": "Success"
    },
    "ewallet_trx_status": "WAITING_PAYMENT",
    "amount": 500000,
    "trx_id": "789467agf238893894rfcw7978iu7g7e",
    "customer_id": "my_user_id",
    "partner_trx_id": "ABC123456527",
    "ewallet_code": "shopeepay_ewallet",
    "ewallet_url": "https://someewalletlink.com"
}
Parameter Type Required Default Description
customer_id String(255) TRUE - ID generated by Partner for a specific user/customer
sub_merchant_id String(255) FALSE - ID generated by Partner for a specific sub-merchant
partner_trx_id String(255) TRUE - ID generated by Partner for a specific transaction
amount BigDecimal TRUE - Transaction amount. Min = 100. Max = 10,000,000
email String(255) FALSE - Customer's email
ewallet_code String(255) TRUE - The ewallet issuer that the customer will use to pay. Refer to table "E-Wallet Details" for the list of codes
mobile_number String(255) CONDITIONAL - Customer mobile number (format 628xxxxxxxxxx) used on their ewallet account. Only required if ewallet_code is equal to "ovo_ewallet"
success_redirect_url String(255) CONDITIONAL - Indicates the URL of your environment (to redirect the customers back once payment has been completed in e-wallet issuers.) Accepts HTTP links and URL scheme formats. Required if ewallet_code = DANA or LINKAJA or SHOPEEPAY.
expiration_time Long FALSE Maximum expiration time (in minutes) for each ewallet issuer Expiration time of the transaction in minute e.g If you want the transaction to be expired after 5 minutes, you just have to set expiration_time to 5. Each ewallet type might have different expiration time rule, please see table "E-Wallet Details"

Response Parameters

Parameter Type Nullable Description
status Object FALSE Status of response in Object {code: <status_code>, message: <status_message>}. See table "Response Code" for more details
ewallet_trx_status String(20) TRUE Always filled with WAITING_PAYMENT if a transaction is successfully created
trx_id String(255) TRUE Filled with a unique transaction identifier from OY
ref_number String(255) TRUE Filled with a unique transaction identifier from OY, can also be used to mock callback in staging environment
customer_id String(255) TRUE ID generated by Partner for a specific user/customer
partner_trx_id String(255) TRUE ID generated by Partner for a specific transaction
amount String(255) TRUE Transaction amount
ewallet_code String(255) TRUE The ewallet issuer that the customer will use to pay. Refer to this for the list of available ewallet codes
ewallet_url String(255) TRUE EWallet URL generated by the the e-wallet issuers to be used for payment purposes

E-Wallet Transaction Callback

The E-Wallet Transaction Callback will be sent as a POST request (using JSON format) to your web hook. Please inform your Callback web hook to our business representative or to partner@oyindonesia.com

You will receive the callback when your user has successfully paid the e-wallet transaction. (Note: We send the callback ONLY for a successful transaction.

Callback for Delayed Settlement (Non-Real Time Settlement)

If your settlement is non-real time, for every transaction whose payment method is settled H+>0 from the time of transaction, you will receive two callbacks with details as follows:

  1. 1st Callback -> To be sent after your customer successfully executes the transaction. For example, if your customer executes the transaction on 11 May 2021 at 14:00:00, that is also when we send the 1st Callback to you. In the 1st callback, the settlement status is set to WAITING (because it is not yet settled to your Account Statement balance)
  2. 2nd Callback -> To be sent after the settlement status is changed from WAITING into SUCCESS. For example, if the settlement status is changed into SUCCESS on 12 May 2021 at 15:00:00, that is also when we send the 2nd Callback to you. In the 2nd callback, the settlement status is SUCCESS

Callback Parameters

Response callback:

{
    "success": true,
    "trx_id": "789467agf238893894rfcw7978iu7g7e",
    "customer_id": "my_user_id",
    "amount": 75000,
    "ewallet_code": "shopeepay_ewallet",
    "mobile_number": "6282114845847",
    "success_redirect_url": "https://myweb.com/usertx/123456",
    "settlement_time": "01/02/2020T15:00:00.000+0000",
    "settlement_status": "WAITING"
}
Parameter Type Nullable Description
success boolean FALSE The status of the payment and it is always set to to true
partner_trx_id String(255) FALSE ID generated by Partner for a specific transaction
trx_id String(255) FALSE Filled with a unique transaction identifier from OY
ref_number String(255) FALSE Filled with a unique transaction identifier from OY, can also be used to mock callback in staging environment
customer_id String(255) FALSE ID generated by Partner for a specific user/customer
amount BigDecimal FALSE Transaction amount
ewallet_code String(255) FALSE The ewallet issuer that the customer used to pay. Refer to this for the list of available ewallet codes
mobile_number String(255) FALSE Customer mobile number
success_redirect_url String(255) FALSE Indicates the URL of your environment (to redirect the customers back once payment has been completed in e-wallet issuers.)
settlement_time Timestamp FALSE The timestamp (in UTC+7) indicating when the fund will be settled to partner’s account statement, format dd/MM/yyyy'T'HH:mm:ss.SSSZZZZ
settlement_status String(255) FALSE Status of the settlement (e.g. success/waiting)

Check E-Wallet Transaction Status

Use this API to check the status of an e-wallet transaction.

HTTPS Request

[Production] POST https://partner.oyindonesia.com/api/e-wallet-aggregator/check-status

[Staging] POST https://api-stg.oyindonesia.com/api/e-wallet-aggregator/check-status

Request Headers

Parameter Type Description
X-Api-Key String API Key used to connect to this particular endpoint
X-Oy-Username String Your OY! account username

Request Parameters

curl -X POST \
  <%= config[:endpoint_prod] %>/api/e-wallet-aggregator/check-status \
  -H 'content-type: application/json' \
  -H 'accept: application/json' \
  -H 'x-api-key: apikeymu' \
  -H 'x-oy-username: yourusername' \
  -d '{
        "partner_trx_id": "ABC123456527"
    }'
var headers = {
  'Content-Type': 'application/json',
  'X-Oy-Username': '{{username}}',
  'X-Api-Key': '{{api-key}}'
};
var request = http.Request('POST', Uri.parse('{{base_url}}/api/e-wallet-aggregator/check-status'));
request.body = json.encode({
 "partner_trx_id": "ABC123456527"
});
request.headers.addAll(headers);

http.StreamedResponse response = await request.send();

if (response.statusCode == 200) {
  print(await response.stream.bytesToString());
}
else {
  print(response.reasonPhrase);
}
package main

import (
  "fmt"
  "strings"
  "net/http"
  "io/ioutil"
)

func main() {

  url := "%7B%7Bbase_url%7D%7D/api/e-wallet-aggregator/check-status"
  method := "POST"

  payload := strings.NewReader(`{
     "partner_trx_id": "ABC123456527"
}`)

  client := &http.Client {
  }
  req, err := http.NewRequest(method, url, payload)

  if err != nil {
    fmt.Println(err)
    return
  }
  req.Header.Add("Content-Type", "application/json")
  req.Header.Add("X-Oy-Username", "{{username}}")
  req.Header.Add("X-Api-Key", "{{api-key}}")

  res, err := client.Do(req)
  if err != nil {
    fmt.Println(err)
    return
  }
  defer res.Body.Close()

  body, err := ioutil.ReadAll(res.Body)
  if err != nil {
    fmt.Println(err)
    return
  }
  fmt.Println(string(body))
}
OkHttpClient client = new OkHttpClient().newBuilder()
  .build();
MediaType mediaType = MediaType.parse("application/json");
RequestBody body = RequestBody.create(mediaType, "{\n\t\"partner_trx_id\": \"ABC123456527\"\n}");
Request request = new Request.Builder()
  .url("{{base_url}}/api/e-wallet-aggregator/check-status")
  .method("POST", body)
  .addHeader("Content-Type", "application/json")
  .addHeader("X-Oy-Username", "{{username}}")
  .addHeader("X-Api-Key", "{{api-key}}")
  .build();
Response response = client.newCall(request).execute();
var data = JSON.stringify({
    "partner_trx_id": "ABC123456527"
});

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function() {
  if(this.readyState === 4) {
    console.log(this.responseText);
  }
});

xhr.open("POST", "%7B%7Bbase_url%7D%7D/api/e-wallet-aggregator/check-status");
xhr.setRequestHeader("Content-Type", "application/json");
xhr.setRequestHeader("X-Oy-Username", "{{username}}");
xhr.setRequestHeader("X-Api-Key", "{{api-key}}");

xhr.send(data);
<?php
require_once 'HTTP/Request2.php';
$request = new HTTP_Request2();
$request->setUrl('{{base_url}}/api/e-wallet-aggregator/check-status');
$request->setMethod(HTTP_Request2::METHOD_POST);
$request->setConfig(array(
  'follow_redirects' => TRUE
));
$request->setHeader(array(
  'Content-Type' => 'application/json',
  'X-Oy-Username' => '{{username}}',
  'X-Api-Key' => '{{api-key}}'
));
$request->setBody('{\n  "partner_trx_id": "ABC123456527"\n}');
try {
  $response = $request->send();
  if ($response->getStatus() == 200) {
    echo $response->getBody();
  }
  else {
    echo 'Unexpected HTTP status: ' . $response->getStatus() . ' ' .
    $response->getReasonPhrase();
  }
}
catch(HTTP_Request2_Exception $e) {
  echo 'Error: ' . $e->getMessage();
}
import http.client
import json

conn = http.client.HTTPSConnection("{{base_url}}")
payload = json.dumps({
  "partner_trx_id": "ABC123456527"
})
headers = {
  'Content-Type': 'application/json',
  'X-Oy-Username': '{{username}}',
  'X-Api-Key': '{{api-key}}'
}
conn.request("POST", "/api/e-wallet-aggregator/check-status", payload, headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))

The above command returns JSON structured similar like this:

{
    "status": {
        "code": "000",
        "message": "Success"
    },
    "ewallet_trx_status": "WAITING_PAYMENT",
    "amount": 500000,
    "trx_id": "789467agf238893894rfcw7978iu7g7e",
    "customer_id": "my_user_id",
    "partner_trx_id": "ABC123456527",
    "ewallet_code": "shopeepay_ewallet",
    "ewallet_url": "https://someewalletlink.com",
    "reason": "marked as WAITING_PAYMENT by creation service"
}
Parameter Type Required Default Description
partner_trx_id String(255) TRUE - ID generated by Partner for a specific transaction

Response Parameters

Parameter Type Nullable Description
status Object FALSE Status of response in Object {code: <status_code>, message: <status_message>}
ewallet_trx_status String(20) TRUE Current transaction status, refer to "E-Wallet Transaction Status" for more details. Will not be sent if request is failed.
trx_id String(255) TRUE Filled with a unique transaction identifier from OY. Will not be sent if request is failed.
customer_id String(255) TRUE ID generated by Partner for a specific user/customer. Will not be sent if request is failed.
partner_trx_id String(255) TRUE ID generated by Partner for a specific transaction. Will not be sent if request is failed.
amount String(255) FALSE Transaction Amount
ewallet_code String(255) TRUE The ewallet issuer that the customer will use to pay. Will not be sent if request is failed.
ewallet_url String(255) TRUE EWallet URL passed from the e-wallet issuers to be used for payment purposes. Empty for all ovo transaction. Also empty for other ewallet if request is failed.
reason String(255) TRUE Reason for the status given. Will not be sent if request is failed.

Refund E-Wallet Transaction

Use this API to refund an e-wallet transaction that has been completed. Please refer to table E-wallet Details to see refund capability of each e-wallet vendor.

HTTPS Request

[Production] POST https://partner.oyindonesia.com/api/e-wallet-aggregator/refund

[Staging] POST https://api-stg.oyindonesia.com/api/e-wallet-aggregator/refund

Request Headers

Parameter Type Description
X-Api-Key String API Key used to connect to this particular endpoint
X-Oy-Username String Your OY! account username

Request Parameters

curl -X POST \
  <%= config[:endpoint_prod] %>/api/e-wallet-aggregator/refund \
  -H 'content-type: application/json' \
  -H 'accept: application/json' \
  -H 'x-api-key: yourapikey' \
  -H 'x-oy-username: yourusername' \
  -d '{
        "partner_trx_id": "ABC123456527",
        "refund_amount": 10000
    }'
var headers = {
  'Content-Type': 'application/json',
  'X-Oy-Username': '{{username}}',
  'X-Api-Key': '{{api-key}}'
};
var request = http.Request('POST', Uri.parse('{{base_url}}/api/e-wallet-aggregator/refund'));
request.body = json.encode({
 "partner_trx_id": "ABC123456527",
 "refund_amount": 10000
});
request.headers.addAll(headers);

http.StreamedResponse response = await request.send();

if (response.statusCode == 200) {
  print(await response.stream.bytesToString());
}
else {
  print(response.reasonPhrase);
}
package main

import (
  "fmt"
  "strings"
  "net/http"
  "io/ioutil"
)

func main() {

  url := "%7B%7Bbase_url%7D%7D/api/e-wallet-aggregator/refund"
  method := "POST"

  payload := strings.NewReader(`{
     "partner_trx_id": "ABC123456527",
     "refund_amount": 10000
}`)

  client := &http.Client {
  }
  req, err := http.NewRequest(method, url, payload)

  if err != nil {
    fmt.Println(err)
    return
  }
  req.Header.Add("Content-Type", "application/json")
  req.Header.Add("X-Oy-Username", "{{username}}")
  req.Header.Add("X-Api-Key", "{{api-key}}")

  res, err := client.Do(req)
  if err != nil {
    fmt.Println(err)
    return
  }
  defer res.Body.Close()

  body, err := ioutil.ReadAll(res.Body)
  if err != nil {
    fmt.Println(err)
    return
  }
  fmt.Println(string(body))
}
OkHttpClient client = new OkHttpClient().newBuilder()
  .build();
MediaType mediaType = MediaType.parse("application/json");
RequestBody body = RequestBody.create(mediaType, "{\n\t\"partner_trx_id\": \"ABC123456527\",\n\t\"refund_amount\": 10000\n}");
Request request = new Request.Builder()
  .url("{{base_url}}/api/e-wallet-aggregator/refund")
  .method("POST", body)
  .addHeader("Content-Type", "application/json")
  .addHeader("X-Oy-Username", "{{username}}")
  .addHeader("X-Api-Key", "{{api-key}}")
  .build();
Response response = client.newCall(request).execute();
var data = JSON.stringify({
    "partner_trx_id": "ABC123456527",
    "refund_amount": 10000
});

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function() {
  if(this.readyState === 4) {
    console.log(this.responseText);
  }
});

xhr.open("POST", "%7B%7Bbase_url%7D%7D/api/e-wallet-aggregator/refund");
xhr.setRequestHeader("Content-Type", "application/json");
xhr.setRequestHeader("X-Oy-Username", "{{username}}");
xhr.setRequestHeader("X-Api-Key", "{{api-key}}");

xhr.send(data);
<?php
require_once 'HTTP/Request2.php';
$request = new HTTP_Request2();
$request->setUrl('{{base_url}}/api/e-wallet-aggregator/refund');
$request->setMethod(HTTP_Request2::METHOD_POST);
$request->setConfig(array(
  'follow_redirects' => TRUE
));
$request->setHeader(array(
  'Content-Type' => 'application/json',
  'X-Oy-Username' => '{{username}}',
  'X-Api-Key' => '{{api-key}}'
));
$request->setBody('{\n  "partner_trx_id": "ABC123456527",\n "refund_amount": 10000\n}');
try {
  $response = $request->send();
  if ($response->getStatus() == 200) {
    echo $response->getBody();
  }
  else {
    echo 'Unexpected HTTP status: ' . $response->getStatus() . ' ' .
    $response->getReasonPhrase();
  }
}
catch(HTTP_Request2_Exception $e) {
  echo 'Error: ' . $e->getMessage();
}
import http.client
import json

conn = http.client.HTTPSConnection("{{base_url}}")
payload = json.dumps({
  "partner_trx_id": "ABC123456527",
  "refund_amount": 10000
})
headers = {
  'Content-Type': 'application/json',
  'X-Oy-Username': '{{username}}',
  'X-Api-Key': '{{api-key}}'
}
conn.request("POST", "/api/e-wallet-aggregator/refund", payload, headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))

The above command returns JSON structured similar like this:

{
    "status": {
        "code": "000",
        "message": "Success"
    },
    "refund_id": "REFUND123",
    "trx_id": "789467agf238893894rfcw7978iu7g7e",
    "partner_trx_id": "ABC123456527",
    "refund_amount": 10000,
    "refund_status": "REFUND_ONPROCESS"
}
Parameter Type Required Default Description
partner_trx_id String(255) TRUE - ID generated by Partner for a specific transaction
refund_amount BigDecimal TRUE - Amount to be refunded, must be greater than 0 and can't be greater than the e-wallet transaction amount

Response Parameters

Parameter Type Nullable Description
status Object FALSE Status of response in Object {code: <status_code>, message: <status_message>}. See table "Response Code" for more details
refund_id String(255) TRUE Filled with a unique refund identifier from OY. You will get refund ID if your request is successfully passed to e-wallet vendor. This can be used as a request parameter to call get refund status API
trx_id String(255) TRUE Filled with a unique transaction identifier from OY. Will not be sent if request is failed.
partner_trx_id String(255) TRUE ID generated by Partner for a specific transaction. Will not be sent if request is failed.
refund_amount BigDecimal TRUE Requested refund amount. Will not be sent if request is failed.
refund_status String(255) TRUE Filled with status of refund request, refer to "E-Wallet Refund Status" for more details. Will not be sent if request is failed.

E-Wallet Refund Callback

The E-Wallet Refund Callback will be sent as a POST request (using JSON format) to your web hook. Please inform your Callback web hook to our business representative or to partner@oyindonesia.com

You will receive the callback when you request to refund an e-wallet transaction and your request is successfully passed to e-wallet vendor.

Callback Parameters

Response callback:

{
    "success": true,
    "refund_id": "REFUND123",
    "refund_status": "REFUNDED",
    "refund_amount": 10000
}
Parameter Type Nullable Description
success boolean FALSE Filled with true if refund is successfully processed by e-wallet vendor, and false if otherwise
refund_id String(255) FALSE Filled with a unique refund identifier from OY
refund_status String(255) FALSE Status of refund request, refer to "E-Wallet Refund Status" for more details
refund_amount BigDecimal FALSE Requested refund amount

Get E-Wallet Refund Status

HTTPS Request

[Production] GET https://partner.oyindonesia.com/api/e-wallet-aggregator/get-refund?refund_id=<refund_id>

[Staging] GET https://api-stg.oyindonesia.com/api/e-wallet-aggregator/get-refund?refund_id=<refund_id>

Request Headers

Parameter Type Description
X-Api-Key String API Key used to connect to this particular endpoint
X-Oy-Username String Your OY! account username

Query Parameters

curl -X GET \
  <%= config[:endpoint_prod] %>/api/e-wallet-aggregator/get-refund?refund_id=<refund_id> \
  -H 'content-type: application/json' \
  -H 'accept: application/json' \
  -H 'x-api-key: yourapikey' \
  -H 'x-oy-username: yourusername'
var headers = {
  'Content-Type': 'application/json',
  'X-Oy-Username': '{{username}}',
  'X-Api-Key': '{{api-key}}'
};
var request = http.Request('GET', Uri.parse('{{base_url}}/api/e-wallet-aggregator/get-refund?refund_id=<refund_id>'));
request.headers.addAll(headers);

http.StreamedResponse response = await request.send();

if (response.statusCode == 200) {
  print(await response.stream.bytesToString());
}
else {
  print(response.reasonPhrase);
}
package main

import (
  "fmt"
  "strings"
  "net/http"
  "io/ioutil"
)

func main() {

  url := "%7B%7Bbase_url%7D%7D/api/e-wallet-aggregator/get-refund?refund_id=<refund_id>"
  method := "GET"

  client := &http.Client {
  }
  req, err := http.NewRequest(method, url, nil)

  if err != nil {
    fmt.Println(err)
    return
  }
  req.Header.Add("Content-Type", "application/json")
  req.Header.Add("X-Oy-Username", "{{username}}")
  req.Header.Add("X-Api-Key", "{{api-key}}")

  res, err := client.Do(req)
  if err != nil {
    fmt.Println(err)
    return
  }
  defer res.Body.Close()

  body, err := ioutil.ReadAll(res.Body)
  if err != nil {
    fmt.Println(err)
    return
  }
  fmt.Println(string(body))
}
OkHttpClient client = new OkHttpClient().newBuilder()
  .build();
MediaType mediaType = MediaType.parse("application/json");
Request request = new Request.Builder()
  .url("{{base_url}}/api/e-wallet-aggregator/get-refund?refund_id=<refund_id>")
  .method("GET", null)
  .addHeader("Content-Type", "application/json")
  .addHeader("X-Oy-Username", "{{username}}")
  .addHeader("X-Api-Key", "{{api-key}}")
  .build();
Response response = client.newCall(request).execute();
var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function() {
  if(this.readyState === 4) {
    console.log(this.responseText);
  }
});

xhr.open("GET", "%7B%7Bbase_url%7D%7D/api/e-wallet-aggregator/get-refund?refund_id=<refund_id>");
xhr.setRequestHeader("Content-Type", "application/json");
xhr.setRequestHeader("X-Oy-Username", "{{username}}");
xhr.setRequestHeader("X-Api-Key", "{{api-key}}");

xhr.send();
<?php
require_once 'HTTP/Request2.php';
$request = new HTTP_Request2();
$request->setUrl('{{base_url}}/api/e-wallet-aggregator/get-refund?refund_id=<refund_id>');
$request->setMethod(HTTP_Request2::METHOD_GET);
$request->setConfig(array(
  'follow_redirects' => TRUE
));
$request->setHeader(array(
  'Content-Type' => 'application/json',
  'X-Oy-Username' => '{{username}}',
  'X-Api-Key' => '{{api-key}}'
));
try {
  $response = $request->send();
  if ($response->getStatus() == 200) {
    echo $response->getBody();
  }
  else {
    echo 'Unexpected HTTP status: ' . $response->getStatus() . ' ' .
    $response->getReasonPhrase();
  }
}
catch(HTTP_Request2_Exception $e) {
  echo 'Error: ' . $e->getMessage();
}
import http.client
import json

conn = http.client.HTTPSConnection("{{base_url}}")
payload = ''
headers = {
  'Content-Type': 'application/json',
  'X-Oy-Username': '{{username}}',
  'X-Api-Key': '{{api-key}}'
}
conn.request("GET", "/api/e-wallet-aggregator/get-refund?refund_id=<refund_id>", payload, headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))

The above command returns JSON structured similar like this:

{
    "status": {
        "code": "000",
        "message": "Success"
    },
    "refund_id": "REFUND123",
    "refund_status": "REFUNDED",
    "refund_amount": 10000
}
Parameter Type Required Default Description
refund_id String(255) TRUE - Unique refund ID, you can get this once you have requested refund for an e-wallet transaction and the request is passed to e-wallet vendor

Response Parameters

Parameter Type Nullable Description
status Object FALSE Status of response in Object {code: <status_code>, message: <status_message>}. See table "Response Code" for more details
refund_id String(255) TRUE Requested e-wallet refund ID. Will not be sent if request is failed.
refund_status String(255) TRUE Status of refund request, refer to "E-Wallet Refund Status" for more details. Will not be sent if request is failed.
refund_amount BigDecimal TRUE Requested refund amount. Will not be sent if request is failed.

Get List of E-Wallet Refund

HTTPS Request

[Production] GET https://partner.oyindonesia.com/api/e-wallet-aggregator/list-refund?partner_trx_id=<partner_trx_id>

[Staging] GET https://api-stg.oyindonesia.com/api/e-wallet-aggregator/list-refund?partner_trx_id=<partner_trx_id>

Request Headers

Parameter Type Description
X-Api-Key String API Key used to connect to this particular endpoint
X-Oy-Username String Your OY! account username

Query Parameters

curl -X GET \
  <%= config[:endpoint_prod] %>/api/e-wallet-aggregator/list-refund?partner_trx_id=<partner_trx_id> \
  -H 'content-type: application/json' \
  -H 'accept: application/json' \
  -H 'x-api-key: yourapikey' \
  -H 'x-oy-username: yourusername'
var headers = {
  'Content-Type': 'application/json',
  'X-Oy-Username': '{{username}}',
  'X-Api-Key': '{{api-key}}'
};
var request = http.Request('GET', Uri.parse('{{base_url}}/api/e-wallet-aggregator/list-refund?partner_trx_id=<partner_trx_id>'));
request.headers.addAll(headers);

http.StreamedResponse response = await request.send();

if (response.statusCode == 200) {
  print(await response.stream.bytesToString());
}
else {
  print(response.reasonPhrase);
}
package main

import (
  "fmt"
  "strings"
  "net/http"
  "io/ioutil"
)

func main() {

  url := "%7B%7Bbase_url%7D%7D/api/e-wallet-aggregator/list-refund?partner_trx_id=<partner_trx_id>"
  method := "GET"

  client := &http.Client {
  }
  req, err := http.NewRequest(method, url, nil)

  if err != nil {
    fmt.Println(err)
    return
  }
  req.Header.Add("Content-Type", "application/json")
  req.Header.Add("X-Oy-Username", "{{username}}")
  req.Header.Add("X-Api-Key", "{{api-key}}")

  res, err := client.Do(req)
  if err != nil {
    fmt.Println(err)
    return
  }
  defer res.Body.Close()

  body, err := ioutil.ReadAll(res.Body)
  if err != nil {
    fmt.Println(err)
    return
  }
  fmt.Println(string(body))
}
OkHttpClient client = new OkHttpClient().newBuilder()
  .build();
MediaType mediaType = MediaType.parse("application/json");
Request request = new Request.Builder()
  .url("{{base_url}}/api/e-wallet-aggregator/list-refund?partner_trx_id=<partner_trx_id>")
  .method("GET", null)
  .addHeader("Content-Type", "application/json")
  .addHeader("X-Oy-Username", "{{username}}")
  .addHeader("X-Api-Key", "{{api-key}}")
  .build();
Response response = client.newCall(request).execute();
var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function() {
  if(this.readyState === 4) {
    console.log(this.responseText);
  }
});

xhr.open("GET", "%7B%7Bbase_url%7D%7D/api/e-wallet-aggregator/list-refund?partner_trx_id=<partner_trx_id>");
xhr.setRequestHeader("Content-Type", "application/json");
xhr.setRequestHeader("X-Oy-Username", "{{username}}");
xhr.setRequestHeader("X-Api-Key", "{{api-key}}");

xhr.send();
<?php
require_once 'HTTP/Request2.php';
$request = new HTTP_Request2();
$request->setUrl('{{base_url}}/api/e-wallet-aggregator/list-refund?partner_trx_id=<partner_trx_id>');
$request->setMethod(HTTP_Request2::METHOD_GET);
$request->setConfig(array(
  'follow_redirects' => TRUE
));
$request->setHeader(array(
  'Content-Type' => 'application/json',
  'X-Oy-Username' => '{{username}}',
  'X-Api-Key' => '{{api-key}}'
));
try {
  $response = $request->send();
  if ($response->getStatus() == 200) {
    echo $response->getBody();
  }
  else {
    echo 'Unexpected HTTP status: ' . $response->getStatus() . ' ' .
    $response->getReasonPhrase();
  }
}
catch(HTTP_Request2_Exception $e) {
  echo 'Error: ' . $e->getMessage();
}
import http.client
import json

conn = http.client.HTTPSConnection("{{base_url}}")
payload = ''
headers = {
  'Content-Type': 'application/json',
  'X-Oy-Username': '{{username}}',
  'X-Api-Key': '{{api-key}}'
}
conn.request("GET", "/api/e-wallet-aggregator/list-refund?partner_trx_id=<partner_trx_id>", payload, headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))

The above command returns JSON structured similar like this:

{
    "status": {
        "code": "000",
        "message": "Success"
    },
    "total": 2,
    "data": [
        {
            "refund_id": "REFUND123",
            "refund_status": "REFUNDED",
            "refund_amount": 10000
        },
        {
            "refund_id": "REFUND456",
            "refund_status": "REFUND_FAILED",
            "refund_amount": 10000
        }
    ]
}
Parameter Type Required Default Description
partner_trx_id String(255) TRUE - ID generated by Partner for a specific transaction

Response Parameters

Parameter Type Nullable Description
status Object FALSE Status of response in Object {code: <status_code>, message: <status_message>}. See table "Response Code" for more details
total Integer TRUE Total items. Will not be sent if request is failed.
data Array of object TRUE List of Object {refund_id: <refund_id>, refund_status: <refund_status>, refund_amount: <refund_amount>} Will not be sent if request is failed.

E-Wallet Details

E-Wallet Issuer E-Wallet Code Minimum Expiration Time Maximum Expiration Time Redirection Feature Refund Support
OVO ovo_ewallet Parameter is ignored, always set to 55 seconds Parameter is ignored, always set to 55 seconds Not supported Not supported
ShopeePay shopeepay_ewallet 1 minute 60 minutes Support Support full refund only & can't do refund between 00.00 - 05.00 WIB
Linkaja linkaja_ewallet Parameter is ignored, always set to 5 minutes Parameter is ignored, always set to 5 minutes Support Support full refund only
DANA dana_ewallet 1 minute 60 minutes Support Support full and partial refund

E-Wallet Transaction Status

Status Trigger
WAITING_PAYMENT Transaction is successfully created and currently active
FAILED Payment failed
COMPLETE Payment successfully received
REFUNDED Payment successfully refunded
EXPIRED Expiration time is reached with no payment received

E-Wallet Refund Status

Status Description
REFUNDED Payment has been successfully refunded
REFUND_FAILED Refund request failed
REFUND_ONPROCESS Refund ongoing by e-wallet vendor
SUSPECTED Refund request failed on e-wallet vendor, balance is being checked

List of Status Codes

Response Code State Description
000 Final Response success without error
990 Final Request is Rejected (Parameter is invalid)
202 Final Request is Rejected (User is not active/registered for this feature)
203 Final Request is Rejected (Duplicate Partner Trx ID)
204 Final Request is Rejected (Partner Trx ID not found)
206 Final Request is Rejected (Balance is not enough)
207 Final Request is Rejected (Request IP Address is not Registered)
208 Final Request is Rejected (API Key is not Valid)
248 Non-Final Request is Rejected (Ewallet/Vendor Server Error)
250 Final Request is Rejected (EWallet code is not available)
251 Final Request is rejected (EWallet code is disabled)
252 Non-Final Request is rejected (Creation/Check Status/Refund request failed)
253 Final Request is Rejected (Partner credential not found or invalid on e-wallet server)
254 Final Request is Rejected (User credential not found, blocked, or invalid)
255 Final Request is Rejected (Refund ID is not found)
999 Non-Final Internal Server Error

List of HTTP Status Codes

HTTP Status Code Description
200 Response success without error
403 Forbidden (IP address is not whitelisted or request is deemed suspicious e.g SQL injection or XSS)
404 Not Found (wrong URL or wrong HTTP method)
429 Request Rejected (Too Many Request to specific endpoint)
500 Internal Server Error (OY! system encountered unknown error)
503 Service Unavailable (OY! system is unable to process the request temporarily)
504 Gateway Timeout (OY! system took too long processing the request and was unable to respond in time)

Payment Routing

Payment Routing offers you with end to end solutions from accept payment to disburse the money. You can disburse the money up to 10 recipients.

Payment Routing Base URL

[Production Base URL] : https://partner.oyindonesia.com
[Staging Base URL] : https://api-stg.oyindonesia.com

Create and Update Payment Routing

This endpoint will trigger the creation of payment routing and will be using the same API to handle the update requests.

curl --location --request POST 'https://partner.oyindonesia.com/api/payment-routing/create-transaction' \
--header 'Content-Type: application/json' \
--header 'x-oy-username: yourusername' \
--header 'x-api-key: apikeymu' \
--data-raw '{
    "partner_user_id": "USR-20211117-1029",
    "use_linked_account": false,
    "partner_trx_id": "TRX-20211117-1030",
    "need_frontend": false,
    "sender_email": "sender@gmail.com",
    "receive_amount": 14000,
    "list_enable_payment_method": "BANK_TRANSFER",
    "list_enable_sof": "002",
    "va_display_name": "partner_brand",
    "payment_routing": [{
        "recipient_bank": "014",
        "recipient_account": "1234567890",
        "recipient_amount": 10000,
        "recipient_email": "recipient_bca@gmail.com"
    }]
}'
var headers = {
  'Content-Type': 'application/json',
  'x-oy-username': 'yourusername',
  'x-api-key': 'apikeymu'

};
var request = http.Request('POST', Uri.parse('https://partner.oyindonesia.com/api/payment-routing/create-transaction'));
request.body = json.encode({
  "partner_user_id": "USR-20211117-1029",
  "use_linked_account": false,
  "partner_trx_id": "TRX-20211117-1030",
  "need_frontend": false,
  "sender_email": "sender@gmail.com",
  "receive_amount": 14000,
  "list_enable_payment_method": "VA",
  "list_enable_sof": "002",
  "va_display_name": "partner_brand",
  "payment_routing": [
    {
      "recipient_bank": "014",
      "recipient_account": "1234567890",
      "recipient_amount": 10000,
      "recipient_email": "recipient_bca@gmail.com"
    }
  ]
});
request.headers.addAll(headers);

http.StreamedResponse response = await request.send();

if (response.statusCode == 200) {
  print(await response.stream.bytesToString());
}
package main

import (
  "fmt"
  "strings"
  "net/http"
  "io/ioutil"
)

func main() {

  url := "https://partner.oyindonesia.com/api/payment-routing/create-transaction"
  method := "POST"

  payload := strings.NewReader(`{
    "partner_user_id": "USR-20211117-1029",
    "use_linked_account": false,
    "partner_trx_id": "TRX-20211117-1030",
    "need_frontend": false,
    "sender_email": "sender@gmail.com",
    "receive_amount": 14000,
    "list_enable_payment_method": "BANK_TRANSFER",
    "list_enable_sof": "002",
    "va_display_name": "partner_brand",
    "payment_routing": [{
        "recipient_bank": "014",
        "recipient_account": "1234567890",
        "recipient_amount": 10000,
        "recipient_email": "recipient_bca@gmail.com"
    }]
}`)

  client := &http.Client {
  }
  req, err := http.NewRequest(method, url, payload)

  if err != nil {
    fmt.Println(err)
    return
  }
  req.Header.Add("Content-Type", "application/json")
  req.Header.Add("x-oy-username", "yourusername")
  req.Header.Add("x-api-key", "apikeymu")

  res, err := client.Do(req)
  if err != nil {
    fmt.Println(err)
    return
  }
  defer res.Body.Close()

  body, err := ioutil.ReadAll(res.Body)
  if err != nil {
    fmt.Println(err)
    return
  }
  fmt.Println(string(body))
}
OkHttpClient client = new OkHttpClient().newBuilder()
  .build();
MediaType mediaType = MediaType.parse("application/json");
RequestBody body = RequestBody.create(mediaType, "{\n    \"partner_user_id\": \"USR-20211117-1029\",\n    \"use_linked_account\": false,\n \"partner_trx_id\": \"TRX-20211117-1030\",\n    \"need_frontend\": false,\n    \"sender_email\": \"sender@gmail.com\",\n    \"receive_amount\": 14000,\n    \"list_enable_payment_method\": \"BANK_TRANSFER\",\n    \"list_enable_sof\": \"002\",\n    \"va_display_name\": \"partner_brand\",\n    \"payment_routing\": [{\n        \"recipient_bank\": \"014\",\n        \"recipient_account\": \"1234567890\",\n        \"recipient_amount\": 10000,\n        \"recipient_email\": \"recipient_bca@gmail.com\"\n    }]\n}");
Request request = new Request.Builder()
  .url("https://partner.oyindonesia.com/api/payment-routing/create-transaction")
  .method("POST", body)
  .addHeader("Content-Type", "application/json")
  .addHeader("x-oy-username", "yourusername")
  .addHeader("x-api-key", "apikeymu")
  .build();
Response response = client.newCall(request).execute();
var data = JSON.stringify({
  "partner_user_id": "USR-20211117-1029",
  "use_linked_account": false,
  "partner_trx_id": "TRX-20211117-1030",
  "need_frontend": false,
  "sender_email": "sender@gmail.com",
  "receive_amount": 14000,
  "list_enable_payment_method": "BANK_TRANSFER",
  "list_enable_sof": "002",
  "va_display_name": "partner_brand",
  "payment_routing": [
    {
      "recipient_bank": "014",
      "recipient_account": "1234567890",
      "recipient_amount": 10000,
      "recipient_email": "recipient_bca@gmail.com"
    }
  ]
});

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function() {
  if(this.readyState === 4) {
    console.log(this.responseText);
  }
});

xhr.open("POST", "https://partner.oyindonesia.com/api/payment-routing/create-transaction");
xhr.setRequestHeader("Content-Type", "application/json");
xhr.setRequestHeader("x-oy-username", "yourusername");
xhr.setRequestHeader("x-api-key", "apikeymu");

xhr.send(data);
<?php
require_once 'HTTP/Request2.php';
$request = new HTTP_Request2();
$request->setUrl('https://partner.oyindonesia.com/api/payment-routing/create-transaction');
$request->setMethod(HTTP_Request2::METHOD_POST);
$request->setConfig(array(
  'follow_redirects' => TRUE
));
$request->setHeader(array(
  'Content-Type' => 'application/json',
  'x-oy-username' => 'yourusername',
  'x-api-key' => 'apikeymu'
));
$request->setBody('{\n    "partner_user_id": "USR-20211117-1029",\n  "use_linked_account": false,\n  "partner_trx_id": "TRX-20211117-1030",\n    "need_frontend": false,\n    "sender_email": "sender@gmail.com",\n    "receive_amount": 14000,\n    "list_enable_payment_method": "BANK_TRANSFER",\n    "list_enable_sof": "002",\n    "va_display_name": "partner_brand",\n    "payment_routing": [{\n        "recipient_bank": "014",\n        "recipient_account": "1234567890",\n        "recipient_amount": 10000,\n        "recipient_email": "recipient_bca@gmail.com"\n    }]\n}');
try {
  $response = $request->send();
  if ($response->getStatus() == 200) {
    echo $response->getBody();
  }
  else {
    echo 'Unexpected HTTP status: ' . $response->getStatus() . ' ' .
    $response->getReasonPhrase();
  }
}
catch(HTTP_Request2_Exception $e) {
  echo 'Error: ' . $e->getMessage();
}
import http.client
import json

conn = http.client.HTTPSConnection("https://partner.oyindonesia.com", undefined)
payload = json.dumps({
  "partner_user_id": "USR-20211117-1029",
  "use_linked_account": False,
  "partner_trx_id": "TRX-20211117-1030",
  "need_frontend": False,
  "sender_email": "sender@gmail.com",
  "receive_amount": 14000,
  "list_enable_payment_method": "BANK_TRANSFER",
  "list_enable_sof": "002",
  "va_display_name": "partner_brand",
  "payment_routing": [
    {
      "recipient_bank": "014",
      "recipient_account": "1234567890",
      "recipient_amount": 10000,
      "recipient_email": "recipient_bca@gmail.com"
    }
  ]
})
headers = {
  'Content-Type': 'application/json',
  'x-oy-username': 'yourusername',
  'x-api-key': 'apikeymu'
}
conn.request("POST", "/api/payment-routing/create-transaction", payload, headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))

The above command returns JSON structured similar like this:

{
    "status": {
        "code": "000",
        "message": "Success"
    },
    "trx_id": "23a009f5-24ce-4567-96b3-03c42a0fb7ae",
    "partner_user_id": "USR-20211117-1029",
    "use_linked_account": false,
    "partner_trx_id": "TRX-20211117-1030",
    "receive_amount": 14000,
    "trx_expiration_time": "2021-12-02 18:59:31",
    "payment_method": "VA",
    "sender_bank": "009",
    "payment_info": {
        "va_number": "103406000000006289",
        "va_display_name": "partner_brand"
    }
}

HTTPS Request

Endpoint:
[Production] POST https://partner.oyindonesia.com/api/payment-routing/create-transaction
[Staging] POST https://api-stg.oyindonesia.com/api/payment-routing/create-transaction

Header

Field Description Example
x-oy-username Partner username username
x-api-key Partner api key 6e87432c-2726-11ec-9621-0242ac130002

Request Parameters

Parameter Type Required Default Description
partner_user_id String Applicable for VA and EWallet with need_frontend: false. If you want the VA to be reusable for each users (multiple use) or create EWallet Direct Payment transaction, you are required define this parameter. - Unique partner user id. Will automatically be generated if left empty on VA payment method with need_frontend: false. For EWallet Direct Payment, it is required to register partner_user_id using Account Linking API first.
use_linked_account Boolean Applicable for EWallet with need_frontend: false. false If true, then EWallet Direct Payment transaction will be created. Else, regular EWallet transaction will be created.
partner_trx_id String FALSE - Unique partner transaction ID. Will automatically be generated if left empty.
need_frontend Boolean TRUE - Partner need UI or not, if true, we will route to payment link, otherwise will be route to API-based solution.
list_enable_payment_method String; comma separated TRUE - To configure payment methods to be enabled in the payment method page.
list_enable_sof String; comma separated TRUE - To configure list of source of fund (banks or ewallets) to be enabled in the payment method page. For additional detail please refer to List Allowed Payment Methods and SOF
sender_email String CONDITIONAL - Email of sender. Required only when creating VA from Mandiri(008), Permata(013) or CIMB(022).
full_name String CONDITIONAL - Fill with the name of end-user that will pay this transaction. Required only when creating VA from Mandiri(008), Permata(013) or CIMB(022).
receive_amount Numeric TRUE - The amount of a transaction to be paid, min. amount is 10000, except if you use unique code BCA which has min. amount 11000 or CARDS which has min. amount 15000
va_display_name String FALSE Partner's brand name Display name for VA that will be displayed once user do inquiry. If empty VA name will be set using partner brand name. This parameter will be used only if you use BANK_TRANSFER payment method and routed to VA.
trx_expiration_time Date string; yyyy-mm-dd hh:mm:ss format (UTC+7) FALSE Refer to Default Expiration Time Set expiration time of transaction. Please refer to Transaction Expiration Time Guidelines
trx_counter Numeric FALSE 1/-1 A transaction counter to limit number of transaction that can be receive by va number. For example, if you put 3, it means that the VA number can only accept transaction 3 times. This parameter will be used only if you use BANK_TRANSFER payment method and routed to VA.
success_redirect_url String(512) CONDITIONAL - Indicates the URL of your environment to redirect customers back to once payment has been completed. Accepts both HTTP links and URL scheme formats. Required if payment method is either "EWALLET" or "CARDS", and need_frontend is set to false. Specific for Shopeepay Direct Payment, Shopeepay will redirect to this url based on the result of the payment. If the payment is successful, ShopeePay will send an additional param ?result=100 following the redirect url. Otherwise, ShopeePay will send additional param ?result=201 for failed payment (insufficient balance, wrong pin, link has been paid, or user click back button). Example: https://example.com/callback?result=100.
failed_redirect_url String(512) CONDITIONAL - Indicates the URL of your environment to redirect customers back to once payment cannot be completed. Accepts both HTTP links and URL scheme formats. Required if payment method is "CARDS", and need_frontend is set to false.
payment_routing List of Objects FALSE - List of disburse recipient; max. is 10
recipient_bank String TRUE - Bank code of the recipient account
recipient_account String TRUE - Recipient bank account number. For testing purpose, please see List of Disbursment Mock Account below
recipient_amount Numeric TRUE - The amount of transaction to be disbursed
recipient_note String TRUE - Notes for the disbursement
recipient_email String TRUE - Email for disbursement notification, email can be up to 5, seperated by a whitespace

Response Parameters

Parameter Type Nullable Description
status Object FALSE Status of response in Object
trx_id String FALSE Payment Routing ID defined by OY!
partner_user_id String TRUE Partner user ID that you defined in the request parameter. Only available for reusable VA or direct payment
use_linked_account Boolean FALSE Applicable for EWallet with need_frontend: false. If true, the transaction created is an EWallet Direct Payment transaction (ShopeePay only). Else, it is a regular EWallet transaction.
partner_trx_id String FALSE Partner transaction ID that you defined in the request parameter
receive_amount Numeric FALSE amount to be received. If you use unique code BCA, this number will contain the amount to be received subtracted by 3 digits generated unique code.
trx_expiration_time Date string; yyyy-MM-dd HH:mm:ss format FALSE Transaction Expiration Time
payment_method String TRUE Only exist if request need_frontend is FALSE. The payment method used by user to complete a payment. Refer to Payment Method on List of Allowed Payment Methods and SOF
sender_bank String TRUE Only exist if request need_frontend is FALSE. The bank code used by a payer to do payment. Refer to SOF on List of Allowed Payment Methods and SOF
payment_info Object FALSE Payment info object
payment_checkout_url String TRUE generated url for payment link; conditional, only exist if request need_frontend is TRUE
account_number String TRUE Generated VA number if you use VA or account number destination if you use unique code BCA; conditional, only exist if request need_frontend is FALSE and payment_method is BANK_TRANSFER
account_name String TRUE VA display name if you use VA or bank account's owner name if you use unique code BCA; conditional, only exist if request need_frontend is FALSE and payment_method is BANK_TRANSFER
bank_code String TRUE Bank code for the destination VA number or bank account; conditional, only exist if request need_frontend is FALSE and payment_method is BANK_TRANSFER
qris_url String TRUE the URL of QR image; conditional, only exist if request need_frontend is FALSE and payment_method is QRIS. This returned URL can only be accessed for 5 minutes after initial response was received, and is independent to the actual QRIS validity / expiration time.
ewallet_url String TRUE For use_linked_account: true: URL that prompt user to input PIN to authorize Direct Payment. For use_linked_account: false: A deep link URL that allows user to access the specific e-wallet vendor's application for making a payment. Currently, only Linkaja, ShopeePay and Dana are supported options. This attribute will only be present if the request parameter 'need_frontend' is set to 'FALSE' and the payment method selected is 'EWALLET'.
cards_url String TRUE URL that allows user to make payment using their Credit Card. This attribute will only be present if the request parameter 'need_frontend' is set to 'FALSE' and the payment method selected is 'CARDS'.
unique_code_detail Object TRUE Contains two objects of number: amount which is the requested amount and unique_code which is the generated 3 digits unique code ; conditional, only exist if request need_frontend is FALSE and payment_method is BANK_TRANSFER and you use unique code BCA.
full_name String FALSE If full_name is needed when creating the transaction, the inputted full_name value at creation will be shown here.

List of Allowed Payment Methods and SOF

Below are the list and examples of possible values for both list_enable_payment_method and list_enable_sof based on the value of need_frontend. The requested SOF and/or payment method must be enabled on your account before your request is sent. Also note that the complete request examples provided only use need_frontend = false.

If need_frontend: true

The request should be filled with at least 1 list_enable_payment_method and 1 list_enable_sof.

Payment Method SOF
BANK_TRANSFER 002, 008, 009, 011, 014, 016, 022, 213, 451, 484
QRIS QRIS
EWALLET dana_ewallet, ovo_ewallet, shopeepay_ewallet, linkaja_ewallet
CARDS CC_DC

If you use BANK_TRANSFER payment method with BCA bank code (014) as SOF, you can either be routed to use VA BCA or unique code BCA. If you are routed to unique code BCA, you can either use addition or subtraction approach by requesting to our business representative. For other SOF with BANK_TRANSFER payment method, you will be routed to use VA.

If need_frontend: false

The request should be filled only with 1 list_enable_payment_method and 1 list_enable_sof.

Payment Method SOF
BANK_TRANSFER 002, 008, 009, 011, 014, 016, 022, 213, 451, 484
QRIS QRIS
EWALLET dana_ewallet, shopeepay_ewallet, linkaja_ewallet
CARDS CC_DC

Examples

need_frontend Case list_enable_payment_method list_enable_sof
TRUE BANK_TRANSFER and QRIS BANK_TRANSFER,QRIS 008,451,QRIS,002
TRUE EWALLET, Credit Cards and BANK_TRANSFER EWALLET,CARDS,BANK_TRANSFER dana_ewallet,linkaja_ewallet,CARDS,484
FALSE BANK_TRANSFER Only BANK_TRANSFER 009
FALSE QRIS Only QRIS QRIS
FALSE EWALLET Only EWALLET dana_ewallet
FALSE CARDS Only CARDS CC_DC

Transaction Expiration Time Guidelines

The table below lists the valid expiration times for transactions based on the payment method and source of funds. Unless specified, the default expiration time is 24 hours and the minimum expiration time is 1 hour.

Payment Method SOF Default Expiration Time Expiration Time
QRIS QRIS 30 minutes Limited to 1 minute - 1 hour after the request is sent. The QRIS validity period is dynamic within the aforementioned limit.
EWALLET dana_ewallet, shopeepay_ewallet 60 minutes 1 minute - 60 minutes.
EWALLET linkaja_ewallet 5 minutes 5 minutes, regardless of the expiration time specified in the request.
EWALLET (Direct Payment) shopeepay_ewallet 30 minutes 30 minutes, regardless of the expiration time specified in the request
CARDS CC_DC 60 minutes 60 minutes, regardless of the expiration time specified in the request.
BANK_TRANSFER (unique code BCA only) 014 3 hours Limited to 1 minute - 3 hours after the request is sent, and maximum at 20:30 (UTC+7). If default expiration time (3 hours) exceeds 20:30, then the expiration time will be 20:30. This does not apply in Staging, as you will be routed to use VA by default in the staging environment. Please check the default transaction expiration time.

List of Disbursement Mock Account for Testing Purpose

Use those mock receiver bank account for testing Payment Routing purpose. To simulate all available status of Payment Routing, you can combine those mocked bank account numbers. For example, if you want to see INCOMPLETE status, put two recipients in the payment_routing object with mocked bank account number 1234567890 and 1234567891. For more information about payment Routing status, see List of Payment Routing section.

Mocked Account Number Mocked Disbursement Status
1234567890 SUCCESS
1234567891 FAILED
1234567892 FAILED FORCE CREDIT
1234567893 PENDING
1234567894 PENDING FORCE CREDIT

Check Status Payment Routing Transaction

And endpoint to check status of payment routing transaction.

curl --location --request POST 'https://partner.oyindonesia.com/api/payment-routing/check-status' \
--header 'Content-Type: application/json' \
--header 'x-oy-username: yourusername' \
--header 'x-api-key: apikeymu' \
--data-raw '{
    "partner_trx_id": "TRX-20211117-1030",
    "send_callback": true
}'

var headers = {
  'Content-Type': 'application/json',
  'x-oy-username': 'yourusername',
  'x-api-key': 'apikeymu'
};
var request = http.Request('POST', Uri.parse('https://partner.oyindonesia.com/api/payment-routing/check-status'));
request.body = json.encode({
  "partner_trx_id": "TRX-20211117-1030",
  "send_callback": true
});
request.headers.addAll(headers);

http.StreamedResponse response = await request.send();

if (response.statusCode == 200) {
  print(await response.stream.bytesToString());
}
else {
  print(response.reasonPhrase);
}

package main

import (
  "fmt"
  "strings"
  "net/http"
  "io/ioutil"
)

func main() {

  url := "https://partner.oyindonesia.com/api/payment-routing/check-status"
  method := "POST"

  payload := strings.NewReader(`{
    "partner_trx_id": "TRX-20211117-1030",
    "send_callback": true
}`)

  client := &http.Client {
  }
  req, err := http.NewRequest(method, url, payload)

  if err != nil {
    fmt.Println(err)
    return
  }
  req.Header.Add("Content-Type", "application/json")
  req.Header.Add("x-oy-username", "yourusername")
  req.Header.Add("x-api-key", "apikeymu")

  res, err := client.Do(req)
  if err != nil {
    fmt.Println(err)
    return
  }
  defer res.Body.Close()

  body, err := ioutil.ReadAll(res.Body)
  if err != nil {
    fmt.Println(err)
    return
  }
  fmt.Println(string(body))
}
OkHttpClient client = new OkHttpClient().newBuilder()
  .build();
MediaType mediaType = MediaType.parse("application/json");
RequestBody body = RequestBody.create(mediaType, "{\n    \"partner_trx_id\": \"TRX-20211117-1030\",\n    \"send_callback\": true\n}");
Request request = new Request.Builder()
  .url("https://partner.oyindonesia.com/api/payment-routing/check-status")
  .method("POST", body)
  .addHeader("Content-Type", "application/json")
  .addHeader("x-oy-username", "yourusername")
  .addHeader("x-api-key", "apikeymu")
  .build();
Response response = client.newCall(request).execute();
var data = JSON.stringify({
  "partner_trx_id": "TRX-20211117-1030",
  "send_callback": true
});

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function() {
  if(this.readyState === 4) {
    console.log(this.responseText);
  }
});

xhr.open("POST", "https://partner.oyindonesia.com/api/payment-routing/check-status");
xhr.setRequestHeader("Content-Type", "application/json");
xhr.setRequestHeader("x-oy-username", "yourusername");
xhr.setRequestHeader("x-api-key", "apikeymu");

xhr.send(data);
<?php
require_once 'HTTP/Request2.php';
$request = new HTTP_Request2();
$request->setUrl('https://partner.oyindonesia.com/api/payment-routing/check-status');
$request->setMethod(HTTP_Request2::METHOD_POST);
$request->setConfig(array(
  'follow_redirects' => TRUE
));
$request->setHeader(array(
  'Content-Type' => 'application/json',
  'x-oy-username' => 'yourusername',
  'x-api-key' => 'apikeymu'
));
$request->setBody('{\n    "partner_trx_id": "TRX-20211117-1030",\n    "send_callback": true\n}');
try {
  $response = $request->send();
  if ($response->getStatus() == 200) {
    echo $response->getBody();
  }
  else {
    echo 'Unexpected HTTP status: ' . $response->getStatus() . ' ' .
    $response->getReasonPhrase();
  }
}
catch(HTTP_Request2_Exception $e) {
  echo 'Error: ' . $e->getMessage();
}
import http.client
import json

conn = http.client.HTTPSConnection("https://partner.oyindonesia.com", undefined)
payload = json.dumps({
  "partner_trx_id": "TRX-20211117-1030",
  "send_callback": True
})
headers = {
  'Content-Type': 'application/json',
  'x-oy-username': 'yourusername',
  'x-api-key': 'apikeymu'
}
conn.request("POST", "/api/payment-routing/check-status", payload, headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))

The above command returns JSON structured similar like this:

{
    "status": {
        "code": "000",
        "message": "Success"
    },
    "trx_id": "23a009f5-24ce-4567-96b3-03c42a0fb7ae",
    "partner_user_id": "USR-20211117-1029",
    "use_linked_account": false,
    "partner_trx_id": "TRX-20211117-1030",
    "request_amount": 14000,
    "received_amount": 0,
    "payment_status": "WAITING_PAYMENT",
    "trx_expiration_time": "2021-12-02 18:59:31",
    "need_frontend": false,
    "payment_method": "VA",
    "sender_bank": "009",
    "payment_info": {
        "va_number": "103406000000006289",
        "va_display_name": "partner_brand"
    },
    "payment_routing": [
        {
            "recipient_bank": "014",
            "recipient_account": "1234567890",
            "recipient_account_name": "Katelin Bode",
            "recipient_amount": 10000.0000,
            "disbursement_trx_id": "35ff4e6b-e240-44b3-aff1-1151289e912e",
            "trx_status": "WAITING"
        }
    ]
}

HTTP Request

Endpoint:
[Production] POST https://partner.oyindonesia.com/api/payment-routing/check-status
[Staging] POST https://api-stg.oyindonesia.com/api/payment-routing/check-status

Header

Field Description Example
x-oy-username Partner username username
x-api-key Partner api key 6e87432c-2726-11ec-9621-0242ac130002

Request Parameter

Parameter Type Required Default Description
partner_trx_id String FALSE - Unique partner transaction ID
payment_reference_number String FALSE - Unique reference ID for QRIS transactions. The reference number is stated in the end user’s receipt/proof of transaction. Note that if a QRIS transaction is paid using OVO, the payment reference number is only the first 12 characters from the given transaction code
send_callback Boolean FALSE - If set true, we also send response as a callback to partner

Responses Parameter

Parameter Type Nullable Description
status Object FALSE Status of response in Object
trx_id String FALSE payment routing transaction id
partner_user_id String TRUE Partner user ID. Only available for reusable VA or direct payment
partner_trx_id String FALSE Partner transaction ID
request_amount Numeric FALSE Amount requested to be paid by end user
received_amount Numeric FALSE Amount received. If user has paid, then the amount will be equal to request_amount. If you use unique code BCA, this number will contain the amount received subtracted by 3 digits generated unique code.
payment_status String FALSE Receive money status
trx_expiration_time Timestamp FALSE Transaction expiration time
payment_received_time Timestamp TRUE Indicates the time when payment routing is marked as COMPLETE (this parameter will only be sent once status of the payment routing is set to ‘COMPLETE’).
settlement_time String TRUE The timestamp (in UTC+7) indicating when the fund will be settled to partner’s account statement (this parameter will only be sent once status of the payment routing is set to ‘COMPLETE’).
settlement_status String TRUE The status of the settlement (this parameter will only be sent once status of the payment routing is set to ‘COMPLETE’).
settlement_type String TRUE Indicate if a transaction will be settled in realtime/non-realtime. (this parameter will only be sent once status of the payment routing is set to ‘COMPLETE’).
need_frontend Boolean FALSE Partner need UI or not, if true, we will route to payment link, otherwise will be routed to payment aggregator.
payment_method String TRUE The payment method used by user to complete a payment. Conditional, only exist if request need_frontend is FALSE. Refer to Payment Method on List of Allowed Payment Methods and SOF
sender_bank String TRUE The bank code used by a payer to do payment. Conditional, only exist if request need_frontend is FALSE. Refer to SOF on List of Allowed Payment Methods and SOF
payment_info Object FALSE Payment info Object
payment_checkout_url String TRUE generated url for payment link; conditional, only exist if request need_frontend is TRUE
account_number String TRUE Generated VA number if you use VA or account number destination if you use unique code BCA; conditional, only exist if request need_frontend is FALSE and payment_method is BANK_TRANSFER
account_name String TRUE VA display name if you use VA or bank account's owner name if you use unique code BCA; conditional, only exist if request need_frontend is FALSE and payment_method is BANK_TRANSFER
qris_url String TRUE the URL of QR image; conditional, only exist if request need_frontend is FALSE and payment_method is QRIS. This returned URL can only be accessed for 5 minutes after initial response was received, and is independent to the actual QRIS validity / expiration time.
payment_reference_number String FALSE Identifier of a payment attempt when the end user successfully completes the payment. The reference number is also stated in the end user’s receipt/proof of transaction. Note that if a QRIS transaction is paid using OVO, the payment reference number is only the first 12 characters from the given transaction code. Available for: QRIS
ewallet_url String TRUE For use_linked_account: true: URL that prompt user to input PIN to authorize Direct Payment. For use_linked_account: false: A deep link URL that allows user to access the specific e-wallet vendor's application for making a payment. Currently, only Linkaja, ShopeePay and Dana are supported options. This attribute will only be present if the request parameter 'need_frontend' is set to 'FALSE' and the payment method selected is 'EWALLET'.
cards_url String TRUE URL that allows user to make payment using their Credit Card. This attribute will only be present if the request parameter 'need_frontend' is set to 'FALSE' and the payment method selected is 'CARDS'.
unique_code_detail Object TRUE Contains two objects of number: amount which is the requested amount and unique_code which is the generated 3 digits unique code ; conditional, only exist if request need_frontend is FALSE and payment_method is BANK_TRANSFER and you use unique code BCA.
payment_routing List of Object TRUE List of payment routing recipients. Only available if exist upon creation. See row belows
recipient_bank String FALSE Bank code of the recipient account
recipient_account String FALSE Recipient's account number
recipient_account_name String FALSE Recipient's bank account name
recipient_amount Numeric FALSE The amount of transaction to be disbursed
recipient_email String; e-mail format TRUE Email for disbursement notification, email can be up to 5, seperated by a whitespace. Only available if exist upon creation
disbursement_trx_id String FALSE Disbursement transaction id
disbursement_trx_notes String TRUE Disbursement Transaction notes. Only available if exist upon creation
disbursement_trx_status String FALSE Disbursement transaction status. See List of Disbursement Status below
email_status String FALSE Email sending status; Possible status:- SENT- UNSENT

Partner Callback Payment Routing

Once user successfully do the payment, our system will make a callback via HTTP POST request to your system

Callback Structure for Payment Link (need_frontend = true)

{
    "trx_id": "23a009f5-24ce-4567-96b3-03c42a0fb7ae",
    "partner_trx_id": "TRX-20211117-1030",
    "receive_amount": 14000,
    "payment_status": "WAITING_PAYMENT",
    "trx_expiration_time": "2021-12-02 18:59:31",
    "need_frontend": false,
    "payment_method": "VA",
    "sender_bank": "009",
    "payment_info": {
        "payment_checkout_url": "https://pay.oyindonesia.com/12345678-9012-3456-7890-123456789012"
    },
    "payment_routing": [
        {
            "recipient_bank": "014",
            "recipient_account": "1234567890",
            "recipient_account_name": "Katelin Bode",
            "recipient_amount": 10000.0000,
            "disbursement_trx_id": "35ff4e6b-e240-44b3-aff1-1151289e912e",
            "trx_status": "WAITING"
        }
    ]
}

Callback Structure for VA

{
    "trx_id": "23a009f5-24ce-4567-96b3-03c42a0fb7ae",
    "partner_user_id": "USR-20211117-1029",
    "partner_trx_id": "TRX-20211117-1030",
    "receive_amount": 14000,
    "payment_status": "WAITING_PAYMENT",
    "trx_expiration_time": "2021-12-02 18:59:31",
    "need_frontend": false,
    "payment_method": "VA",
    "sender_bank": "009",
    "payment_info": {
        "account_number": "103406000000006289",
        "account_name": "partner_brand",
        "bank_code": "009"
    },
    "payment_routing": [
        {
            "recipient_bank": "014",
            "recipient_account": "1234567890",
            "recipient_account_name": "Katelin Bode",
            "recipient_amount": 10000.0000,
            "disbursement_trx_id": "35ff4e6b-e240-44b3-aff1-1151289e912e",
            "trx_status": "WAITING"
        }
    ]
}

Callback Structure for Unique Code

{
    "trx_id": "23a009f5-24ce-4567-96b3-03c42a0fb7ae",
    "partner_trx_id": "TRX-20211117-1030",
    "receive_amount": 14000,
    "payment_status": "WAITING_PAYMENT",
    "trx_expiration_time": "2021-12-02 18:59:31",
    "need_frontend": false,
    "payment_method": "BANK_TRANSFER",
    "sender_bank": "014",
    "payment_info": {
        "account_number": "123",
        "account_name": "PT. Dompet Harapan Bangsa",
        "bank_code": "014",
        "unique_code_detail": {
            "amount": 14123,
            "unique_code": 123,
            "unique_amount": 14000
        }
    },
    "payment_routing": [
        {
            "recipient_bank": "014",
            "recipient_account": "1234567890",
            "recipient_account_name": "Katelin Bode",
            "recipient_amount": 10000.0000,
            "disbursement_trx_id": "35ff4e6b-e240-44b3-aff1-1151289e912e",
            "trx_status": "WAITING"
        }
    ]
}

Callback Structure for QRIS

{
    "trx_id": "23a009f5-24ce-4567-96b3-03c42a0fb7ae",
    "partner_trx_id": "TRX-20211117-1030",
    "receive_amount": 14000,
    "payment_status": "WAITING_PAYMENT",
    "trx_expiration_time": "2021-12-02 18:59:31",
    "need_frontend": false,
    "payment_method": "QRIS",
    "sender_bank": "QRIS",
    "payment_info": {
        "qris_url": "https://qris.url.com",
        "payment_reference_number": "120345030342784191"
    },
    "payment_routing": [
        {
            "recipient_bank": "014",
            "recipient_account": "1234567890",
            "recipient_account_name": "Katelin Bode",
            "recipient_amount": 10000.0000,
            "disbursement_trx_id": "35ff4e6b-e240-44b3-aff1-1151289e912e",
            "trx_status": "WAITING"
        }
    ]
}

Callback Structure for E-wallet

{
    "trx_id": "23a009f5-24ce-4567-96b3-03c42a0fb7ae",
    "partner_trx_id": "TRX-20211117-1030",
    "receive_amount": 14000,
    "payment_status": "WAITING_PAYMENT",
    "trx_expiration_time": "2021-12-02 18:59:31",
    "need_frontend": false,
    "payment_method": "EWALLET",
    "sender_bank": "dana_ewallet",
    "payment_info": {
        "ewallet_url": "https://ewallet.url.com"
    },
    "payment_routing": [
        {
            "recipient_bank": "014",
            "recipient_account": "1234567890",
            "recipient_account_name": "Katelin Bode",
            "recipient_amount": 10000.0000,
            "disbursement_trx_id": "35ff4e6b-e240-44b3-aff1-1151289e912e",
            "trx_status": "WAITING"
        }
    ]
}

Callback Structure for Cards

{
    "trx_id": "23a009f5-24ce-4567-96b3-03c42a0fb7ae",
    "partner_trx_id": "TRX-20211117-1030",
    "receive_amount": 14000,
    "payment_status": "WAITING_PAYMENT",
    "trx_expiration_time": "2021-12-02 18:59:31",
    "need_frontend": false,
    "payment_method": "CARDS",
    "sender_bank": "CC_DC",
    "payment_info": {
        "card_url": "https://ccdc.link.com"
    },
    "payment_routing": [
        {
            "recipient_bank": "014",
            "recipient_account": "1234567890",
            "recipient_account_name": "Katelin Bode",
            "recipient_amount": 10000.0000,
            "disbursement_trx_id": "35ff4e6b-e240-44b3-aff1-1151289e912e",
            "trx_status": "WAITING"
        }
    ]
}

Callback for Delayed Settlement (Non-Real Time Settlement)

If your settlement is non-real time, for every transaction whose payment method is settled H+>0 from the time of transaction, you will receive two callbacks with details as follows:

  1. 1st Callback -> To be sent after your customer successfully executes the transaction. For example, if your customer executes the transaction on 11 May 2021 at 14:00:00, that is also when we send the 1st Callback to you. In the 1st callback, the settlement status is set to WAITING (because it is not yet settled to your Account Statement balance)
  2. 2nd Callback -> To be sent after the settlement status is changed from WAITING into SUCCESS. For example, if the settlement status is changed into SUCCESS on 12 May 2021 at 15:00:00, that is also when we send the 2nd Callback to you. In the 2nd callback, the settlement status is SUCCESS

Callback Parameter

Parameter Type Nullable Description
trx_id String FALSE payment routing transaction id
partner_user_id String TRUE Partner user ID. Only available for reusable VA or direct payment
use_linked_account Boolean FALSE Applicable for EWallet with need_frontend: false. If true, the transaction created is an EWallet Direct Payment transaction. Else, it is a regular EWallet transaction.
partner_trx_id String FALSE Partner transaction ID
receive_amount String FALSE Amount to be received. If you use unique code BCA, this number will contain the amount to be received subtracted by 3 digits generated unique code.
payment_status String FALSE Receive money status
trx_expiration_time Timestamp FALSE Transaction expiration time
need_frontend Boolean FALSE Partner need UI or not, if true, we will route to payment link, otherwise will be routed to payment aggregator.
payment_received_time Timestamp FALSE Indicates the time when payment routing is marked as COMPLETE (this parameter will only be sent once status of the payment routing is set to ‘COMPLETE’).
settlement_time String TRUE The timestamp (in UTC+7) indicating when the fund will be settled to partner’s account statement (this parameter will only be sent once status of the payment routing is set to ‘COMPLETE’).
settlement_status String TRUE The status of the settlement (this parameter will only be sent once status of the payment routing is set to ‘COMPLETE’).
settlement_type String TRUE Indicate if a transaction will be settled in realtime/non-realtime. (this parameter will only be sent once status of the payment routing is set to ‘COMPLETE’).
payment_method String TRUE The payment method used by user to complete a payment. Conditional, only exist if request need_frontend is FALSE. Refer to Payment Method on List of Allowed Payment Methods and SOF
sender_bank String TRUE The bank code used by a payer to do payment. Conditional, only exist if request need_frontend is FALSE. Refer to SOF on List of Allowed Payment Methods and SOF
payment_info Object FALSE Payment info Object
payment_checkout_url String TRUE generated url for payment link; conditional, only exist if request need_frontend is TRUE
account_number String TRUE Generated VA number if you use VA or account number destination if you use unique code BCA; conditional, only exist if request need_frontend is FALSE and payment_method is BANK_TRANSFER
account_name String TRUE VA display name if you use VA or bank account's owner name if you use unique code BCA; conditional, only exist if request need_frontend is FALSE and payment_method is BANK_TRANSFER
qris_url String TRUE the URL of QR image; conditional, only exist if request need_frontend is FALSE and payment_method is QRIS. This returned URL can only be accessed for 5 minutes after initial response was received, and is independent to the actual QRIS validity / expiration time.
payment_reference_number String FALSE Identifier of a payment attempt when the end user successfully completes the payment. The reference number is also stated in the end user’s receipt/proof of transaction. Note that if a QRIS transaction is paid using OVO, the payment reference number is only the first 12 characters from the given transaction code. Available for: QRIS
ewallet_url String TRUE For use_linked_account: true: URL that prompt user to input PIN to authorize Direct Payment. For use_linked_account: false: A deep link URL that allows user to access the specific e-wallet vendor's application for making a payment. Currently, only Linkaja, ShopeePay and Dana are supported options. This attribute will only be present if the request parameter 'need_frontend' is set to 'FALSE' and the payment method selected is 'EWALLET'.
cards_url String TRUE URL that allows user to make payment using their Credit Card. This attribute will only be present if the request parameter 'need_frontend' is set to 'FALSE' and the payment method selected is 'CARDS'.
unique_code_detail Object TRUE Contains two objects of number: amount which is the requested amount and unique_code which is the generated 3 digits unique code ; conditional, only exist if request need_frontend is FALSE and payment_method is BANK_TRANSFER and you use unique code BCA.
payment_routing List of Object TRUE List of payment routing recipients. Only available if exist upon creation. See row belows
recipient_bank String FALSE Bank code of the recipient account
recipient_account String FALSE Recipient's account number
recipient_account_name String FALSE Recipient's bank account name
recipient_amount Numeric FALSE The amount of transaction to be disbursed
recipient_email String; e-mail format TRUE Email for disbursement notification, email can be up to 5, seperated by a whitespace. Only available if exist upon creation
disbursement_trx_id String FALSE Disbursement transaction id
disbursement_trx_notes String TRUE Disbursement Transaction notes. Only available if exist upon creation
disbursement_trx_status String FALSE Disbursement transaction status. See List of Disbursement Status below
email_status String FALSE Email sending status; Possible status:- SENT- UNSENT

List of Payment Routing Status

Status Description
CREATED For Payment Link, Payment Link has been created.
WAITING_PAYMENT For Payment Link, user already choose a payment method in payment link but has not done the payment yet. For VA, VA number has been created.
PAYMENT_IN_PROGRESS User has made a payment and currently being processed by OY!
DISBURSE_IN_PROGRESS Money has been successfuly received and is being forwared to each recipient.
COMPLETE Money has been successfully received by recipients.
INCOMPLETE Money received but forwarding money to recipients process is totally or partially failed.
EXPIRED Payment Link or VA number has been expired.
PAYMENT_FAILED Payment has been failed, no money has been received (currently for EWALLET only)

List of Disbursement Status

Status Description
WAITING When status payment routing: CREATED / WAITING_PAYMENT / PAYMENT_IN_PROGRESS
IN_PROGRESS Money is being forwared to each recipient.
PENDING Disbursement pending because of disbursement channel
PENDING_FORCE_CREDIT When force credit process is pending
SUCCESS Money has been successfully received by recipients.
CANCEL Not receiving any payment so system will automatically cancel sending money to recipients
FAILED Sending money to recipient process is failed
FAILED_FORCE_CREDIT When force credit process is failed

Payment Routing Response Codes

Below is the list of response codes for API Payment Routing:

Response Code State Description
000 Final Response success without error
400 Final Request is rejected (Amount is not valid)
400 Final Request is rejected (Amount is empty)
400 Final Request is rejected (Invalid list payment method)
400 Final Request is rejected (Invalid list source of fund)
400 Final Request is rejected (Success redirect url is empty)
400 Final Request is rejected (Failed redirect url is empty)
400 Final Request is rejected (Reusable VA is not supported for the requested SOF)
400 Final Request is rejected (Transaction using linked account is not supported for the requested SOF)
400 Final Request is rejected (Format expiration is yyyy-MM-dd HH:mm:ss and must be greater than 1 hour)
400 Final Request is rejected (Format expiration is yyyy-MM-dd HH:mm:ss and must be within valid interval for each e-wallet type)
400 Final Request is rejected (Format expiration is yyyy-MM-dd HH:mm:ss and must be between 1 minute and 1 hour)
400 Final Request is rejected (Format expiration is yyyy-MM-dd HH:mm:ss, must be between 1 minute and 3 hours and not exceed 20:30:00)
400 Final Request is rejected (Invalid config product disburse or acceptance)
400 Final Request is rejected (Invalid partner user id)
400 Final Request is rejected (Token is already expired.)
429 Final Request Rejected (Too Many Request to specific endpoint)
203 Final Request is rejected (Duplicate Partner Tx Id)
247 Final Request is rejected (Email is not valid)
901 Non Final General Error

Below is the list of HTTP Status Code for API Payment Routing:

HTTP Status Code Description
200 Response success without error
403 Forbidden (IP address is not whitelisted or request is deemed suspicious e.g SQL injection or XSS)
404 Not Found (wrong URL)
429 Request Rejected (Too Many Request to specific endpoint)
500 Internal Server Error (OY! system encountered unknown error)
503 Service Unavailable (OY! system is unable to process the request temporarily)
504 Gateway Timeout (OY! system took too long processing the request and was unable to respond in time)

API Multi Account Management

Multi Account Management APIs allow you to interact with parent/child accounts in OY.

Disburse with Child Balance

curl -X \
POST https://partner.oyindonesia.com/api/remit \
-H 'content-type: application/json' \
-H 'accept: application/json' \
-H 'x-oy-username:myuser' \
-H 'x-api-key:987654' \
-d '{
  "recipient_bank": "014", 
  "recipient_account": "1239812390", 
  "amount":125000, 
  "note":"Split lunch bill", 
  "partner_trx_id":"1234-asdf",
  "email" :"napoleon@email.com test@email.com",
  "child_balance":"Alice"
}'
var headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json',
  'x-oy-username': '{{username}}',
  'x-api-key': '{{api-key}}'
};
var request = http.Request('POST', Uri.parse('{{base_url}}/api/remit'));
request.body = json.encode({
  "recipient_bank": "008",
  "recipient_account": "0201245681",
  "amount": 15000,
  "note": "Test API Disburse",
  "partner_trx_id": "OYON0000064",
  "email": "business.support@oyindonesia.com"
  "child_balance":"Alice"
});
request.headers.addAll(headers);

http.StreamedResponse response = await request.send();

if (response.statusCode == 200) {
  print(await response.stream.bytesToString());
}
else {
  print(response.reasonPhrase);
}
package main

import (
  "fmt"
  "strings"
  "net/http"
  "io/ioutil"
)

func main() {

  url := "%7B%7Bbase_url%7D%7D/api/remit"
  method := "POST"

  payload := strings.NewReader(`{
    "recipient_bank": "008",
    "recipient_account": "0201245681",
    "amount": 15000,
    "note": "Test API Disburse",
    "partner_trx_id": "OYON0000064",
    "email": "business.support@oyindonesia.com"
    "child_balance":"Alice"
}`)

  client := &http.Client {
  }
  req, err := http.NewRequest(method, url, payload)

  if err != nil {
    fmt.Println(err)
    return
  }
  req.Header.Add("Content-Type", "application/json")
  req.Header.Add("Accept", "application/json")
  req.Header.Add("x-oy-username", "{{username}}")
  req.Header.Add("x-api-key", "{{api-key}}")

  res, err := client.Do(req)
  if err != nil {
    fmt.Println(err)
    return
  }
  defer res.Body.Close()

  body, err := ioutil.ReadAll(res.Body)
  if err != nil {
    fmt.Println(err)
    return
  }
  fmt.Println(string(body))
}
OkHttpClient client = new OkHttpClient().newBuilder()
  .build();
MediaType mediaType = MediaType.parse("application/json");
RequestBody body = RequestBody.create(mediaType, "{\n\t\"recipient_bank\": \"008\",\n\t\"recipient_account\": \"0201245681\",\n\t\"amount\": 15000,\n\t\"note\": \"Test API Disburse\",\n\t\"partner_trx_id\": \"OYON0000064\",\n\t\"email\": \"business.support@oyindonesia.com\", \"child_balance\":\"Alice\"\n}");
Request request = new Request.Builder()
  .url("{{base_url}}/api/remit")
  .method("POST", body)
  .addHeader("Content-Type", "application/json")
  .addHeader("Accept", "application/json")
  .addHeader("x-oy-username", "{{username}}")
  .addHeader("x-api-key", "{{api-key}}")
  .build();
Response response = client.newCall(request).execute();
var data = JSON.stringify({
  "recipient_bank": "008",
  "recipient_account": "0201245681",
  "amount": 15000,
  "note": "Test API Disburse",
  "partner_trx_id": "OYON0000064",
  "email": "business.support@oyindonesia.com"
  "child_balance": "Alice"
});

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function() {
  if(this.readyState === 4) {
    console.log(this.responseText);
  }
});

xhr.open("POST", "%7B%7Bbase_url%7D%7D/api/remit");
xhr.setRequestHeader("Content-Type", "application/json");
xhr.setRequestHeader("Accept", "application/json");
xhr.setRequestHeader("x-oy-username", "{{username}}");
xhr.setRequestHeader("x-api-key", "{{api-key}}");

xhr.send(data);
<?php
require_once 'HTTP/Request2.php';
$request = new HTTP_Request2();
$request->setUrl('{{base_url}}/api/remit');
$request->setMethod(HTTP_Request2::METHOD_POST);
$request->setConfig(array(
  'follow_redirects' => TRUE
));
$request->setHeader(array(
  'Content-Type' => 'application/json',
  'Accept' => 'application/json',
  'x-oy-username' => '{{username}}',
  'x-api-key' => '{{api-key}}'
));
$request->setBody('{\n  "recipient_bank": "008",\n  "recipient_account": "0201245681",\n    "amount": 15000,\n  "note": "Test API Disburse",\n  "partner_trx_id": "OYON0000064",\n  "email": "business.support@oyindonesia.com",\n "child_balance": "Alice"\n}');
try {
  $response = $request->send();
  if ($response->getStatus() == 200) {
    echo $response->getBody();
  }
  else {
    echo 'Unexpected HTTP status: ' . $response->getStatus() . ' ' .
    $response->getReasonPhrase();
  }
}
catch(HTTP_Request2_Exception $e) {
  echo 'Error: ' . $e->getMessage();
}
import http.client
import json

conn = http.client.HTTPSConnection("{{base_url}}")
payload = json.dumps({
  "recipient_bank": "008",
  "recipient_account": "0201245681",
  "amount": 15000,
  "note": "Test API Disburse",
  "partner_trx_id": "OYON0000064",
  "email": "business.support@oyindonesia.com"
  "child_balance": "Alice"
})
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json',
  'x-oy-username': '{{username}}',
  'x-api-key': '{{api-key}}'
}
conn.request("POST", "/api/remit", payload, headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))

The above command returns JSON structured similar like this:

{
  "status":{
    "code":"101",
    "message":"Request is Processed"
  },
  "amount":125000,
  "recipient_bank":"014",
  "recipient_account":"1239812390",
  "trx_id":"ABC-456",
  "partner_trx_id":"1234-asdf",
  "timestamp":"16-10-2019 10:23:42"
}

Use this API to start disbursing money from child account to a specific beneficiary account.

HTTPS Request

[Production] POST https://partner.oyindonesia.com/api/remit
[Staging] POST https://api-stg.oyindonesia.com/api/remit

Request Parameters

Parameter Type Required Description
recipient_bank String(255) TRUE Bank Code of the Beneficiary account, see Disbursement Bank Codes
recipient_account String(255) TRUE Beneficiary account number, numeric only
amount BigInteger TRUE Amount of disbursement (Accept Non-Decimal Number), min amount 10000
note String(255) FALSE Add Note to the payout
partner_trx_id String(255) TRUE Unique Payout ID for a specific request, generated by partner
email String(255) FALSE Email for invoice notification (Optional). Email can be more than one but not more that five separated by a whitespace.
child_balance String(255) FALSE Child username whom balance will be used for disbursement, if Multi Account Management config is active (Optional). By default will be using client’s own balance.

Response Parameters

Parameter Type Description
status Object Status of Payout in Object {code: <status_code>, message: <status_message>}
amount BigInteger Amount of disbursement (Accept Non-Decimal Number)
recipient_bank String(255) Bank Code of the Beneficiary account, see Disbursement Bank Codes
recipient_account String(255) Beneficiary account number
trx_id String(36) Unique Payout ID from OY!. Partner can use this ID for settlement
partner_trx_id String(255) Unique Payout ID which partner put on the Request
timestamp String(19) Execution time of Disbursement in OY! system ("dd-MM-yyyy HH:mm:ss")

[Staging only]

You can replicate error response code (final) based on Fund Disbursement Response Codes by fill in recipient_account value using following format <desired response code>0000. Another value not following the format will be processed normally.

example:

a request with "recipient_account": "2100000" will return response with "status": { "code": "210", message": "Request is Rejected (Amount is not valid)"}

Get Child Balance

curl -X \
GET https://partner.oyindonesia.com/api/v1/multi-account/child/balance \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'X-OY-Username: janedoe' \
-H 'X-Api-Key: 7654321'
var headers = {
  'x-oy-username': '{{username}}',
  'x-api-key': '{{api-key}}',
  'Content-Type': 'application/json',
  'Accept': 'application/json'
};
var request = http.Request('GET', Uri.parse('{{base_url}}/api/v1/multi-account/child/balance'));

request.headers.addAll(headers);

http.StreamedResponse response = await request.send();

if (response.statusCode == 200) {
  print(await response.stream.bytesToString());
}
else {
  print(response.reasonPhrase);
}
package main

import (
  "fmt"
  "net/http"
  "io/ioutil"
)

func main() {

  url := "%7B%7Bbase_url%7D%7D/api/v1/multi-account/child/balance"
  method := "GET"

  client := &http.Client {
  }
  req, err := http.NewRequest(method, url, nil)

  if err != nil {
    fmt.Println(err)
    return
  }
  req.Header.Add("x-oy-username", "{{username}}")
  req.Header.Add("x-api-key", "{{api-key}}")
  req.Header.Add("Content-Type", "application/json")
  req.Header.Add("Accept", "application/json")

  res, err := client.Do(req)
  if err != nil {
    fmt.Println(err)
    return
  }
  defer res.Body.Close()

  body, err := ioutil.ReadAll(res.Body)
  if err != nil {
    fmt.Println(err)
    return
  }
  fmt.Println(string(body))
}
OkHttpClient client = new OkHttpClient().newBuilder()
  .build();
Request request = new Request.Builder()
  .url("{{base_url}}/api/v1/multi-account/child/balance")
  .method("GET", null)
  .addHeader("x-oy-username", "{{username}}")
  .addHeader("x-api-key", "{{api-key}}")
  .addHeader("Content-Type", "application/json")
  .addHeader("Accept", "application/json")
  .build();
Response response = client.newCall(request).execute();

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function() {
  if(this.readyState === 4) {
    console.log(this.responseText);
  }
});

xhr.open("GET", "%7B%7Bbase_url%7D%7D/api/v1/multi-account/child/balance");
xhr.setRequestHeader("x-oy-username", "{{username}}");
xhr.setRequestHeader("x-api-key", "{{api-key}}");
xhr.setRequestHeader("Content-Type", "application/json");
xhr.setRequestHeader("Accept", "application/json");

xhr.send();
<?php
require_once 'HTTP/Request2.php';
$request = new HTTP_Request2();
$request->setUrl('{{base_url}}/api/v1/multi-account/child/balance');
$request->setMethod(HTTP_Request2::METHOD_GET);
$request->setConfig(array(
  'follow_redirects' => TRUE
));
$request->setHeader(array(
  'x-oy-username' => '{{username}}',
  'x-api-key' => '{{api-key}}',
  'Content-Type' => 'application/json',
  'Accept' => 'application/json'
));
try {
  $response = $request->send();
  if ($response->getStatus() == 200) {
    echo $response->getBody();
  }
  else {
    echo 'Unexpected HTTP status: ' . $response->getStatus() . ' ' .
    $response->getReasonPhrase();
  }
}
catch(HTTP_Request2_Exception $e) {
  echo 'Error: ' . $e->getMessage();
}
import http.client
import json

conn = http.client.HTTPSConnection("{{base_url}}")
payload = ''
headers = {
  'x-oy-username': '{{username}}',
  'x-api-key': '{{api-key}}',
  'Content-Type': 'application/json',
  'Accept': 'application/json'
}
conn.request("GET", "/api/v1/multi-account/child/balance", payload, headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))

The above command returns JSON structured similar like this:

{
  "status":{
    "code":"000",
    "message":"Success"
  },
  "data":{
    "balances":[
      {
        "username": "JohnDoe",
        "balance":100000000.0000,
        "pendingBalance":2000000.0000,
        "availableBalance":98500000.0000
      }
    ],
    "timeStamp":"10-12-2019 12:15:37"
  }
}

Use this API to get child balance.

HTTPS Request

[Production] GET https://partner.oyindonesia.com/api/v1/multi-account/child/balance?child_username=<child_username>
[Staging] GET https://api-stg.oyindonesia.com/api/v1/multi-account/child/balance?child_username=<child_username>

Request Parameters

Parameter Type Required Description
child_username String(255) FALSE Child username whom balance info will be returned. If not specified, all child balances will be returned.

Response Parameters

Parameter Type Description
status Object Status of Request in Object {code: <status_code>, message: <status_message>}
data Object Response data {balances: <balances>, timeStamp: <timeStamp>}
balances Array of Objects List of Objects consist of username of the child, balance, overdraftBalance, overbookingBalance, pendingBalance, and availableBalance
username String(255) Child username whom balance info is returned
balance BigDecimal Remaining balance (Accept non fraction number)
overdraftBalance BigDecimal Remaining overdraft balance (Accept non fraction number)
overbookingBalance BigDecimal Remaining overbooking balance (Accept non fraction number)
pendingBalance BigDecimal The cumulative balance of your pending transactions.
availableBalance BigDecimal The total cumulative money of Balance + Available Overdraft - Pending Balance that you can use for disbursement.
timeStamp String(19) Execution time of Request in OY! system ("dd-MM-yyyy HH:mm:ss").

API GET Transaction Summary

This API allows you to get a summary of how much balance that is still waiting for settlement time within a chosen time frame. You will receive data of: * Count Transaction * Sum transaction amount * Sum admin fee amount * Sum PPN tax amount * Settlement balance after admin fee and tax.

You can select to get your pending settlement transaction summary within these time periods: today, tomorrow, or all time (all balance that has not been settled yet). "Today" means you will get summary of transaction that will be settled today. "Tommorow" means you will get summary of transaction that will be settled tommorow. While "All time" means you will get all the total balance that is still waiting for settlement. To be able to use this API, please contact our representative so we can activate this API for you.

Note: Soon, this API can provide you with the capability to get a summary of how much you have spent and earned during a time period.

HTTPS Request

[Production] GET https://partner.oyindonesia.com/api/transaction-summary
[Staging] GET https://api-stg.oyindonesia.com/api/transaction-summary

curl --location --request GET `https://partner.oyindonesia.com/api/transaction-summary` \
--header 'Content-Type: application/json' \
--header 'x-oy-username: yourusername' \
--header 'x-api-key: yourapikey' \
--data-raw '{
    "product_group": "PENDING_SETTLEMENT",
    "time_period": "ALL_TIME"
}'

The above command returns JSON structured similar like this:

{
    "status": {
        "code": "000",
        "message": "Success"
    },
    "data": 
        {
         “product_group” : “PENDING_SETTLEMENT”,
         “time_period”: “ALL_TIME”,
         “amount” : 8000000,
         “admin_fee” : 800000,
         “ppn_tax” : 88000,
         “count” : 800,
         “settlement_balance” : 7112000

        }
}

Request Headers

Parameters Type Description
X-Oy-Key String API Key for establishing connection to this particular endpoint
X-Oy-Username String The registered partner's username with enabled access for API Get Transaction Summary

Request Parameters

Parameters Type Required Description
product_group String TRUE Value must be: PENDING_SETTLEMENT (to get a summary of how much transaction that is still waiting for settlement)
time_period String TRUE Time period that you need. You can select one from these values: TODAY, TOMORROW, and ALL_TIME.

Response Parameters

Parameter Type Nullable Description
status WalletError FALSE Indicates the status of the request, it will return response code and response message
Data Object TRUE Data that you requested.

Product_group: Product group that you requested, currently only PENDING SETTLEMENT time_period: seleted time period (ALL_TIME, TODAY, or TOMMOROW) Transfer_amount: SUM amount of transaction before admin fee and tax Admin_fee: SUM admin fee Ppn_tax: SUM of PPN tax Count: count of transaction Setlement_balance: total balance that will be settled, after admin fee and tax.

Response Codes and Messages

Below is the list of response codes that show the request status for API Get Transaction Summary:

Response Code Response Message Description
000 Successful Request successful
102 Request is in progress. Please retry after several minutes Request is in progress and you should retry after several minutes
201 Username Not Found Username not found error
202 User is not active This API has not yet been activated for you
207 IP Address not registered You have not registered your IP Address
208 API Key is not valid Your API Key is invalid
229 Too many request When you make requests too much and reached the rate limit
290 Parameter / object is not valid The param you requested is invalid

API Send WhatsApp NEW

OY's API Collection for sending Whatsapp Notifications. Currently, WhatsApp can only be enabled for Payment Link and Invoice product. Contact your Business Representative if you'd like to activate this feature.

Use this API to send a payment link and/or invoice link through WhatsApp (using OY’s pre-defined template).

`curl -X POST \
  https://partner.oyindonesia.com/api/whatsapp/send-link \
  -H 'cache-control: no-cache' \
  -H 'content-type: application/json' \
  -H 'X-Api-Key: apikeymu' \
  -H 'X-Oy-Username: yourusername' \
  -d '{
        "partner_tx_id":"partnerTxId",
        "whatsapp_number":"621234567890"
    }'`
var headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json',
  'x-oy-username': '{{username}}',
  'x-api-key': '{{api-key}}'
};
var request = http.Request('POST', Uri.parse('{{base_url}}/api/whatsapp/send-link'));
request.body = json.encode({
  "partner_tx_id":"partnerTxId",
  "whatsapp_number":"621234567890"
});
request.headers.addAll(headers);

http.StreamedResponse response = await request.send();

if (response.statusCode == 200) {
  print(await response.stream.bytesToString());
}
else {
  print(response.reasonPhrase);
}
package main

import (
  "fmt"
  "strings"
  "net/http"
  "io/ioutil"
)

func main() {

  url := "%7B%7Bbase_url%7D%7D/api/whatsapp/send-link"
  method := "POST"

  payload := strings.NewReader(`{
        "partner_tx_id":"partnerTxId",
        "whatsapp_number":"621234567890"
    }`)

  client := &http.Client {
  }
  req, err := http.NewRequest(method, url, payload)

  if err != nil {
    fmt.Println(err)
    return
  }
  req.Header.Add("Content-Type", "application/json")
  req.Header.Add("Accept", "application/json")
  req.Header.Add("x-oy-username", "{{username}}")
  req.Header.Add("x-api-key", "{{api-key}}")

  res, err := client.Do(req)
  if err != nil {
    fmt.Println(err)
    return
  }
  defer res.Body.Close()

  body, err := ioutil.ReadAll(res.Body)
  if err != nil {
    fmt.Println(err)
    return
  }
  fmt.Println(string(body))
}
OkHttpClient client = new OkHttpClient().newBuilder()
  .build();
MediaType mediaType = MediaType.parse("application/json");
RequestBody body = RequestBody.create(mediaType, "{\n\"partner_tx_id\": \"partnerTxId\",\n \"whatsapp_number\": \"621234567890\"\n}");
Request request = new Request.Builder()
  .url("{{base_url}}/api/whatsapp/send-link")
  .method("POST", body)
  .addHeader("Content-Type", "application/json")
  .addHeader("Accept", "application/json")
  .addHeader("x-oy-username", "{{username}}")
  .addHeader("x-api-key", "{{api-key}}")
  .build();
Response response = client.newCall(request).execute();
var data = JSON.stringify({
  "partner_tx_id":"partnerTxId",
    "whatsapp_number":"621234567890"
});

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function() {
  if(this.readyState === 4) {
    console.log(this.responseText);
  }
});

xhr.open("POST", "%7B%7Bbase_url%7D%7D/api/whatsapp/send-link");
xhr.setRequestHeader("Content-Type", "application/json");
xhr.setRequestHeader("Accept", "application/json");
xhr.setRequestHeader("x-oy-username", "{{username}}");
xhr.setRequestHeader("x-api-key", "{{api-key}}");

xhr.send(data);
<?php
require_once 'HTTP/Request2.php';
$request = new HTTP_Request2();
$request->setUrl('{{base_url}}/api/whatsapp/send-link');
$request->setMethod(HTTP_Request2::METHOD_POST);
$request->setConfig(array(
  'follow_redirects' => TRUE
));
$request->setHeader(array(
  'Content-Type' => 'application/json',
  'Accept' => 'application/json',
  'x-oy-username' => '{{username}}',
  'x-api-key' => '{{api-key}}'
));
$request->setBody('{\n  "partner_tx_id": "partnerTxId",\n   "whatsapp_number": "621234567890"\n}');
try {
  $response = $request->send();
  if ($response->getStatus() == 200) {
    echo $response->getBody();
  }
  else {
    echo 'Unexpected HTTP status: ' . $response->getStatus() . ' ' .
    $response->getReasonPhrase();
  }
}
catch(HTTP_Request2_Exception $e) {
  echo 'Error: ' . $e->getMessage();
}
import http.client
import json

conn = http.client.HTTPSConnection("{{base_url}}")
payload = json.dumps({
  "partner_tx_id":"partnerTxId",
  "whatsapp_number":"621234567890"
})
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json',
  'x-oy-username': '{{username}}',
  'x-api-key': '{{api-key}}'
}
conn.request("POST", "/api/whatsapp/send-link", payload, headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))

JSON Response

{
    "status": {
        "code": "000",
        "message": "Success"
    },
    "data": {
        "partner_tx_id": "partnerTxId",
        "whatsapp_number": "621234567890",
        "success_queued": true,
        "message_id" : "98ndyfs98fdysdf98y-sdiufhnudfsh4hr9h8"
    }
}

[Production] POST https://partner.oyindonesia.com/api/whatsapp/send-link

[Staging] POST https://api-stg.oyindonesia.com/api/whatsapp/send-link

Parameter Type Description
X-Api-Key String API Key used to connect to this particular endpoint
X-Oy-Username String Your OY! account username
Parameter Type Required Default Description
partner_tx_id String(255) TRUE - ID generated by Partner for a specific transaction
whatsapp_number String(255) TRUE - The WhatsApp number of your users. (format 628xxxxxxxxxx)
Parameter Type Description
status Object Status of response in Object {code: <status_code>, message: <status_message>}.
data Object The API's response data in an Object, details are in the Response Data Parameters table.
Parameter Type Description
partner_tx_id String(255) ID generated by Partner for a specific transaction
whatsapp_number String(255) The WhatsApp number of your users. (format 628xxxxxxxxxx)
success_queued Boolean Filled with TRUE if a WA has successfully been successfully queued for sending
message_id String(255) Unique ID generated for each WhatsApp message being sent (null if unsuccessfully queued)

Callback WhatsApp Sending

Because of the asynchronous behavior of sending a WhatsApp message, we provide a callback for you to track the status of your message. To activate this feature please contact your business representative to provide a callback url to be sent to.

We can send multiple callback status updates for a single message depending on the situation. Each message is represented by the message_id we have provided. The general order of a successful callback status request will however be: sent -> delivered -> read

JSON Request Body

{
  "partner_tx_id": "8sd7ftbs97dgfdsg-dsfn87gsdf9b8",
  "whatsapp_number": "62123123123",
  "message_id": "987ntdsfs8dn7f8ds7fy-0bsd7ftsd08b7f",
  "status": "read"
}

Status Descriptions

Status Description
sent If the WhatsApp user blocks OY!'s WhatsApp business account, this status will be final and will not be updated (there will be no following callback status for the message). Otherwise, the status is possible to change into "delivered"
delivered Message has been delivered to the WhatsApp user but hasn't been read
read Message has been delivered to the WhatsApp user and has been read by the user. This status is final and will not be updated (there will be no following callback status for the message)
undelivered Message has not been delivered. This status is final and will not be updated (there will be no following callback status for the message)
failed Message has failed to be delivered. This status is final and will not be updated (there will be no following callback status for the message)

Callback Request Parameters

Parameter Type Description
partner_tx_id String(255) ID generated by partner for a specific transaction
whatsapp_number String(255) The WhatsApp number of your user (format: 62xxxxxxxx)
message_id String(255) Message ID of the individual message that we sent
status String(255) Status of the message. Possible values are as provided in the previous table

Biller API

Biller APIs allow you to instruct OY to do inquiry and pay bill to any available biller in Indonesia with ease and in real-time.

Bill Inquiry

curl -X \
POST https://partner.oyindonesia.com/api/v2/bill \
-H 'content-type: application/json' \
-H 'accept: application/json' \
-H 'x-oy-username:myuser' \
-H 'x-api-key:987654' \
-d '{
    "customer_id": "12345678910",
    "product_id": "plnpre",
    "partner_tx_id": "DEV123456789",
    "amount": null,
    "additional_data": null
}'
var headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json',
  'x-oy-username': '{{username}}',
  'x-api-key': '{{api-key}}'
};
var request = http.Request('POST', Uri.parse('{{base_url}}/api/v2/bill'));
request.body = json.encode({
    "customer_id": "12345678910",
    "product_id": "plnpre",
    "partner_tx_id": "DEV123456789",
    "amount": null,
    "additional_data": null
});
request.headers.addAll(headers);

http.StreamedResponse response = await request.send();

if (response.statusCode == 200) {
  print(await response.stream.bytesToString());
}
else {
  print(response.reasonPhrase);
}
package main

import (
  "fmt"
  "strings"
  "net/http"
  "io/ioutil"
)

func main() {

  url := "%7B%7Bbase_url%7D%7D/api/v2/bill"
  method := "POST"

  payload := strings.NewReader(`{
    "customer_id": "12345678910",
    "product_id": "plnpre",
    "partner_tx_id": "DEV123456789",
    "amount": null,
    "additional_data": null
  }`)

  client := &http.Client {
  }
  req, err := http.NewRequest(method, url, payload)

  if err != nil {
    fmt.Println(err)
    return
  }
  req.Header.Add("Content-Type", "application/json")
  req.Header.Add("Accept", "application/json")
  req.Header.Add("x-oy-username", "{{username}}")
  req.Header.Add("x-api-key", "{{api-key}}")

  res, err := client.Do(req)
  if err != nil {
    fmt.Println(err)
    return
  }
  defer res.Body.Close()

  body, err := ioutil.ReadAll(res.Body)
  if err != nil {
    fmt.Println(err)
    return
  }
  fmt.Println(string(body))
}
OkHttpClient client = new OkHttpClient().newBuilder()
  .build();
MediaType mediaType = MediaType.parse("application/json");
RequestBody body = RequestBody.create(mediaType, "{\n\t\"customer_id\": \"12345678910\",\n\t\"product_id\": \"plnpre\",\n\t\"partner_tx_id\": \"DEV123456789\",\n\t\"amount\": null,\n\t\"additional_data\": null\n}");
Request request = new Request.Builder()
  .url("{{base_url}}/api/v2/bill")
  .method("POST", body)
  .addHeader("Content-Type", "application/json")
  .addHeader("Accept", "application/json")
  .addHeader("x-oy-username", "{{username}}")
  .addHeader("x-api-key", "{{api-key}}")
  .build();
Response response = client.newCall(request).execute();
var data = JSON.stringify({
    "customer_id": "12345678910",
    "product_id": "plnpre",
    "partner_tx_id": "DEV123456789",
    "amount": null,
    "additional_data": null
});

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function() {
  if(this.readyState === 4) {
    console.log(this.responseText);
  }
});

xhr.open("POST", "%7B%7Bbase_url%7D%7D/api/v2/bill");
xhr.setRequestHeader("Content-Type", "application/json");
xhr.setRequestHeader("Accept", "application/json");
xhr.setRequestHeader("x-oy-username", "{{username}}");
xhr.setRequestHeader("x-api-key", "{{api-key}}");

xhr.send(data);
<?php
require_once 'HTTP/Request2.php';
$request = new HTTP_Request2();
$request->setUrl('{{base_url}}/api/v2/bill');
$request->setMethod(HTTP_Request2::METHOD_POST);
$request->setConfig(array(
  'follow_redirects' => TRUE
));
$request->setHeader(array(
  'Content-Type' => 'application/json',
  'Accept' => 'application/json',
  'x-oy-username' => '{{username}}',
  'x-api-key' => '{{api-key}}'
));
$request->setBody('{\n  "customer_id": "12345678910",\n  "product_id": "plnpre",\n  "partner_tx_id": "DEV123456789",\n  "amount": null,\n  "additional_data": null\n}');
try {
  $response = $request->send();
  if ($response->getStatus() == 200) {
    echo $response->getBody();
  }
  else {
    echo 'Unexpected HTTP status: ' . $response->getStatus() . ' ' .
    $response->getReasonPhrase();
  }
}
catch(HTTP_Request2_Exception $e) {
  echo 'Error: ' . $e->getMessage();
}
import http.client
import json

conn = http.client.HTTPSConnection("{{base_url}}")
payload = json.dumps({
    "customer_id": "12345678910",
    "product_id": "plnpre",
    "partner_tx_id": "DEV123456789",
    "amount": null,
    "additional_data": null
})
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json',
  'x-oy-username': '{{username}}',
  'x-api-key': '{{api-key}}'
}
conn.request("POST", "/api/v2/bill", payload, headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))

The above command returns JSON structured similar like this:

{
  "status": {
    "code": "000",
    "message": "Success",
  },
  "data": {
    "tx_id": "12345-12345-12345-12345",
    "partner_tx_id": "DEV123456789",
    "product_id": "plnpre",
    "customer_id": "000372190053",
    "customer_name": "FIRDAUS", 
    "amount": 832500,
    "admin_fee": 2500,
    "additional_data": "{\"electric_power\":\"R1M/900 VA\",\"customer_id\":\"000372190053\",\"customer_name\":\"FIRDAUS\",\"total_amount\":835000}"
  },
}

Use this API to do Inquiry and get detail information on the Bill before paying.

HTTPS Request

[Production] POST https://partner.oyindonesia.com/api/v2/bill
[Staging] POST https://api-stg.oyindonesia.com/api/v2/bill

Request Parameters

Parameter Type Required Description
customer_id String(255) TRUE Customer ID for specific biller product
product_id String(255) TRUE OY's Biller ID, see Biller Products List
partner_tx_id String(255) TRUE Unique Payout ID for a specific request, generated by partner
amount BigInteger FALSE Product denom/amount, only for PLN Prepaid 20.000, 50.000, 100.000, 200.000, 500.000, 1.000.000
additional_data String(255) FALSE Required for BPJS and PBB,
BPJS (number of months, ex : 3 is for 3 months),
PBB (tax year, ex 2023 is for tax 2023)

Response Parameters

Parameter Type Description
status Object Status of Payout in Object {code: <status_code>, message: <status_message>}
data Object Data object that wraps the response parameters
tx_id String(36) Unique Payout ID from OY!. Partner can use this ID for settlement
customer_id String(255) Customer ID for specific biller product
product_id String(255) OY's Biller ID, see Biller Products List
partner_tx_id String(255) Unique Payout ID for a specific request, generated by partner
customer_name String(255) Customer Name from biller
amount BigDecimal Bill's amount (excluding admin fee).
admin_fee BigDecimal Bill's admin fee
additional_data Object Additional detailed data from biller

Pay Bill

curl -X \
POST https://partner.oyindonesia.com/api/v2/bill/payment \
-H 'content-type: application/json' \
-H 'accept: application/json' \
-H 'x-oy-username:myuser' \
-H 'x-api-key:987654' \
-d '{
  "partner_tx_id": "DEV123456789",
  "note": "Payment for bill #001"
}'
var headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json',
  'x-oy-username': '{{username}}',
  'x-api-key': '{{api-key}}'
};
var request = http.Request('POST', Uri.parse('{{base_url}}/api/v2/bill/payment'));
request.body = json.encode({
  "partner_tx_id": "DEV123456789",
  "note": "Payment for bill #001"
});
request.headers.addAll(headers);

http.StreamedResponse response = await request.send();

if (response.statusCode == 200) {
  print(await response.stream.bytesToString());
}
else {
  print(response.reasonPhrase);
}
package main

import (
  "fmt"
  "strings"
  "net/http"
  "io/ioutil"
)

func main() {

  url := "%7B%7Bbase_url%7D%7D/api/v2/bill/payment"
  method := "POST"

  payload := strings.NewReader(`{
    "partner_tx_id": "DEV123456789",
    "note": "Payment for bill #001",
  }`)

  client := &http.Client {
  }
  req, err := http.NewRequest(method, url, payload)

  if err != nil {
    fmt.Println(err)
    return
  }
  req.Header.Add("Content-Type", "application/json")
  req.Header.Add("Accept", "application/json")
  req.Header.Add("x-oy-username", "{{username}}")
  req.Header.Add("x-api-key", "{{api-key}}")

  res, err := client.Do(req)
  if err != nil {
    fmt.Println(err)
    return
  }
  defer res.Body.Close()

  body, err := ioutil.ReadAll(res.Body)
  if err != nil {
    fmt.Println(err)
    return
  }
  fmt.Println(string(body))
}
OkHttpClient client = new OkHttpClient().newBuilder()
  .build();
MediaType mediaType = MediaType.parse("application/json");
RequestBody body = RequestBody.create(mediaType, "{\n\t\"partner_tx_id\": \"DEV123456789\",\n\t\"note\": \"Payment for bill #001\"\n}");
Request request = new Request.Builder()
  .url("{{base_url}}/api/v2/bill/payment")
  .method("POST", body)
  .addHeader("Content-Type", "application/json")
  .addHeader("Accept", "application/json")
  .addHeader("x-oy-username", "{{username}}")
  .addHeader("x-api-key", "{{api-key}}")
  .build();
Response response = client.newCall(request).execute();
var data = JSON.stringify({
  "partner_tx_id": "DEV123456789",
  "note": "Payment for bill #001"
});

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function() {
  if(this.readyState === 4) {
    console.log(this.responseText);
  }
});

xhr.open("POST", "%7B%7Bbase_url%7D%7D/api/v2/bill/payment");
xhr.setRequestHeader("Content-Type", "application/json");
xhr.setRequestHeader("Accept", "application/json");
xhr.setRequestHeader("x-oy-username", "{{username}}");
xhr.setRequestHeader("x-api-key", "{{api-key}}");

xhr.send(data);
<?php
require_once 'HTTP/Request2.php';
$request = new HTTP_Request2();
$request->setUrl('{{base_url}}/api/v2/bill/payment');
$request->setMethod(HTTP_Request2::METHOD_POST);
$request->setConfig(array(
  'follow_redirects' => TRUE
));
$request->setHeader(array(
  'Content-Type' => 'application/json',
  'Accept' => 'application/json',
  'x-oy-username' => '{{username}}',
  'x-api-key' => '{{api-key}}'
));
$request->setBody('{\n "partner_tx_id": "DEV123456789",\n "note": "Payment for bill #001"\n}');
try {
  $response = $request->send();
  if ($response->getStatus() == 200) {
    echo $response->getBody();
  }
  else {
    echo 'Unexpected HTTP status: ' . $response->getStatus() . ' ' .
    $response->getReasonPhrase();
  }
}
catch(HTTP_Request2_Exception $e) {
  echo 'Error: ' . $e->getMessage();
}
import http.client
import json

conn = http.client.HTTPSConnection("{{base_url}}")
payload = json.dumps({
  "partner_tx_id": "DEV123456789",
  "note": "Payment for bill #001"
})
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json',
  'x-oy-username': '{{username}}',
  'x-api-key': '{{api-key}}'
}
conn.request("POST", "/api/v2/bill/payment", payload, headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))

The above command returns JSON structured similar like this:

{
    "status": {
        "code": "101",
        "message": "In Progress",
    },
    "data": {
        "tx_id": "12345-12345-12345-12345",
        "customer_id": "000372190053",
        "product_id": "BPFI",
        "partner_tx_id": "DEV123456789",
        "note": "note for payment",
        "customer_name": "FIRDAUS", 
        "amount": 835000,
        "admin_fee": 2500,
    }
}

This API will enable you to do payment for your bill. You need to do inquiry first before calling this API.

HTTPS Request

[Production] POST https://partner.oyindonesia.com/api/v2/bill/payment
[Staging] POST https://api-stg.oyindonesia.com/api/v2/bill/payment

Request Parameters

Parameter Type Required Description
partner_tx_id String(255) TRUE Unique Payout ID for a specific request, generated by partner
note String(255) FALSE Partner defined note for bill payment

Response Parameters

Parameter Type Description
status Object Status of Payout in Object {code: <status_code>, message: <status_message>}
data Object Data object that wraps the response parameters
tx_id String(36) Unique Payout ID from OY!. Partner can use this ID for settlement
customer_id String(255) Customer ID for specific biller product
product_id String(255) OY's Biller ID, see Biller Products List
partner_tx_id String(255) Unique Payout ID for a specific request, generated by partner
customer_name String(255) Customer Name from biller
note String(255) Partner defined note for bill payment
amount BigDecimal Bill's amount (excluding admin fee).
admin_fee BigDecimal Bill's admin fee

Partner Callback

Response callback:

{
  "status": {
    "code": "000",
    "message": "Success",
  },
  "data": {
    "tx_id": "12345-12345-12345-12345",
    "partner_tx_id": "DEV123456789",
    "product_id": "BPFI",
    "customer_id": "000372190053",
    "customer_name": "FIRDAUS", 
    "amount": 835000,
    "admin_fee": 2500,
    "note": "note for payment",
    "additional_data": "{\"customer_id\":\"000372190053\",\"customer_name\":\"FIRDAUS\",\"total_amount\":835000,\"receipt_code\":\"123123123123\",\"settlement_date\":\"2020-10-1917:16:17\"}"
  },
}

Once a bill payment request has finished, our system will make a callback status of that payment request to your system

Please contact us and submit a callback URL if you need a callback status of a bill payment request.

Callback Parameters

Parameter Type Description
status Object Status of Payout in Object {code: <status_code>, message: <status_message>}
data Object Data object that wraps the response parameters
tx_id String(36) Unique Payout ID from OY!. Partner can use this ID for settlement
customer_id String(255) Customer ID for specific biller product
product_id String(255) OY's Biller ID, see Biller Products List
partner_tx_id String(255) Unique Payout ID for a specific request, generated by partner
customer_name String(255) Customer Name from biller
amount BigDecimal Bill's amount (excluding admin fee).
admin_fee BigDecimal Bill's admin fee
additional_data Object Additional detailed data from biller
note String(255) Partner defined note for bill payment

Get Bill Payment Status

curl -X \
GET https://partner.oyindonesia.com/api/v2/bill/status?partner_tx_id=partner-tx-id-001 \
-H 'content-type: application/json' \
-H 'accept: application/json' \
-H 'x-oy-username:myuser' \
-H 'x-api-key:987654' \
var headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json',
  'x-oy-username': '{{username}}',
  'x-api-key': '{{api-key}}'
};
var request = http.Request('GET', Uri.parse('{{base_url}}/api/v2/bill/status?partner_tx_id=partner-tx-id-001'));
request.headers.addAll(headers);

http.StreamedResponse response = await request.send();

if (response.statusCode == 200) {
  print(await response.stream.bytesToString());
}
else {
  print(response.reasonPhrase);
}
package main

import (
  "fmt"
  "strings"
  "net/http"
  "io/ioutil"
)

func main() {

  url := "%7B%7Bbase_url%7D%7D/api/v2/bill/status?partner_tx_id=partner-tx-id-001"
  method := "GET"

  client := &http.Client {
  }
  req, err := http.NewRequest(method, url, nil)

  if err != nil {
    fmt.Println(err)
    return
  }
  req.Header.Add("Content-Type", "application/json")
  req.Header.Add("Accept", "application/json")
  req.Header.Add("x-oy-username", "{{username}}")
  req.Header.Add("x-api-key", "{{api-key}}")

  res, err := client.Do(req)
  if err != nil {
    fmt.Println(err)
    return
  }
  defer res.Body.Close()

  body, err := ioutil.ReadAll(res.Body)
  if err != nil {
    fmt.Println(err)
    return
  }
  fmt.Println(string(body))
}
OkHttpClient client = new OkHttpClient().newBuilder()
  .build();
Request request = new Request.Builder()
  .url("{{base_url}}/api/v2/bill/status?partner_tx_id=partner-tx-id-001")
  .method("GET", null)
  .addHeader("Content-Type", "application/json")
  .addHeader("Accept", "application/json")
  .addHeader("x-oy-username", "{{username}}")
  .addHeader("x-api-key", "{{api-key}}")
  .build();
Response response = client.newCall(request).execute();

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function() {
  if(this.readyState === 4) {
    console.log(this.responseText);
  }
});

xhr.open("GET", "%7B%7Bbase_url%7D%7D/api/v2/bill/status?partner_tx_id=partner-tx-id-001");
xhr.setRequestHeader("Content-Type", "application/json");
xhr.setRequestHeader("Accept", "application/json");
xhr.setRequestHeader("x-oy-username", "{{username}}");
xhr.setRequestHeader("x-api-key", "{{api-key}}");

xhr.send();
<?php
require_once 'HTTP/Request2.php';
$request = new HTTP_Request2();
$request->setUrl('{{base_url}}/api/v2/bill/status?partner_tx_id=partner-tx-id-001');
$request->setMethod(HTTP_Request2::METHOD_GET);
$request->setConfig(array(
  'follow_redirects' => TRUE
));
$request->setHeader(array(
  'Content-Type' => 'application/json',
  'Accept' => 'application/json',
  'x-oy-username' => '{{username}}',
  'x-api-key' => '{{api-key}}'
));
try {
  $response = $request->send();
  if ($response->getStatus() == 200) {
    echo $response->getBody();
  }
  else {
    echo 'Unexpected HTTP status: ' . $response->getStatus() . ' ' .
    $response->getReasonPhrase();
  }
}
catch(HTTP_Request2_Exception $e) {
  echo 'Error: ' . $e->getMessage();
}
import http.client
import json

conn = http.client.HTTPSConnection("{{base_url}}")
payload = ''
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json',
  'x-oy-username': '{{username}}',
  'x-api-key': '{{api-key}}'
}
conn.request("GET", "/api/v2/bill/status?partner_tx_id=partner-tx-id-001", payload, headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))

The above command returns JSON structured similar like this:

{
  "status": { 
    "code": "000",
    "message": "Success",
  },
  "data": {
    "tx_id":"12345-12345-12345-12345", 
    "partner_tx_id": "DEV123456789",
    "product_id": "BPFI",
    "customer_id": "000372190053",
    "customer_name": "FIRDAUS", 
    "amount": 835000, 
    "admin_fee": 2500, 
    "status": "SUCCESS",
    "tx_status_description": "",
    "additional_data": "{\"customer_id\":\"000372190053\",\"customer_name\":\"FIRDAUS\",\"total_amount\":835000,\"receipt_code\":\"123123123123\",\"settlement_date\":\"2020-10-1917:16:17\"}"
  }
}

This endpoint allows you to get the status of an inquiried bill.

HTTPS Request

[Production] GET https://partner.oyindonesia.com/api/v2/bill/status?partner_tx_id=<partner_tx_id>
[Staging] GET https://api-stg.oyindonesia.com/api/v2/bill/status?partner_tx_id=<partner_tx_id>

Request Parameters

Parameter Type Required Description
partner_tx_id String(255) TRUE Unique Payout ID which partner put on scheduled disburse creation

Response Parameters

Parameter Type Description
status Object Status of Check Status hit in Object {code: <status_code>, message: <status_message>}
data Object Data object that wraps the response parameters
tx_id String(36) Unique Payout ID from OY!. Partner can use this ID for settlement
customer_id String(255) Customer ID for specific biller product
product_id String(255) OY's Biller ID, see Biller Products List
partner_tx_id String(255) Unique Payout ID for a specific request, generated by partner
customer_name String(255) Customer Name from biller
amount BigDecimal Bill's amount (excluding admin fee).
admin_fee BigDecimal Bill's admin fee
additional_data Object Additional detailed data from biller
status String Biller Transaction Status, Refer to API Biller Status
tx_status_description String Error reason if exists, field is blank if status is SUCCESS

Get Bill Products List

curl -X \
GET https://partner.oyindonesia.com/api/v2/bill/products \
-H 'content-type: application/json' \
-H 'accept: application/json' \
-H 'x-oy-username:myuser' \
-H 'x-api-key:987654' \
var headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json'
};
var request = http.Request('GET', Uri.parse('{{base_url}}/api/v2/bill/products'));
request.body = json.encode({
  "partner_tx_id": "partner-tx-id-001"
});
request.headers.addAll(headers);

http.StreamedResponse response = await request.send();

if (response.statusCode == 200) {
  print(await response.stream.bytesToString());
}
else {
  print(response.reasonPhrase);
}
package main

import (
  "fmt"
  "strings"
  "net/http"
  "io/ioutil"
)

func main() {

  url := "%7B%7Bbase_url%7D%7D/api/v2/bill/products"
  method := "GET"

  client := &http.Client {
  }
  req, err := http.NewRequest(method, url)

  if err != nil {
    fmt.Println(err)
    return
  }
  req.Header.Add("Content-Type", "application/json")
  req.Header.Add("Accept", "application/json")

  res, err := client.Do(req)
  if err != nil {
    fmt.Println(err)
    return
  }
  defer res.Body.Close()

  body, err := ioutil.ReadAll(res.Body)
  if err != nil {
    fmt.Println(err)
    return
  }
  fmt.Println(string(body))
}
OkHttpClient client = new OkHttpClient().newBuilder()
  .build();
Request request = new Request.Builder()
  .url("{{base_url}}/api/v2/bill/products")
  .method("GET", null)
  .addHeader("Content-Type", "application/json")
  .addHeader("Accept", "application/json")
  .build();
Response response = client.newCall(request).execute();
var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function() {
  if(this.readyState === 4) {
    console.log(this.responseText);
  }
});

xhr.open("GET", "%7B%7Bbase_url%7D%7D/api/v2/bill/products");
xhr.setRequestHeader("Content-Type", "application/json");
xhr.setRequestHeader("Accept", "application/json");

xhr.send();
<?php
require_once 'HTTP/Request2.php';
$request = new HTTP_Request2();
$request->setUrl('{{base_url}}/api/v2/bill/products');
$request->setMethod(HTTP_Request2::METHOD_GET);
$request->setConfig(array(
  'follow_redirects' => TRUE
));
$request->setHeader(array(
  'Content-Type' => 'application/json',
  'Accept' => 'application/json'
));
try {
  $response = $request->send();
  if ($response->getStatus() == 200) {
    echo $response->getBody();
  }
  else {
    echo 'Unexpected HTTP status: ' . $response->getStatus() . ' ' .
    $response->getReasonPhrase();
  }
}
catch(HTTP_Request2_Exception $e) {
  echo 'Error: ' . $e->getMessage();
}
import http.client
import json

conn = http.client.HTTPSConnection("{{base_url}}")
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json'
}
conn.request("GET", "/api/v2/bill/products", payload, headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))

The above command returns JSON structured similar like this:

{
  "status": { 
    "code": "000",
    "message": "Success",
  },
  "data": {
    "product_list": [
      {
        "product_id": "plnpre",
        "description": "pln prepaid",
        "admin_fee": 2500.0000,
        "amount": 50000.0000,
        "is_available": true
      },
      ...
  }
}

This endpoint allows you to get the list of bill products available.

HTTPS Request

[Production] GET https://partner.oyindonesia.com/api/v2/bill/products
[Staging] GET https://api-stg.oyindonesia.com/api/v2/bill/products

Response Parameters

Parameter Type Description
status Object Status of Payout in Object {code: <status_code>, message: <status_message>}
data Object Data object that wraps the response parameters
product_list Array of Object List of API Biller Product Object
product_id String(255) OY's Biller ID, see Biller Products List
description String(255) Product Description / Name
amount BigDecimal Bill's amount (excluding admin fee).
admin_fee BigDecimal Bill's admin fee
is_available Boolean Product availabilty

API Biller Response Codes

These are the list of possible response codes for API Biller:

Status State Meaning
000 Final Inquiry or Payment Request has been completed (SUCCESS)
102 Non-Final Request is In Progress
300 Final Transaction Failed (FAILED)
302 Final Customer ID Not Found (FAILED)
303 Final Product Not Exist or Not Available (FAILED)
304 Final Invalid Data (FAILED)
305 Final Customer ID Already Paid (FAILED)
306 Final System on the Cut-off Schedule (FAILED)
307 Final Biller System Error (FAILED)
400 Non-Final Transaction Pending (PENDING)

The following status codes are for rejected requests

Status State Meaning
201 Final Request is Rejected (User ID is not Found)
202 Final Request is Rejected (User ID is not Active)
203 Final Request is Rejected (Duplicate Partner Tx ID)
204 Final Request is Rejected (Partner Tx ID is Not Found)
205 Final Request is Rejected (Biller product_id is not available at this moment)
206 Final Request is Rejected (Partner Deposit Balance is Not Enough)
207 Final Request is Rejected (Request IP Address is not Registered)
208 Final Request is Rejected (API Key is not Valid)
210 Final Request is Rejected (Invalid denom amount request)
223 Final Request is Rejected (Duplicate payment request)
290 Final Request is Rejected (Parameter / object is not valid)
999 Final Internal Server Error

API Biller Status

These are all the status that apply to API Biller product

Status Meaning
INQUIRY Bill has been inquired and may be paid
IN_PROGRESS Processing payment request to biller provider
PENDING Unknown status from biller provider and will be resolved manually
SUCCESS Bill payment success
FAILED Bill payment failed

Mock Value for Staging

Inquiry

You can mock the inquiry to return failed status. To do this, fill in the customer_id to any number with the last number being 9. When inquiring this customer id to any product, it will return failed response. customer_id with last character other than 9 will return success inquiry.

example:

a request with "customer_id": "123456789" will mock the inquiry to return failed inquiry status with reason Internal Server Error.
a request with "customer_id": "1234563059" will mock the inquiry to return failed inquiry status with reason Bill is Already Paid or Not Found.
a request with "customer_id": "1234563029" will mock the inquiry to return failed inquiry status with reason Customer Id is Not Found. a request with "customer_id": "987654321" will return success inquiry.

Payment

You can replicate error response code (final) by filling in customer_id value using following format <desired response code>0000. Another value not following the format will be processed normally. The response codes that are available are 300 for FAILED, and 301 for PENDING.

example:

a request with "customer_id": "3010000" will mock the payment callback to return pending status.

Test Scenario

To test out all scenarios of API Biller and ensure the flows in your integration are handled correctly, please visit this link

Biller Products List

Here is the list of available bill products in our Biller Service

Insurance

Product Id Product Description
bpjsks BPJS KESEHATAN
bpjs-ketenagakerjaan BPJS KETENAGAKERJAAN
bpjs-denda BPJS DENDA
asrjws ASURANSI JIWASRAYA/ASURANSI IFG LIFE
asrtokios TOKIO MARINE
asrbint1 ASURANSI BINTANG PAKET 1
asrbint2 ASURANSI BINTANG PAKET 2
asrcar CENTRAL ASIA RAYA
asrpru PRUDENTIAL PREMI LANJUTAN

PLN

Product Id Product Description
plnpost PLN POSTPAID
plnpre PLN PREPAID

Internet

Product Id Product Description
telkom TELKOM / TELKOM SPEEDY
myrepublic MYREPUBLIC
cbn CBN
centrin-online CENTRIN ONLINE
comet-internet MYREPUBLIC
indihome INDIHOME
mnc-play MNC PLAY

TV Cable

Product Id Product Description
tvbig BIG TV
tvindvs INDOVISION
tvindvs TOPTV
tvindvs OKEVISION
tvnex NEX MEDIA
tvtlkmv TRANSVISION
tvtlkmv TELKOMVISION
tvtlkmv YESTV
tvtopas TOPAS TV
k-vision K VISION
mnc-vision MNC VISION

Multifinance

Product Id Product Description
alf AL IJARAH FINANCE
apf ARTHA PRIMA FINANCE
bpfi BATAVIA FINANCE
bmf BIMA FINANCE
bprkm BPR KM
bprnbp BPR NBP
citra CAKRAWALA CITRAMEGA MULTIFINANCE
edv ESTA DANA VENTURA
jgdr JAGADIRI
cvk KOPERASI ANUGRAH MEGA MANDIRI
nrc KOPERASI NRC
mdl MANDALA
mtf MANDIRI TUNAS FINANCE
maf MEGA AUTO FINANCE
mcf MEGA CENTRAL FINANCE
mf MEGA FINANCE
mbf MIZUHO BALIMOR FINANCE
pmt PERMATA FINANCE
dtpr PRIMA PEGADAIAN
dtpu PUTRA PEGADAIAN
smmf SINARMAS
smf SMART FINANCE
sol SOLITE
top TOP FINANCE
tpf TRANS PACIFIC
trh TRIHAMAS FINANCE

PDAM

Product Id Product Description
pdamkab.mojokerto PDAM KAB MOJOKERTO
pdamkab.sidoarjo PDAM KAB SIDOARJO
pdamkab.bojonegoro PDAM KAB BOJONEGORO
pdamkab.malang PDAM KAB MALANG
pdamkab.bogor PDAM KAB BOGOR
pdamaetra PDAM AETRA
pdampalyja PDAM PALYJA
pdamkab.bandung PDAM BANDUNG KOT
pdamkab.bangkalan PDAM BANGKALAN KAB
pdamkab.cilacap PDAM CILACAP KAB
pdamkab.jember PDAM JEMBER KAB
pdamkot.lampung PDAM LAMPUNG KOT
pdamkot.mataram PDAM MATARAM KOT
pdamkot.palembang PDAM PALEMBANG KOT
pdamkab.semarang PDAM SEMARANG KAB
pdamkot.surabaya PDAM SURABAYA KOT
pdamkab.tapin PDAM TAPIN KAB
pdamketapang PDAM KETAPANG
pdammakasar PDAM MAKASAR

PBB

Product Id Product Description
pbbdki.jakarta PBB DKI JAKARTA
pbbkab.bandung PBB KAB. BANDUNG
pbbkab.bandungbarat PBB KAB. BANDUNG BARAT
pbbkab.banjarnegara PBB KAB. BANJAR NEGARA
pbbkab.banyumas PBB KAB. BANYUMAS
pbbkab.batang PBB KAB. BATANG
pbbkab.bekasicikarang PBB KAB. BEKASI CIKARANG
pbbkab.blora PBB KAB. BLORA
pbbkab.bogorcibinong PBB KAB. BOGOR CIBINONG
pbbkab.boyolali PBB KAB BOYOLALI
pbbkab.brebes PBB KAB. BREBES
pbbkab.ciamis PBB KAB. CIAMIS
pbbkab.cianjur PBB KAB. CIANJUR
pbbkab.cilacap PBB KAB. CILACAP
pbbkab.cirebon PBB KAB. CIREBON
pbbkab.demak PBB KAB. DEMAK
pbbkab.garut PBB KAB. GARUT
pbbkab.grobogan PBB KAB. GROBOGAN
pbbkab.indramayu PBB KAB. INDRAMAYU
pbbkab.jepara PBB KAB. JEPARA
pbbkab.karangayar PBB KAB. KARANGAYAR
pbbkab.karawang PBB KAB. KARAWANG
pbbkab.kebumen PBB KAB. KEBUMEN
pbbkab.kendal PBB KAB. KENDAL
pbbkab.klaten PBB KAB. KLATEN
pbbkab.kudus PBB KAB. KUDUS
pbbkab.kuningan PBB KAB. KUNINGAN
pbbkab.lebak PBB KAB. LEBAK
pbbkab.magelang PBB KAB. MAGELANG
pbbkab.majalengka PBB KAB. MAJALENGKA
pbbkab.pandeglang PBB KAB. PANDEGLANG
pbbkab.pangandaran PBB KAB. PANGANDARAN
pbbkab.pati PBB KAB.PATI
pbbkab.pekalongan PBB KAB. PEKALONGAN
pbbkab.pemalang PBB KAB. PEMALANG
pbbkab.purbalingga PBB KAB.PURBALINGGA
pbbkab.purwakarta PBB KAB. PURWAKARTA
pbbkab.purworejo PBB KAB. PURWOREJO
pbbkab.rembang PBB KAB. REMBANG
pbbkab.semarang PBB KAB. SEMARANG
pbbkab.serang PBB KAB. SERANG
pbbkab.sragen PBB KAB. SRAGEN
pbbkab.subang PBB KOTA SUBANG
pbbkab.sukabumi PBB KAB. SUKABUMI
pbbkab.sukaharjo PBB KAB. SUKAHARJO
pbbkab.sumedang PBB KAB. SUMEDANG
pbbkab.tangerang PBB KAB. TANGERANG
pbbkab.tasikmalaya PBB KAB. TASIKMALAYA
pbbkab.tegal PBB KAB.TEGAL
pbbkab.temanggung PBB KAB. TEMANGGUNG
pbbkab.wonogiri PBB KAB.WONOGIRI
pbbkab.wonosobo PBB KAB. WONOSOBO
pbbkot.banjar PBB KOTA BANJAR
pbbkot.bekasi PBB KOTA BEKASI
pbbkot.bogor PBB KOTA BOGOR
pbbkot.cilegon PBB KOTA CILEGON
pbbkot.cimahi PBB KOTA CIMAHI
pbbkot.cirebon PBB KOTA CIREBON
pbbkot.depok PBB KOTA DEPOK
pbbkot.magelang PBB KOTA MAGELANG
pbbkot.pekalongan PBB KOTA PEKALONGAN
pbbkot.pekanbaru PBB KOTA PEKAN BARU
pbbkot.salatiga PBB KOTA SALATIGA
pbbkot.semarang PBB KOTA SEMARANG
pbbkot.serang PBB KOTA SERANG
pbbkot.sukabumi PBB KOTA SUKABUMI
pbbkot.surakarta PBB KOTA SURAKARTA
pbbkot.tangerang PBB KOTA TANGERANG
pbbkot.tangerangselatan PBB KOTA TANGERANG SELATAN
pbbkot.tasikmalaya PBB KOTA TASIKMALAYA

Voucher Pulsa

Product Id Product Description
as100 PULSA AS 100.000
as10 PULSA AS 10.000
as25 PULSA AS 25.000
as50 PULSA AS 50.000
as5 PULSA AS 5.000
sim100 PULSA SIMPATI 100.000
sim10 PULSA SIMPATI 10.000
sim20 PULSA SIMPATI 20.000
sim50 PULSA SIMPATI 50.000
sim5 PULSA SIMPATI 5.000
mr20 PULSA MENTARI REGULAR 20.000
mr100 PULSA MENTARI REGULAR 100.000
mr10 PULSA MENTARI REGULAR 10.000
mr25 PULSA MENTARI REGULAR 25.000
mr50 PULSA MENTARI REGULAR 50.000
mr5 PULSA MENTARI REGULAR 5.000
imr100 PULSA IM3 REGULAR 100.000
imr10 PULSA IM3 REGULAR 10.000
imr25 PULSA IM3 REGULAR 25.000
imr50 PULSA IM3 REGULAR 50.000
imr5 PULSA IM3 REGULAR 5.000
imr20 PULSA IM3 REGULAR 20.000
axp100 PULSA AXIS 100.000
axp10 PULSA AXIS 10.000
axp25 PULSA AXIS 25.000
axp50 PULSA AXIS 50.000
axp5 PULSA AXIS 5.000
xlv100 PULSA XL VOUCHER 100.000
xlv10 PULSA XL VOUCHER 10.000
xlv25 PULSA XL VOUCHER 25.000
xlv50 PULSA XL VOUCHER 50.000
xlv5 PULSA XL VOUCHER 5.000
sf5 PULSA SMARTFREN 5.000
sf10 PULSA SMARTFREN 10.000
sf20 PULSA SMARTFREN 20.000
sf25 PULSA SMARTFREN 25.000
sf50 PULSA SMARTFREN 50.000
sf60 PULSA SMARTFREN 60.000
sf100 PULSA SMARTFREN 100.000
sf150 PULSA SMARTFREN 150.000
tri1 PULSA THREE 1.000
tri2 PULSA THREE 2.000
tri5 PULSA THREE 5.000
tri10 PULSA THREE 10.000
tri15 PULSA THREE 15.000
tri20 PULSA THREE 20.000
tri25 PULSA THREE 25.000
tri30 PULSA THREE 30.000
tri50 PULSA THREE 50.000
tri100 PULSA THREE 100.000
tri150 PULSA THREE 150.000
tri200 PULSA THREE 200.000
tri300 PULSA THREE 300.000
tri500 PULSA THREE 500.000

e-Wallet

Product Id Product Description
dana E-WALLET TOP UP DANA
shopeepay E-WALLET TOP UP SHOPEEPAY
ovo E-WALLET TOP UP OVO
linkaja E-WALLET TOP UP LINKAJA
grab TOP UP DRIVER GRAB
maxim TOP UP DRIVER MAXIM

API Account Linking

OY's API Collection to link user's phone number to e-wallets. Currently, this feature support to link user's phone number to DANA and ShopeePay e-wallet. Contact your Business Representative if you'd like to activate this feature.

Get Linking URL

Use this API to get the linking URL for your user.

curl --location --request POST 'https://partner.oyindonesia.com/api/account/linking' \
--header 'Content-Type: application/json' \
--header 'X-Oy-Username: yourusername' \
--header 'X-Api-Key: yourapikey' \
--data-raw '{
    "partner_user_id": "USR-20230112-001",
    "phone_number": "082114845847",
    "payment_method": "EWALLET",
    "channel_code": "dana_ewallet"
}
'
var headers = {
  'Content-Type': 'application/json',
  'x-oy-username': 'yourusername',
  'x-api-key': 'yourapikey'

};
var request = http.Request('POST', Uri.parse('https://partner.oyindonesia.com/api/account/linking'));
request.body = json.encode({
  "partner_user_id": "USR-20230112-001",
    "phone_number": "082114845847",
    "payment_method": "EWALLET",
    "channel_code": "dana_ewallet"
});
request.headers.addAll(headers);

http.StreamedResponse response = await request.send();

if (response.statusCode == 200) {
  print(await response.stream.bytesToString());
}
package main

import (
  "fmt"
  "strings"
  "net/http"
  "io/ioutil"
)

func main() {

  url := "https://partner.oyindonesia.com/api/account/linking"
  method := "POST"

  payload := strings.NewReader(`{
    "partner_user_id": "USR-20230112-001",
    "phone_number": "082114845847",
    "payment_method": "EWALLET",
    "channel_code": "dana_ewallet"
}`)

  client := &http.Client {
  }
  req, err := http.NewRequest(method, url, payload)

  if err != nil {
    fmt.Println(err)
    return
  }
  req.Header.Add("Content-Type", "application/json")
  req.Header.Add("x-oy-username", "yourusername")
  req.Header.Add("x-api-key", "yourapikey")

  res, err := client.Do(req)
  if err != nil {
    fmt.Println(err)
    return
  }
  defer res.Body.Close()

  body, err := ioutil.ReadAll(res.Body)
  if err != nil {
    fmt.Println(err)
    return
  }
  fmt.Println(string(body))
}
OkHttpClient client = new OkHttpClient().newBuilder()
  .build();
MediaType mediaType = MediaType.parse("application/json");
RequestBody body = RequestBody.create(mediaType, "{\n    \"partner_user_id\": \"USR-20230112-001\",\n    \"phone_number\": \"082114845847\",\n    \"payment_method\": \"EWALLET\",\n    \"channel_code\": \"dana_ewallet\"\n}");
Request request = new Request.Builder()
  .url("https://partner.oyindonesia.com/api/account/linking")
  .method("POST", body)
  .addHeader("Content-Type", "application/json")
  .addHeader("x-oy-username", "yourusername")
  .addHeader("x-api-key", "yourapikey")
  .build();
Response response = client.newCall(request).execute();
var data = JSON.stringify({
  "partner_user_id": "USR-20230112-001",
  "phone_number": "082114845847",
  "payment_method": "EWALLET",
  "channel_code": "dana_ewallet"
});

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function() {
  if(this.readyState === 4) {
    console.log(this.responseText);
  }
});

xhr.open("POST", "https://partner.oyindonesia.com/api/account/linking");
xhr.setRequestHeader("Content-Type", "application/json");
xhr.setRequestHeader("x-oy-username", "yourusername");
xhr.setRequestHeader("x-api-key", "yourapikey");

xhr.send(data);
<?php
require_once 'HTTP/Request2.php';
$request = new HTTP_Request2();
$request->setUrl('https://partner.oyindonesia.com/api/account/linking');
$request->setMethod(HTTP_Request2::METHOD_POST);
$request->setConfig(array(
  'follow_redirects' => TRUE
));
$request->setHeader(array(
  'Content-Type' => 'application/json',
  'x-oy-username' => 'yourusername',
  'x-api-key' => 'yourapikey'
));
$request->setBody('{\n    "partner_user_id": "USR-20230112-001",\n    "phone_number": "082114845847",\n    "payment_method": "EWALLET",\n    "channel_code": "dana_ewallet"\n}');
try {
  $response = $request->send();
  if ($response->getStatus() == 200) {
    echo $response->getBody();
  }
  else {
    echo 'Unexpected HTTP status: ' . $response->getStatus() . ' ' .
    $response->getReasonPhrase();
  }
}
catch(HTTP_Request2_Exception $e) {
  echo 'Error: ' . $e->getMessage();
}
import http.client
import json

conn = http.client.HTTPSConnection("https://partner.oyindonesia.com", undefined)
payload = json.dumps({
  "partner_user_id": "USR-20230112-001",
  "phone_number": "082114845847",
  "payment_method": "EWALLET",
  "channel_code": "dana_ewallet"
})
headers = {
  'Content-Type': 'application/json',
  'x-oy-username': 'yourusername',
  'x-api-key': 'yourapikey'
}
conn.request("POST", "/api/account/linking", payload, headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))

The above command returns JSON structured similar like this:

{
    "success": true,
    "error": null,
    "data": {
        "partner_user_id": "USR-20230112-001",
        "payment_method": "EWALLET",
        "channel_code": "dana_ewallet",
        "linking_url": "https://generated-linking-url"
    },
    "reason": null,
    "status_code": 200
}

HTTPS Request

[Production] POST https://partner.oyindonesia.com/api/account/linking

[Staging] POST https://api-stg.oyindonesia.com/api/account/linking

Request Headers

Parameter Type Description
X-Api-Key String API Key used to connect to this particular endpoint
X-Oy-Username String Your OY! account username

Request Parameters

Parameter Type Required Default Description
partner_user_id String(255) TRUE - ID generated by Partner for a specific user/customer
phone_number String(20) TRUE - The user phone number (format 08xxxxxxxxxx)
payment_method String(255) TRUE - The payment method type that user want to linked to (Currently only support EWALLET. In the future we will have another payment method type, such as CARDS)
channel_code String(255) TRUE - The payment channel type that user want to linked to (Currently support dana_ewallet and shopeepay_ewallet)

Response Parameters

Parameter Type Nullable Description
success Boolean FALSE Will be true if the account linking process is successful and vice versa
error Object TRUE Error detail of the account linking process in Object {code: <error_code>, message: <error_message>}. This value is not null if the value of field success is false
data Object TRUE Account linking data, the detail will be explained in the next section. This value is not null if the value of field success is false
reason String(255) TRUE Will be filled with error reason if the linking status is failed
status_code Integer FALSE Will be 200 if the account linking process is success and will be the same as error code if the linking process is failed

Account Linking Response Data

The field data in response parameters will contain below informations.

Parameter Type Description
partner_user_id String(255) ID generated by Partner for a specific user/customer
payment_method String(255) The payment method type that user want to linked to (Currently only support EWALLET. In the future we will have another payment method type, such as CARDS)
channel_code String(255) The payment channel type that user want to linked to (Currently support dana_ewallet and shopeepay_ewallet)
linking_url String Linking URL to be accessed by user to complete the account linking process

Use this API to get the unlink user account. Currently this feature support unlink user ShopeePay account.

curl --location --request POST 'https://partner.oyindonesia.com/api/account/unlink' \
--header 'Content-Type: application/json' \
--header 'X-Oy-Username: yourusername' \
--header 'X-Api-Key: yourapikey' \
--data-raw '{
    "partner_user_id": "USR-20230112-001",
    "payment_method": "EWALLET",
    "channel_code": "shopeepay_ewallet"
}
'
var headers = {
  'Content-Type': 'application/json',
  'x-oy-username': 'yourusername',
  'x-api-key': 'yourapikey'

};
var request = http.Request('POST', Uri.parse('https://partner.oyindonesia.com/api/account/unlink'));
request.body = json.encode({
  "partner_user_id": "USR-20230112-001",
  "payment_method": "EWALLET",
  "channel_code": "shopeepay_ewallet"
});
request.headers.addAll(headers);

http.StreamedResponse response = await request.send();

if (response.statusCode == 200) {
  print(await response.stream.bytesToString());
}
package main

import (
  "fmt"
  "strings"
  "net/http"
  "io/ioutil"
)

func main() {

  url := "https://partner.oyindonesia.com/api/account/unlink"
  method := "POST"

  payload := strings.NewReader(`{
    "partner_user_id": "USR-20230112-001",
    "payment_method": "EWALLET",
    "channel_code": "shopeepay_ewallet"
}`)

  client := &http.Client {
  }
  req, err := http.NewRequest(method, url, payload)

  if err != nil {
    fmt.Println(err)
    return
  }
  req.Header.Add("Content-Type", "application/json")
  req.Header.Add("x-oy-username", "yourusername")
  req.Header.Add("x-api-key", "yourapikey")

  res, err := client.Do(req)
  if err != nil {
    fmt.Println(err)
    return
  }
  defer res.Body.Close()

  body, err := ioutil.ReadAll(res.Body)
  if err != nil {
    fmt.Println(err)
    return
  }
  fmt.Println(string(body))
}
OkHttpClient client = new OkHttpClient().newBuilder()
  .build();
MediaType mediaType = MediaType.parse("application/json");
RequestBody body = RequestBody.create(mediaType, "{\n    \"partner_user_id\": \"USR-20230112-001\",\n    \"payment_method\": \"EWALLET\",\n    \"channel_code\": \"shopeepay_ewallet\"\n}");
Request request = new Request.Builder()
  .url("https://partner.oyindonesia.com/api/account/unlink")
  .method("POST", body)
  .addHeader("Content-Type", "application/json")
  .addHeader("x-oy-username", "yourusername")
  .addHeader("x-api-key", "yourapikey")
  .build();
Response response = client.newCall(request).execute();
var data = JSON.stringify({
  "partner_user_id": "USR-20230112-001",
  "payment_method": "EWALLET",
  "channel_code": "shopeepay_ewallet"
});

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function() {
  if(this.readyState === 4) {
    console.log(this.responseText);
  }
});

xhr.open("POST", "https://partner.oyindonesia.com/api/account/unlink");
xhr.setRequestHeader("Content-Type", "application/json");
xhr.setRequestHeader("x-oy-username", "yourusername");
xhr.setRequestHeader("x-api-key", "yourapikey");

xhr.send(data);
<?php
require_once 'HTTP/Request2.php';
$request = new HTTP_Request2();
$request->setUrl('https://partner.oyindonesia.com/api/account/unlink');
$request->setMethod(HTTP_Request2::METHOD_POST);
$request->setConfig(array(
  'follow_redirects' => TRUE
));
$request->setHeader(array(
  'Content-Type' => 'application/json',
  'x-oy-username' => 'yourusername',
  'x-api-key' => 'yourapikey'
));
$request->setBody('{\n    "partner_user_id": "USR-20230112-001",\n    "payment_method": "EWALLET",\n    "channel_code": "shopeepay_ewallet"\n}');
try {
  $response = $request->send();
  if ($response->getStatus() == 200) {
    echo $response->getBody();
  }
  else {
    echo 'Unexpected HTTP status: ' . $response->getStatus() . ' ' .
    $response->getReasonPhrase();
  }
}
catch(HTTP_Request2_Exception $e) {
  echo 'Error: ' . $e->getMessage();
}
import http.client
import json

conn = http.client.HTTPSConnection("https://partner.oyindonesia.com", undefined)
payload = json.dumps({
  "partner_user_id": "USR-20230112-001",
  "payment_method": "EWALLET",
  "channel_code": "shopeepay_ewallet"
})
headers = {
  'Content-Type': 'application/json',
  'x-oy-username': 'yourusername',
  'x-api-key': 'yourapikey'
}
conn.request("POST", "/api/account/unlink", payload, headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))

The above command returns JSON structured similar like this:

{
    "success": true,
    "error": null,
    "data": {
        "partner_user_id": "USR-20230112-001",
        "payment_method": "EWALLET",
        "channel_code": "shopeepay_ewallet",
        "status": "UNLINKED"
    },
    "reason": null,
    "status_code": 200
}

[Production] POST https://partner.oyindonesia.com/api/account/unlink

[Staging] POST https://api-stg.oyindonesia.com/api/account/unlink

Parameter Type Description
X-Api-Key String API Key used to connect to this particular endpoint
X-Oy-Username String Your OY! account username
Parameter Type Required Default Description
partner_user_id String(255) TRUE - ID generated by Partner for a specific user/customer
payment_method String(255) TRUE - The payment method type that user want to linked to (Currently only support EWALLET. In the future we will have another payment method type, such as CARDS)
channel_code String(255) TRUE - The payment channel type that user want to linked to (Currently only support shopeepay_ewallet)
Parameter Type Nullable Description
success Boolean FALSE Will be true if the account linking process is successful and vice versa
error Object TRUE Error detail of the account linking process in Object {code: <error_code>, message: <error_message>}. This value is not null if the value of field success is false
data Object TRUE Account linking data, the detail will be explained in the next section. This value is not null if the value of field success is false
reason String(255) TRUE Will be filled with error reason if the linking status is failed
status_code Integer FALSE Will be 200 if the account linking process is success and will be the same as error code if the linking process is failed

The field data in response parameters will contain below informations.

Parameter Type Description
partner_user_id String(255) ID generated by Partner for a specific user/customer
payment_method String(255) The payment method type that user want to linked to (Currently only support EWALLET. In the future we will have another payment method type, such as CARDS)
channel_code String(255) The payment channel type that user want to linked to (currently only support shopeepay_ewallet)
status String Account linking status, should be UNLINKED if successful. Other status if otherwise.

How we notify account linking/unlinking result?

Send Callback Condition

Payment Method Channel Code Successful Account Linking Failed Account Linking
EWALLET dana_ewallet Send Callback -
EWALLET shopeepay_ewallet Send Callback -

The response callback will looks like this:

{
    "username": "username",
    "partner_user_id": "789467agf238893894rfcw7978iu7g7e",
    "payment_method": "EWALLET",
    "channel_code": "dana_ewallet",
    "phone_number": "082114845847",
    "status": "LINKED",
    "expiration_time": "01/02/2020T15:00:00.000+0000"
}

Callback Parameters

Parameter Type Nullable Description
username String FALSE Partner username
partner_user_id String FALSE ID generated by Partner for a specific user/customer
payment_method String FALSE The payment method type that user want to linked to (Currently only support EWALLET. In the future we will have another payment method type, such as CARDS)
channel_code String FALSE The payment channel type that user want to linked to (Currently support dana_ewallet and shopeepay_ewallet)
phone_number String FALSE The user phone number (format 08xxxxxxxxxx)
status String FALSE User's account linking status
expiration_time String FALSE User's account linking expiration time (example: 01/02/2020T15:00:00.000+0000)
Redirect URL Result Status Partner User ID Redirect URL Embedded with Result Status
https://url.com/redirect SUCCESS 789467agf238893894rfcw7978iu7g7e https://url.com/redirect?result=SUCCESS&partnerUserId=789467agf238893894rfcw7978iu7g7e&channelCode=dana_ewallet&paymentMethod=EWALLET
https://url.com/redirect FAILED 789467agf238893894rfcw7978iu7g7e https://url.com/redirect?result=FAILED&partnerUserId=789467agf238893894rfcw7978iu7g7e&channelCode=dana_ewallet&paymentMethod=EWALLET

Get E-Wallet Account Balance

After do account linking, user have the capability to see their e-wallet balance. Use this API to get user e-wallet balance.

curl --location --request POST 'https://partner.oyindonesia.com/api/account/balance' \
--header 'Content-Type: application/json' \
--header 'X-Oy-Username: yourusername' \
--header 'X-Api-Key: yourapikey' \
--data-raw '{
    "partner_user_id": "USR-20230112-001",
    "channel_code": "dana_ewallet"
}
'
var headers = {
  'Content-Type': 'application/json',
  'x-oy-username': 'yourusername',
  'x-api-key': 'yourapikey'

};
var request = http.Request('POST', Uri.parse('https://partner.oyindonesia.com/api/account/balance'));
request.body = json.encode({
  "partner_user_id": "USR-20230112-001",
    "channel_code": "dana_ewallet"
});
request.headers.addAll(headers);

http.StreamedResponse response = await request.send();

if (response.statusCode == 200) {
  print(await response.stream.bytesToString());
}
package main

import (
  "fmt"
  "strings"
  "net/http"
  "io/ioutil"
)

func main() {

  url := "https://partner.oyindonesia.com/api/account/balance"
  method := "POST"

  payload := strings.NewReader(`{
    "partner_user_id": "USR-20230112-001",
    "channel_code": "dana_ewallet"
}`)

  client := &http.Client {
  }
  req, err := http.NewRequest(method, url, payload)

  if err != nil {
    fmt.Println(err)
    return
  }
  req.Header.Add("Content-Type", "application/json")
  req.Header.Add("x-oy-username", "yourusername")
  req.Header.Add("x-api-key", "yourapikey")

  res, err := client.Do(req)
  if err != nil {
    fmt.Println(err)
    return
  }
  defer res.Body.Close()

  body, err := ioutil.ReadAll(res.Body)
  if err != nil {
    fmt.Println(err)
    return
  }
  fmt.Println(string(body))
}
OkHttpClient client = new OkHttpClient().newBuilder()
  .build();
MediaType mediaType = MediaType.parse("application/json");
RequestBody body = RequestBody.create(mediaType, "{\n    \"partner_user_id\": \"USR-20230112-001\",\n    \"channel_code\": \"dana_ewallet\"\n}");
Request request = new Request.Builder()
  .url("https://partner.oyindonesia.com/api/account/balance")
  .method("POST", body)
  .addHeader("Content-Type", "application/json")
  .addHeader("x-oy-username", "yourusername")
  .addHeader("x-api-key", "yourapikey")
  .build();
Response response = client.newCall(request).execute();
var data = JSON.stringify({
  "partner_user_id": "USR-20230112-001",
  "channel_code": "dana_ewallet"
});

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function() {
  if(this.readyState === 4) {
    console.log(this.responseText);
  }
});

xhr.open("POST", "https://partner.oyindonesia.com/api/account/balance");
xhr.setRequestHeader("Content-Type", "application/json");
xhr.setRequestHeader("x-oy-username", "yourusername");
xhr.setRequestHeader("x-api-key", "yourapikey");

xhr.send(data);
<?php
require_once 'HTTP/Request2.php';
$request = new HTTP_Request2();
$request->setUrl('https://partner.oyindonesia.com/api/account/balance');
$request->setMethod(HTTP_Request2::METHOD_POST);
$request->setConfig(array(
  'follow_redirects' => TRUE
));
$request->setHeader(array(
  'Content-Type' => 'application/json',
  'x-oy-username' => 'yourusername',
  'x-api-key' => 'yourapikey'
));
$request->setBody('{\n    "partner_user_id": "USR-20230112-001",\n    "channel_code": "dana_ewallet"\n}');
try {
  $response = $request->send();
  if ($response->getStatus() == 200) {
    echo $response->getBody();
  }
  else {
    echo 'Unexpected HTTP status: ' . $response->getStatus() . ' ' .
    $response->getReasonPhrase();
  }
}
catch(HTTP_Request2_Exception $e) {
  echo 'Error: ' . $e->getMessage();
}
import http.client
import json

conn = http.client.HTTPSConnection("https://partner.oyindonesia.com", undefined)
payload = json.dumps({
  "partner_user_id": "USR-20230112-001",
  "channel_code": "dana_ewallet"
})
headers = {
  'Content-Type': 'application/json',
  'x-oy-username': 'yourusername',
  'x-api-key': 'yourapikey'
}
conn.request("POST", "/api/account/balance", payload, headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))

The above command returns JSON structured similar like this:

{
    "status": {
        "code": "000",
        "message": "Success"
    },
    "partner_user_id": "USR-20230112-001",
    "channel_code": "dana_ewallet",
    "amount": 150000
}

HTTPS Request

[Production] POST https://partner.oyindonesia.com/api/account/balance

[Staging] POST https://api-stg.oyindonesia.com/api/account/balance

Request Headers

Parameter Type Description
X-Api-Key String API Key used to connect to this particular endpoint
X-Oy-Username String Your OY! account username

Request Parameters

Parameter Type Required Default Description
partner_user_id String(255) TRUE - ID generated by Partner for a specific user/customer
channel_code String(255) TRUE - The payment channel type (Currently support dana_ewallet and shopeepay_ewallet)

Response Parameters

Parameter Type Nullable Description
status Object FALSE Status of response in Object {code: <status_code>, message: <status_message>}.
partner_user_id String(255) FALSE ID generated by Partner for a specific user/customer
channel_code String(255) FALSE The payment channel type (Currently support dana_ewallet and shopeepay_ewallet)
amount BigDecimal TRUE User e-wallet balance amount. This value is not null if the value of field success is false

Response Codes

Below is the list of response codes for API Account Linking:

Response Code State Description
000 Final Response success without error.
201 Final Request is rejected with message “User not found”.
202 Final Request is rejected with message “User not active”.
207 Final Request is rejected with message “Request IP Address is not Registered”.
208 Final Request is rejected with message “API Key is not valid”.
290 Final Request is Rejected (Parameter / object is not valid)
400 Final Request is rejected with message “Unsupported e-wallet type for tokenization”. Currently, OY support account linking for DANA and ShopeePay e-wallet.
400 Final Account linking request is rejected with message “Phone number is linked”.
400 Final Get user balance request is rejected with message “User account is not linked”.
999 Non-Final Internal Server Error.

Transaction Detail

Transaction detail API allows you to get the detail of a transaction

Get Transaction Detail

The Transaction Detail Query API allows partners to retrieve transaction details using the partner transaction ID. Before making a query using this API, it is recommended to ensure that the transaction has been marked as successful through the Check Status API.

curl --location --request GET 'https://partner.oyindonesia.com/api/v1/transaction?partner_tx_id=<partner_tx_id>&product_type=<product_type>' \
--header 'content-type: application/json' \
--header 'accept: application/json' \
--header 'x-oy-username: yourusername' \
--header 'x-api-key: apikeymu'
var headers = {
  'content-type': 'application/json',
  'accept: application/json',
  'x-oy-username': 'yourusername',
  'x-api-key': 'apikeymu'

};
var request = http.Request('GET', Uri.parse('https://partner.oyindonesia.com/api/v1/transaction?partner_tx_id=<partner_tx_id>&product_type=<product_type>'));
request.headers.addAll(headers);

http.StreamedResponse response = await request.send();

if (response.statusCode == 200) {
  print(await response.stream.bytesToString());
}
package main

import (
  "fmt"
  "strings"
  "net/http"
  "io/ioutil"
)

func main() {

  url := "https://partner.oyindonesia.com/api/v1/transaction?partner_tx_id=<partner_tx_id>&product_type=<product_type>"
  method := "GET"

  client := &http.Client {
  }
  req, err := http.NewRequest(method, url, nil)

  if err != nil {
    fmt.Println(err)
    return
  }
  req.Header.Add("Content-Type", "application/json")
  req.Header.Add("x-oy-username", "yourusername")
  req.Header.Add("x-api-key", "apikeymu")

  res, err := client.Do(req)
  if err != nil {
    fmt.Println(err)
    return
  }
  defer res.Body.Close()

  body, err := ioutil.ReadAll(res.Body)
  if err != nil {
    fmt.Println(err)
    return
  }
  fmt.Println(string(body))
}
OkHttpClient client = new OkHttpClient().newBuilder()
  .build();
Request request = new Request.Builder()
  .url("https://partner.oyindonesia.com/api/v1/transaction?partner_tx_id=<partner_tx_id>&product_type=<product_type>")
  .method("GET", null)
  .addHeader("Content-Type", "application/json")
  .addHeader("x-oy-username", "yourusername")
  .addHeader("x-api-key", "apikeymu")
  .build();
Response response = client.newCall(request).execute();
var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function() {
  if(this.readyState === 4) {
    console.log(this.responseText);
  }
});

xhr.open("GET", "https://partner.oyindonesia.com/api/v1/transaction?partner_tx_id=<partner_tx_id>&product_type=<product_type>");
xhr.setRequestHeader("Content-Type", "application/json");
xhr.setRequestHeader("x-oy-username", "yourusername");
xhr.setRequestHeader("x-api-key", "apikeymu");

xhr.send();
<?php
require_once 'HTTP/Request2.php';
$request = new HTTP_Request2();
$request->setUrl('https://partner.oyindonesia.com/api/v1/transaction?partner_tx_id=<partner_tx_id>&producet_type=<product_type>');
$request->setMethod(HTTP_Request2::METHOD_GET);
$request->setConfig(array(
  'follow_redirects' => TRUE
));
$request->setHeader(array(
  'Content-Type' => 'application/json',
  'x-oy-username' => 'yourusername',
  'x-api-key' => 'apikeymu'
));
try {
  $response = $request->send();
  if ($response->getStatus() == 200) {
    echo $response->getBody();
  }
  else {
    echo 'Unexpected HTTP status: ' . $response->getStatus() . ' ' .
    $response->getReasonPhrase();
  }
}
catch(HTTP_Request2_Exception $e) {
  echo 'Error: ' . $e->getMessage();
}
import http.client
import json

conn = http.client.HTTPSConnection("https://partner.oyindonesia.com", undefined)
payload = ''
headers = {
  'Content-Type': 'application/json',
  'x-oy-username': 'yourusername',
  'x-api-key': 'apikeymu'
}
conn.request("GET", "/api/v1/transaction?partner_tx_id=<partner_tx_id>&product_type=<product_type>", payload, headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))

The above command returns JSON structured similar like this:

{
  "status": {
    "code": "000",
    "message": "Success",
  },
  "data": {
    "transfer_amount": 10000, 
    "settlement_amount": 10150,
    "admin_fee": {
      "total_fee": 150
    },
  }
}

HTTPS Request

Endpoint:
[Production] GET https://partner.oyindonesia.com/api/v1/transaction?partner_tx_id=<partner_tx_id>&product_type=<product_type>
[Staging] GET https://api-stg.oyindonesia.com/api/v1/transaction?partner_tx_id=<partner_tx_id>&product_type=<product_type>

Header

Field Description Example
x-oy-username Partner username username
x-api-key Partner api key 6e87432c-2726-11ec-9621-0242ac130002

Request Parameters

Parameter Type Required Description
partner_tx_id String(255) TRUE The partner transaction ID of the transaction to be queried
product_type Enum TRUE The product type of the transaction to be queried. Valid options are: API_DISBURSE, API_BILLER, EWALLET_AGGREGATOR, VA_AGGREGATOR, PAYMENT_ROUTING, PAYMENT_LINK

Response Parameters

Parameter Type Description
status Object Status of the request in an object. {code: \<status_code\>, message: \<status_message\>
data Object Data object that wraps the response parameters. Nullable if status is not success
data.transfer_amount BigDecimal The amount that must be paid or received by the end user.
data.settlement_amount BigDecimal The total amount that is reflected in the partner's balance. The calculation of the settlement amount varies depending on the transaction type:
- For disbursement transactions: (settlement_amount = transfer_amount + admin_fee)
- For acceptance transactions: (settlement_amount = transfer_amount - admin_fee)
data.admin_fee Object Admin fee detail of the transaction
data.admin_fee.total_fee BigDecimal Total amount of the admin fee for this transaction.

Product Type

For money-in product, this API can only be used for single-use transactions. For more detailed about each product type, please refer to the following table:

Product Type Product Docs Notes
API_DISBURSE Api Disburse
API_BILLER Api Biller
PAYMENT_LINK Payment Link Excludes the use of reusable payment links.
PAYMENT_ROUTING Payment Routing Excludes disbursement through payment routing.
VA_AGGREGATOR VA Aggregator Excludes the use of VA (Virtual Account) for multiple uses.
EWALLET_AGGREGATOR Ewallet Aggregator

Timeout

Timeouts can be set by partners when making requests to our API. This allows partners to control the maximum duration for which they are willing to wait for a response from our server.

Timeout Durations for OY's API

Below is the list of timeout durations for OY's API, which partners can set when using our services:

API Timeout in seconds
VA Aggregator 60
Fund Acceptance (Payment Link) 120
E-Wallet Aggregator 60
Payment Routing 120
Account Linking 100

Setting Timeout

Partners can set the timeout by including the timeout parameter in the request headers. The value of the timeout parameter should be specified in seconds.

Example

POST https://partner.oyindonesia.com/api/e-wallet-aggregator/create-transaction
Host: partner.oyindonesia.com
Content-Type: application/json
X-Oy-Username: yourusername
X-Api-Key: yourapikey
Timeout: 60

In this example, the partner is setting a timeout of 60 seconds for the request to POST /api/e-wallet-aggregator/create-transaction. Please note that OY's server will respond within this specified timeout duration.

Docs Changelog

December 1, 2022

Select Language