This guide explains the technical specifications of JSAPIs that is available to be called from your application's frontend.
Integrate SDK
-
Include the gpContainer SDK in Your Codebase
To use the SDK, add the following<script src="https://gwk.gopayapi.com/sdk/stable/gp-container.min.js"></script> -
Invoking SDK Methods
To call any JSAPI from the SDK, use the following format:window.gpContainer.call(className, methodName, params, successCallback, failureCallback, timeout); -
Handling Response
Currently, the GoPay app uses string responses for versions below 2.00, and JSON responses for versions 2.00 and above.
If you are using any of the handlers listed below, please update your implementation to handle both response formats. This will ensure backward compatibility and prevent errors for users on different app versions.
We will notify you once there is sufficient adoption of the JSON response, at which point string responses will be deprecated.// `response.data` may be either a JSON string or a parsed object const rawData = response.data; let data = {}; try { data = typeof rawData === 'string' ? JSON.parse(rawData) : rawData || {}; } catch (e) { console.error('Invalid response data:', rawData); }
Supported JSAPIs
GPLocation (need to change all openlinks)
| API | Function | Requires Consent |
|---|---|---|
| GPLocation.getLocation | Obtain user's device longitude and latitude location | Yes |
GPMiniAppAuth
| API | Function | Requires Consent |
|---|---|---|
| GPMiniAppAuth.getAuthCode | Get an auth code used to identify the current user session | No |
GPNavigator
| API | Function | Requires Consent |
|---|---|---|
| GPNavigator.launchDeeplink | Open a third-party app or page using a custom deeplink | No |
| GPNavigator.launchUri | Open a browser or in-app page using a universal or web URI | No |
GP
| API | Function | Requires Consent |
|---|---|---|
| GP.launchPayment | Automatically redirect users to the GoPay app to complete the payment, then return them to your Mini App. | No |
| GP.getBankAccountToken | Request and tokenize the user’s linked bank account information | Yes |
GPSystem
| API | Function | Requires Consent |
|---|---|---|
| GPSystem.getSystemInfo | Get device's system info such as OS, model, and app version | Yes |
| GPSystem.getRootedDeviceInfo | Get device's rooted info | Yes |
| GPSystem.getWifiInfo | Get the device’s connected Wi-Fi details, such as SSID or signal strength | Yes |
GPConsent
| API | Function | Requires Consent |
|---|---|---|
| GPConsent.getUserConsent | Ask user to retrieve user consent for accessing sensitive including PII and device permission data | Yes |
GPMotion
| API | Function | Requires Consent |
|---|---|---|
| GPMotion.startAccelerometer | Start monitoring acceleration of the device in 3D space | No |
| GPMotion.stopAccelerometer | Stop monitoring acceleration | No |
| GPMotion.startCompass | Start receiving compass direction data (magnetic heading) | No |
| GPMotion.stopCompass | Stop receiving compass data | No |
| GPMotion.listenGyro | Start receiving gyroscope data (rotation rate around device axes) | No |
| GPMotion.listeningShake | Listen for shake gesture events | No |
| GPMotion.vibrate | Trigger vibration on the device | No |
GPFile
| API | Function | Requires Consent |
|---|---|---|
| GPFile.save | To save image and PDF in iOS (Android is not supported yet) | No |
GPShare
| API | Function | Requires Consent |
|---|---|---|
| GPShare.share | To share text format to the social media | No |
GPBase
| API | Function | Requires Consent |
|---|---|---|
| GPBase.getLocale | To get the app locale, supported ID and EN | No |
| GPBase.copyToClipboard | To copy content to clipboard | No |
GP
| API | Function | Requires Consent |
|---|---|---|
| GP.trackBinaryEvent | Track Clickstream events | No |
Version History
| Version | Description | Date |
|---|---|---|
| 0.4.0 | Initial Release for V1 (Deprecated) | 10/07/25 |
| 1.0.0 | Initial Release for V4 Webkit | 18/08/25 |
JSAPIs Specification (v1.0.0)
Note
- Data will be null in case of success = false, and vice versa.
- Error will be null in case of success = true, and vice versa.
Get Location
Sample Request:
var params = {
// Specify whether to obtain a high-precision location.
enable_high_accuracy: true
};
window.gpContainer.call(
"GPLocation",
"getLocation",
params,
function(response) {
console.log('success:', response);
},
function(error) {
console.log('error:', error);
}
);Sample Response: (error codes)
{
"success": true,
"data": {
"coords": {
"longitude": 77.5946,
"latitude": 12.9716,
"time": 12
}
},
"ret": "GP_SUCCESS"
}{
"success": false,
"error_code": "",
"error_type": "JS_BRIDGE_ERROR",
"error_message": "",
"ret": "GP_EXCEPTION"
}Get Auth Code
Sample Request:
window.gpContainer.call(
"GPMiniAppAuth",
"getAuthCode",
{},
function(response) {
console.log('success:', response);
},
function(error) {
console.log('error:', error);
}
);Sample Response: (error codes)
{
"success": true,
"data": {
authCode: "GBNURP5WyBIqXiGxKv2cO8Qj4CyS0qZrRK5O4e8ehdnHpowG6k5pkj2SsF7BqGIF"
},
"ret": "GP_SUCCESS"
}{
"success": false,
"error_code": "",
"error_type": "JS_BRIDGE_ERROR",
"error_message": "",
"ret": "GP_EXCEPTION"
}Launch Deeplink
Sample Request:
var params = {
deeplink: "string"
};
window.gpContainer.call(
"GPNavigator",
"launchDeeplink",
params,
function(response) {
console.log('success:', response);
},
function(error) {
console.log('error:', error);
}
);Sample Response: (error codes)
{
success: true,
"ret": "GP_SUCCESS"
}{
"success": false,
"error_code": "300",
"error_type": "JS_BRIDGE_ERROR",
"error_message": "Permission denied",
"ret": "GP_EXCEPTION"
}Launch Payment
Sample Request:
const webUrl = response.webRedirectUrl;
function convertToGoPayDeepLink(url) {
const urlObj = new URL(url);
const params = urlObj.search;
return `gopay://merchanttransfer${params}`;
}
const deepLink = convertToGoPayDeepLink(webUrl);
// Assign to params object
var params = {
deeplink: deepLink
};
window.gpContainer.call(
"GP",
"launchPayment",
params,
function(response) {
console.log('success:', response);
},
function(error) {
console.log('error:', error);
}
);Sample Response: (error codes)
{
success: true,
data: {
status: "success"
},
"ret": "GP_SUCCESS"
}{
"success": false,
"error_code": "300",
"error_type": "JS_BRIDGE_ERROR",
"error_message": "Permission denied",
"ret": "GP_EXCEPTION"
}| Status | Description |
|---|---|
| success | User have successfully paid the transaction |
| failed | User cancelled the transaction |
| pending | There's an error processing the transaction |
| cancelled | User goes back to the miniapp without completing or cancelling the payment |
Launch Uri
Sample Request:
var params = {
uri: "string"
};
window.gpContainer.call(
"GPNavigator",
"launchUri",
params,
function(response) {
console.log('success:', response);
},
function(error) {
console.log('error:', error);
}
);Sample Response: (error codes)
{
"success": true,
"ret": "GP_SUCCESS"
}{
"success": false,
"error_code": "",
"error_type": "JS_BRIDGE_ERROR",
"error_message": "",
"ret": "GP_EXCEPTION"
}Get System Info
Sample Request:
window.gpContainer.call(
"GPSystem",
"getSystemInfo",
{},
function(response) {
console.log('success:', response);
},
function(error) {
console.log('error:', error);
}
);Sample Response: (error codes)
{
success: boolean,
data?: {
platform: string,
is_emulator: boolean,
brand: string,
model: string,
product: string,
uuid: string,
idfa: string,
idfv: string
},
"ret": "GP_SUCCESS"
}{
"success": false,
"error_code": "",
"error_type": "JS_BRIDGE_ERROR",
"error_message": "",
"ret": "GP_EXCEPTION"
}Get Rooted Device Info
Sample Request:
window.gpContainer.call(
"GPSystem",
"getRootedDeviceInfo",
{},
function(response) {
console.log('success:', response);
},
function(error) {
console.log('error:', error);
}
);Sample Response: (error codes)
{
success: boolean,
data?: {
is_rooted: string
},
"ret": "GP_SUCCESS"
}{
"success": false,
"error_code": "",
"error_type": "JS_BRIDGE_ERROR",
"error_message": "",
"ret": "GP_EXCEPTION"
}Get Wifi Info
Sample Request:
window.gpContainer.call(
"GPSystem",
"getWifiInfo",
{},
function(response) {
console.log('success:', response);
},
function(error) {
console.log('error:', error);
}
);Sample Response: (error codes)
{
success: boolean,
data?: {
wifi_bssid: string,
wifi_ssid: string,
},
"ret": "GP_SUCCESS"
}{
"success": false,
"error_code": "",
"error_type": "JS_BRIDGE_ERROR",
"error_message": "",
"ret": "GP_EXCEPTION"
}Get User Consent
Please use the latest version of the Get User Consent, the previous version is planned to be deprecated in Q1 2026.
Webkit (latest version)
Sample Request:
var params = {
scope: 'location'
/**
scope is consent_name provided below, you must have the right permissions and consent configured to show this
*/
};
window.gpContainer.call(
"GP",
"authorize",
params,
function(response) {
if (response.successScope['location']) {
alert('success authorize location');
//call the jsapi you need to use
}
console.log('success:', response);
},
function(error) {
console.log('error:', error);
}
);| JSAPI | consent_name |
|---|---|
| getLocation(GoPay) | location |
| getCamera(Javascript) | camera |
| getProfile(GoPay) | You can get this from the error response from getProfile |
Sample Response: (error codes)
{
data: {
successScope: {"location": true}
},
success: boolean,
"ret": "GP_SUCCESS"
}{
"success": false,
"error_code": "",
"error_type": "JS_BRIDGE_ERROR",
"error_message": "",
"ret": "GP_EXCEPTION"
}Webview
Sample Request:
var params = {
consent_name: 'string'
};
window.gpContainer.call(
"GPConsent",
"getUserConsent",
params,
function(response) {
console.log('success:', response);
},
function(error) {
console.log('error:', error);
}
);Sample Response: (error codes)
{
data: {
consent_name: string,
has_consent: boolean,
},
success: boolean,
"ret": "GP_SUCCESS"
}{
"success": false,
"error_code": "",
"error_type": "JS_BRIDGE_ERROR",
"error_message": "",
"ret": "GP_EXCEPTION"
}Possible Error Codes:
| Error Code | Description |
|---|---|
| 100 | Method not supported error |
| 105 | User not found |
| 200 | Incomplete parameter error |
| 201 | Invalid type error |
| 202 | Parameter data error |
| 203 | Miniapp not registered |
| 300 | No permission error |
| 303 | Malformed Authorization |
| 400 | Device not supported |
| 401 | Network error |
| 500 | Superapp error |
| 900 | Unable to process |
Get Bank Account Token
Sample Request:
window.gpContainer.call(
"GP",
"getBankAccountToken",
{},
function(response) {
console.log('success:', response);
},
function(error) {
console.log('error:', error);
}
);Sample Response: (error codes)
{
success: boolean,
data?: {
token: string
},
"ret": "GP_SUCCESS"
}{
"success": false,
"error_code": "",
"error_type": "JS_BRIDGE_ERROR",
"error_message": "",
"ret": "GP_EXCEPTION"
}Start Accelerometer
Sample Request:
var params = {
/**
interval is either "game", "ui", or "normal". "normal" is default
"game" : 20ms
"ui": 60ms
"normal": 200ms
*/
interval: 'normal'
};
window.gpContainer.call(
"GPMotion",
"startAccelerometer",
params,
function(response) {
console.log('success:', response);
},
function(error) {
console.log('error:', error);
}
);
// Listen to Compass result
document.addEventListener('GPMotion.Event.accelerometer', (e: GPMotionAccelerometerData) => {
console.log('Received gpAsyncCallback event:', JSON.stringify(e));
});Sample Response: (error codes)
{
"success": true,
"ret": "GP_SUCCESS",
"msg": "ACCELEROMETER_STARTED"
}{
x: double,
y: double,
z: double
}{
"success": false,
"error_code": "",
"error_type": "JS_BRIDGE_ERROR",
"error_message": "",
"ret": "GP_EXCEPTION"
}Stop Accelerometer
Sample Request:
window.gpContainer.call(
"GPMotion",
"stopAccelerometer",
{},
function(response) {
console.log('success:', response);
},
function(error) {
console.log('error:', error);
}
);Sample Response: (error codes)
{
"success": true,
"ret": "GP_SUCCESS",
"msg": "ACCELEROMETER_STOPPED"
}{
"success": false,
"error_code": "",
"error_type": "JS_BRIDGE_ERROR",
"error_message": "",
"ret": "GP_EXCEPTION"
}Start Compass
Sample Request:
var params = {
/**
interval is either "game", "ui", or "normal". "normal" is default
"game" : 20ms
"ui": 60ms
"normal": 200ms
*/
interval: 'normal'
};
window.gpContainer.call(
"GPMotion",
"startCompass",
params,
function(response) {
console.log('success:', response);
},
function(error) {
console.log('error:', error);
}
);
// Listen to Compass result
document.addEventListener('GPMotion.Event.compass', (e: GPMotionCompassData) => {
console.log('Received gpAsyncCallback event:', JSON.stringify(e));
});Sample Response: (error codes)
{
"success": true,
"ret": "GP_SUCCESS",
"msg": "COMPASS_STARTED"
}{
direction: double, // The value due north between [0,360)
timestamp: int64
}{
"success": false,
"error_code": "",
"error_type": "JS_BRIDGE_ERROR",
"error_message": "",
"ret": "GP_EXCEPTION"
}Stop Compass
Sample Request:
window.gpContainer.call(
"GPMotion",
"stopCompass",
{},
function(response) {
console.log('success:', response);
},
function(error) {
console.log('error:', error);
}
);Sample Response: (error codes)
{
"success": true,
"ret": "GP_SUCCESS",
"msg": "COMPASS_STOPPED"
}{
"success": false,
"error_code": "",
"error_type": "JS_BRIDGE_ERROR",
"error_message": "",
"ret": "GP_EXCEPTION"
}Listen Gyro
Sample Request:
var params = {
/**
on - Enable or disable monitoring of the gyroscope. (response would be GYROSCOPE_STARTED or GYROSCOPE_STOPPED)
frequency - The interval between gyroscope events.
*/
on: true,
frequency: 100
};
window.gpContainer.call(
"GPMotion",
"listenGyro",
{},
function(response) {
console.log('success:', response);
},
function(error) {
console.log('error:', error);
}
);
// Listen to gyroscope
document.addEventListener('motion.gyro', (e: GPMotionGyroscopeData) => {
console.log('Received gpAsyncCallback event:', JSON.stringify(e));
});Sample Response: (error codes)
{
"success": true,
"ret": "GP_SUCCESS",
"msg": "GYROSCPOPE_STARTED"
}{
x: double,
y: double,
z: double
}{
"success": false,
"error_code": "",
"error_type": "JS_BRIDGE_ERROR",
"error_message": "",
"ret": "GP_EXCEPTION"
}Listening Shake
Sample Request:
var params = {
// on: specifies whether to enable monitoring of the shake gesture. (response would be SHAKE_STARTED or SHAKE_STOPPED)
//frequency: optional. The minimum interval between shake events.
//shakeThreshold: optional. The acceleration threshold used to identify shake gestures.
//shakeNum: optional. The number of shake gestures used to generate a shake event.
bool on = 1;
number frequency = 2;
number shakeThreshold = 3;
number shakeNum = 4
};
window.gpContainer.call(
"GPMotion",
"listeningShake",
params,
function(response) {
console.log('success:', response);
},
function(error) {
console.log('error:', error);
}
);
// Listen to Shake
document.addEventListener('motion.shake', (e: GPMotionShakeData) => {
console.log('Received gpAsyncCallback event:', JSON.stringify(e));
});Sample Response: (error codes)
{
"success": true,
"ret": "GP_SUCCESS",
"msg": "SHAKE_STARTED"
}{
x: double,
y: double,
z: double
}{
"success": false,
"error_code": "",
"error_type": "JS_BRIDGE_ERROR",
"error_message": "",
"ret": "GP_EXCEPTION"
}Vibrate
Sample Request:
var params = {
// The vibration duration.
duration: 7000
};
window.gpContainer.call(
"GPMotion",
"vibrate",
params,
function(response) {
console.log('success:', response);
},
function(error) {
console.log('error:', error);
}
);Sample Response: (error codes)
{
"success": true,
"ret": "GP_SUCCESS"
}{
"success": false,
"error_code": "",
"error_type": "JS_BRIDGE_ERROR",
"error_message": "",
"ret": "GP_EXCEPTION"
}Save
Sample Request:
var params = {
/**
url: the download URL of the file
name: the name of the file after the file is downloaded.The default name is
timestamp_gpwebkit. This param is optional
destination: destination can either be
"DOWNLOADS", (IOS & Android)
"DOCUMENTS", (Android)
"PICTURES", (IOS & Android)
"DCIM" (Android)
Based on that file will be saved either to local storage or gallery
*/
string url = "imageUrl";
string name = "Images";
string destination = "PICTURES";
};
window.gpContainer.call(
"GPFile",
"save",
params,
function(response) {
console.log('success:', response);
},
function(error) {
console.log('error:', error);
}
);
// Listen to Save success
document.addEventListener('GPFile.Event.saveSuccess', (e) => {
console.log('Received gpAsyncCallback event:', e.detail);
showResult("downloadAsyncResult", e.detail);
});
// Listen to Save failed
document.addEventListener('GPFile.Event.saveFailed', (e) => {
console.log('Received gpAsyncCallback event:', e.detail);
showResult("downloadAsyncResult", e.detail);
});Sample Response: (error codes)
{
"success": true,
"msg": "SAVE_STARTED",
"ret": "GP_SUCCESS"
}{
"msg": "SAVE_SUCCESS"
}{
"msg": "SAVE_FAILED"
}Share
Sample Request:
var params = {
text: "string",
};
window.gpContainer.call(
"GPShare",
"share",
params,
function(response) {
console.log('success:', response);
},
function(error) {
console.log('error:', error);
}
);Sample Response: (error codes)
{
"success": true,
"ret": "GP_SUCCESS"
}{
"success": false,
"error_code": "",
"error_type": "JS_BRIDGE_ERROR",
"error_message": "",
"ret": "GP_EXCEPTION"
}GetLocale
Sample Request:
window.gpContainer.call(
"GPBase",
"getLocale",
{},
function(response) {
console.log('success:', response);
},
function(error) {
console.log('error:', error);
}
);Sample Response: (error codes)
{
"success": true,
"ret": "GP_SUCCESS",
"app_locale": "en_ID" // You will receive the value in en_ID or id_ID , en_ID for English and id_ID for Indonesia
}{
"success": false,
"error_code": "",
"error_type": "JS_BRIDGE_ERROR",
"error_message": "",
"ret": "GP_EXCEPTION"
}CopyToClipboard
Sample Request:
var params = {
text: "string"
};
window.gpContainer.call(
"GPBase",
"copyToClipboard",
params,
function(response) {
console.log('success:', response);
},
function(error) {
console.log('error:', error);
}
);Sample Response: (error codes)
{
"success": true,
"ret": "GP_SUCCESS"
}{
"success": false,
"error_code": "",
"error_type": "JS_BRIDGE_ERROR",
"error_message": "",
"ret": "GP_EXCEPTION"
}Track Binary Event
Sample Request:
// TrackBinaryEvent request
var params = {
event_name = 1;
type = 2;
encoded_data = 3;
};
window.gpContainer.call(
"GP",
"",
params,
function(response) {
console.log('success:', response);
},
function(error) {
console.log('error:', error);
}
);Sample Response: (error codes)
{
"success": true,
"ret": "GP_SUCCESS"
}{
"success": false,
"error_code": "",
"error_type": "JS_BRIDGE_ERROR",
"error_message": "",
"ret": "GP_EXCEPTION"
}Error Codes
Category:
| Category | Code | Description |
|---|---|---|
| Platform Error | 1xx | Platform-related errors, such as opening GoPay deeplink while you're testing on the web |
| Miniapp Error | 2xx | Such as method invocation error calling openDeeplink with a wrong deeplink format |
| Permission Error | 3xx | Permission-related error, such as getting user location but the user does not give the permission |
| Device related Error | 4xx | Returned on device-related error such as network error |
| Superapp Error | 5xx | Error from the superapp side (imagine this as server error) |
Error Code List:
| Codes | Description | Happens When |
|---|---|---|
| 100 | Method not supported error | The miniapp is calling a method that's not supported on the platform. |
| 200 | Incomplete parameter error | The method call have incomplete parameters |
| 201 | Invalid type error | The method call have invalid parameters. E.g. providing int while the required type is string |
| 202 | Parameter data error | The parameters being called is not supported by gopay. E.g. calling open deeplink with non-gopay deeplink |
| 203 | Miniapp not registered | The miniapp you're developing is not registered inside gopay system |
| 300 | No permission error | Miniapp does not have access to the method being called |
| 400 | Device not supported | The resource being requested is not supported by the device |
| 401 | Network Error | Internet related problem such as slow or disconnected internet |
| 500 | Superapp error | Superapp related error. Happens if there's an internal error in gopay while a resource is requested |