SNAP Customer Top Up v1.14
Overview of OpenAPI for Customer Topup Use Case
Host :
https://app.byte-stack.net
https://apigw.ovo.id
Method | Endpoint | Usage |
---|---|---|
POST | HOST/OVOSNAP/v1.0/access-token/b2b |
Generate System Token (B2B) |
POST | HOST/OVOSNAP/v2.0/emoney/account-inquiry |
Customer Topup Inquiry |
POST | HOST/OVOSNAP/v2.0/emoney/topup |
Customer Topup |
POST | HOST/OVOSNAP/v2.0/emoney/topup-status |
Customer Topup Inquiry Status |
GET | HOST/cashin/snap/v2.0/merchant/account/balance |
Customer Topup Check Balance Deposit |
Partner with client-specific use cases (non-user-related use-case) can use the below API to generate system tokens.
Before generating the token, partners are requested to address this as a requirement, so OVO can configure the necessary.
As per BI requirements, the token expiry for B2B token should be 15 minutes
Not recommended to call System Token (B2B) every time transaction happen
Endpoint: HOST/OVOSNAP/{version}/access-token/b2b
Parameter | Data Type | Mandatory | Description |
---|---|---|---|
X-CLIENT-KEY | String | M | Client’s client_id (PJP Name) (given at completion registration process ) |
Content-Type | String | M | String represents indicate the media type of the resource (e.g. application/json, application/pdf) |
X-SIGNATURE | String | M | Using Asymmetric Signature |
X-TIMESTAMP | String | M | Client's current local time in yyyy-MM-ddTHH:mm:ss.SSSTZD format |
Parameter | Data Type | Mandatory | Description |
---|---|---|---|
grantType | String | M | "client_credentials”: The client can request an access token using only its client credentials (or other supported means of authentication) when the client is requesting access to the protected resources under its control |
Parameter | Data Type | Description |
---|---|---|
responseCode | String | Refer to standar data dan spesifikasi teknis part 6 (Response Code).If access token failed to generate, this value must be filled. |
responseMessage | String | Refer to standar data dan spesifikasi teknis part 6 (Response Message)If access token failed to generate, this value must be filled. |
accessToken | String (2048) | A string representing an authorizationissued to the client that used to accessprotected resources |
tokenType | String | The access token type provides the client with the information required to successfully utilize the
access token to makea protected resource request (along with type-specific attributes)
Token Type Value:
|
expiresIn | String | Session expiry in seconds |
curl --location --request POST 'https://app.byte-stack.net/OVOSNAP/v1.0/access-token/b2b' \
--header 'x-client-key: test' \
--header 'Content-Type: application/json' \
--header 'X-Signature: 14fc9b92ce30559b3db75987b0150890e2680fe5dc8e2eda9ed77304603dcf0670f41ff1de1b3d5a79e417f39391abb694f41028b1a425f2d40e7eccf988a5f281f96afea63a8cfe7f01938b7d67a76070b7fb3a7c6cdfe1f94e6e98e502db8cdc8a7db0aa08186ae44c28197a3b2f66dd8170d0a1c848f0a424a6d857ecbf8337cefa7120b5e4a04bd52f4cc9a6ae5a3bd9c8125227b5a259cd03ed7c4ea3afef9f147f3d73b99b3c1e6df68011b485ed0c177133c92d8cce913f14bb10da8223783c8b94b0c0a65b07fdeac0f3687d86a95bb4389f4e15b5679119dee0679823dd8db5e28af728c32600d1a2af48871ec2134dc5ac6ede056fb7d557d5d824' \
--header 'x-Timestamp: 2022-08-02T02:03:08.123Z' \
--data-raw '{
"grantType" : "client_credentials"
}'
{
"responseCode": "2007300",
"responseMessage": "Success",
"accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJjb2RlaGFzaCI6IlptVTRORGt5WVRnM01EZ3lOR1JpWmprMU5HSTBZakE1TURVMU1UWmhOV0kiLCJyYW5kb20iOiJOalF3TXpFMk5RIiwidmVyc2lvbiI6MX0.Wo5-5jM07X6Ft9UjZx0u2H9egmu76VwXoZzxcB_noSQ",
"tokenType": "Bearer",
"expiresIn": "900"
}
All the APIs mentioned are to follow the standard header format mentioned here, unless stated otherwise
Parameters | Description | Attribute | Example |
---|---|---|---|
Content-type | String represents indicating the media type of the resource | Mandatory | application/json,application/pdf |
Authorization | Represents access_token of a request;string starts with keyword “Bearer ”followed by accessToken (e.g. BearereyJraWQiOi...JzcIiwiY) | No Need For
|
Bearer gp9HjjEj813Y9JGoqwOeOPWbnt4CUpvIJbU1mMU4a11MNDZ7Sg5u9a |
X-PARTNER-ID | Client's client_id. | Mandatory | oamerchantg |
X-TIMESTAMP | Client's current local time in yyyyMMddTHH:mm:ss.SSSTZD format | Mandatory | |
X-SIGNATURE |
|
Mandatory | Please check Signature Section |
X-DEVICE-ID | Device identification on which the API services are currently being accessed by the end-user (customer) | Optional | |
X-EXTERNAL-ID | Unique ID to avoid duplication. ID reset for every 24 hours Use this
for
|
Mandatory | |
CHANNEL-ID | PJP’s channel id Device identification on which the API services is currently being accessed by the end user (customer) | Optional |
Here is the list of authentication related common error codes that can be returned throughout all APIs. Please note that the “XX” in the middle of the error code will follow the respective service code of the API. Except for the APIs that are not part of BISNAP, but are using the same BISNAP authentication mechanism, for this kind of API “XX” will stay as it is.
HTTP Code | Error Code | Error Message (Indonesian) |
---|---|---|
401 | 401XX00 | Unauthorized. [reason] |
401 | 401XX01 | Invalid Token:Anda Tidak Memiliki Akses |
{
"data": {
"actionables": [
{
"pinWebviewURL": "https://webview.byte-stack.net/cellblockui/v2/paymentPin",
"qParams": {
"action": "regeneratePayment",
"client-id": "snapinternalcimb"
},
"token": "PaymentToken"
}
],
"error": {
"code": "OV00502",
"message": "Unauthorized access"
}
},
"responseCode": "4013701",
"responseMessage": "Invalid Token:Anda Tidak Memiliki Akses"
}
{
"responseCode": "4013700",
"responseMessage": "Unauthorized. No Interface Definition: Timestamp."
}
{
"responseCode": "4013700",
"responseMessage": "Unauthorized. Signature Failed: AGW-002-05."
}
Signature asymmetric is used by OVO to verify that your access token request is not altered by attackers.
SHA256withRSA is used to generate the signature with your Private Key as the key.
X-SIGNATURE = SHA256withRSA(PrivateKey, StringToSign)
The StringToSign will be a colon-separated list derived from some request data as below:
StringToSign = HTTPMethod + ”:“+ EndpointUrl +":“ + Lowercase(HexEncode(SHA-256(minify(RequestBody)))) + ":“ + TimeStamp
Signature is used to verify that your open API service request is not altered by attackers.
SHA-512 HMAC is used to generate the signature with your Client Secret as the key.
X-SIGNATURE = HMAC-SHA512(ClientSecret, StringToSign)
The StringToSign will be a colon-separated list derived from some request data as below :
stringToSign = HTTPMethod + ”:“+ EndpointUrl +":"+ AccessToken + ":“+ Lowercase(HexEncode(SHA-256(minify(RequestBody)))) + ":“ + TimeStamp
openssl genrsa -out private.pem 4096
openssl rsa -in private.pem -RSAPublicKey_out -out public.pem
HTPP Code | Error Code | Error Message (Indonesian) |
---|---|---|
401 | 4017300 | Unauthorized. [HMAC mismatch] |
400 | 4007301 | Invalid timestamp format [X-TIMESTAMP] |
400 | 4017300 | Invalid field format [clientId/clientSecret/grant_type] |
This snippet code is an example on how to check SNAP Auth validity
package main
import (
"crypto"
"crypto/hmac"
"crypto/rsa"
"crypto/sha256"
"crypto/sha512"
"crypto/x509"
"encoding/hex"
"encoding/pem"
"errors"
"fmt"
"strings"
)
const PrivateKey = `-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAghghSSsbhCKBllAWbLmqdvqkg/b/yrRXE3PHzH2zkOVUgV/u
YtmLAaMUOt4UGiBKQa4TcRPPf6ITQpHCrpgpCadQAvikTFF+BW7pBdSvfZQVsscf
9MGLFkz7+uQlcnrDotHjeQ1Ei4wWU/kqe5rLRJZMl2+91yxWeaLTgockF6Mb8XrR
DI4DdaxBY0Lr0B20QqOFgM54ti1i628vAQGFFZPw2rgKufLOmRkJ9A8+vjVhXxC3
8sB2Is81okJcQKsLQZT4IqLxayF8jfr2j9mZtTCpoBdjQIVcbCbOFKtNN7c1j7wy
c8T9lWPPY43vKzfNf73w9JzKLfH6M8LDfJFIzwIDAQABAoIBAAsi2aaTxBU5hvJB
BMpl0kvBBNgvCpJlgZausIm2sOpUVzmD5robeSS4uwCXBg1+ehzJM+zYD0kTrKZk
J9AeQlULN3QpqJbH2wvIBLZ1EFilln3pQbkH4EoWaPN/GB2GmLyVTu2LzzRK15Z0
m8hc5c2HOCM2c3+50eUzpPtlaheDxRP5STPZVVpz87UyK09FAstzGNYmzZ733lDV
JoVGaa7hWTxzm4M4oxo2Bb06FSW2g3HKkqWC8PGBQ4nxDo7Xy3AkEYI3fGsYXbjC
fn/xMly/ARFWM1sICJTHzNdpHPIBuYtRJ8bEgc1Pew8g+JfAA1BFCWvYqcwjxIr9
6+JEfsECgYEA3AQdKGGq2sSPghbBbeWMotXxzXtwxJjxFAvRR32riIiu/qdtoC29
rsBpjvSs4jFVd4II6cE7xy0xJLtOU6asNIfhJbL3k3/f+HCN2PzkHwsNHIG6Xb8v
m9W+YCJudOmQJzfWUDcwfYk+uL0f6DnhGpazr5HkPmvicVzEsV3cRBECgYEAl18Q
8SwA8qwf18wCbVTgX/u2XD33lnabnz8a4F/5N4pKs7FKPDz7bgW4Jyik9+THZsrG
zepw8wXxzNqyTLC0WmyyYLTNp1x7EUBfAM40QYjydXcbXrTti28OGAKTh/DB3OvO
vl9uO+FfwWFXIdVK4Ie8JWsFrn5ciBM04aY4Ht8CgYBgeiVXCczj9YGAZ/4V9KzA
0tQfaNvAOditE6mHkeHgEx+5Zy25KZWdxZ4EI+KTpVJ2/zxtVGCkLHr6QnBMWi/1
MQhXgazyrwZFaQWqeuqFelEbiP9yEF4OFaJPgYmyFqExsVh3AFxxD/fDBpuxN4Aw
KplMicruXFyFnUpbBG+MIQKBgGFZfmfcSO/IyuHaDmWKBJM2Kt2/7I8T0Jnl178d
egXCJrDSAFAlV/42J2znstDKjYMKPjkH4YQp+owoyiqQKi1NYprXLLvJukwp/e9i
rjDHhkcNRsjtyye1UHcYkREIQWV3Mgs1DIvuMcsIcyULK5CjOtlFru29znyk/Ylx
gP45AoGBAIBkUjJo+xd7sNNhNCW07rUiAWegEHOIk5pWzwLDlY2AVK9/tlNBI6wD
GWLT6L5B9reN+982tOEBAYlP/p2e+eUBy8BPgvqbsPD3yHD3pR8WibrNEVwGhL8P
SC/C9azKvNlBsN1HRWdRrEN9Fx5Eu15XNBlKX1RIiHkv8iW1n6F9
-----END RSA PRIVATE KEY----
`
const PublicKey = `-----BEGIN RSA PUBLIC KEY-----
MIIBCgKCAQEAghghSSsbhCKBllAWbLmqdvqkg/b/yrRXE3PHzH2zkOVUgV/uYtmL
AaMUOt4UGiBKQa4TcRPPf6ITQpHCrpgpCadQAvikTFF+BW7pBdSvfZQVsscf9MGL
Fkz7+uQlcnrDotHjeQ1Ei4wWU/kqe5rLRJZMl2+91yxWeaLTgockF6Mb8XrRDI4D
daxBY0Lr0B20QqOFgM54ti1i628vAQGFFZPw2rgKufLOmRkJ9A8+vjVhXxC38sB2
Is81okJcQKsLQZT4IqLxayF8jfr2j9mZtTCpoBdjQIVcbCbOFKtNN7c1j7wyc8T9
lWPPY43vKzfNf73w9JzKLfH6M8LDfJFIzwIDAQAB
-----END RSA PUBLIC KEY-----
`
const RawBody = `{"foo": "bar"}`
func main() {
specs := Specs{
ClientID: "test",
PrivateKey: PrivateKey,
PublicKey: PublicKey,
ClientSecret: "foo-bar",
HTTPMethod: "POST",
URI: "/foo/bar",
RawBody: []byte(RawBody),
Timestamp: "2022-03-10T04:02:11.108+07:00",
AccessToken: "foobar",
}
AccessTokenSignature := "730f96f44e95c3b9fe7cb3ed94efa0cf8424813c0aa5974bd1c66ca0dcd00150107decca4de63b5b776cc7f7db25cf67ba70740438af76776bd15cba75e4604ae97e8b27f8ce36b87ad34ae6eaf4c3390a80db7e353b8384c85d8bf95ff8095e183d45520d739e12228fdbdf673b361ab97ac6de1bd544fd9b850d3cb5f91e47d6d7975565004d7551e23ca5bf42db9090e200f65789eaa74ff50ecb3a316786831d0f89e66230fcbd7e7195ba9b5f40f46b3b7001ab6b8f47d7be68656f5be0a8ff4a51bebb2c2741e997ca33adcec1ec58137af5a61b6234f7791399be6c1fcdfd1c2650a39d29ff8c38c6350754255b4970db1f44da43175798637b47784c"
SymmetricSignature := "9b4ad98c7e4107ac7008576fb0347eb2369d540f929435a438d81094d4cb6b65348e06cb9af4660deb86a4508694f8431b30351e57f9874662e3740779fcdc4b"
AsymmetricSignature := "533c8f937b285ac9d258f85b01d48ad8a1cf66d7418686dcd030bb6d6775bd88b0526d4abe92e8f3a2142efd8905e4fa77460a5affc064b57a3607dc6849d3fb3b7895d425e027f01f43f067c8bfcd1c25a039d2d9d3a8f1df36ab9d2607778b6d1f846e2f3e606aa87c8eca9b1a6a4bd35b072ea7beb0ec80714594ade85eede4992892eaaa1f3a46f48cd17f2b6e46753e76546fa39990e0f4e7a5f077f2586092af0bfbff38ceceebf7dfcafe2e1a8c3b3cca003d4802aebb1f659b40bab08f43aaa9349df9d69e6c3e88cae7b5a1721bf1c06f9c081e10fe6f8ef087fd4e3e616a4ae35040612a4abdbda211f02a386d07a988906a06e2bd29c1722583f3"
err := Validate(AccessTokenSignature, AccessToken, specs)
if err != nil {
println(err.Error())
} else {
println("Validation success.")
}
err = Validate(SymmetricSignature, Symmetric, specs)
if err != nil {
println(err.Error())
} else {
println("Validation success.")
}
err = Validate(AsymmetricSignature, Asymmetric, specs)
if err != nil {
println(err.Error())
} else {
println("Validation success.")
}
}
type ValidationType string
const (
AccessToken ValidationType = "access-token"
Symmetric = "symmetric"
Asymmetric = "asymmetric"
)
var (
ErrInvalidHMAC = errors.New("invalid HMAC")
ErrInvalidValType = errors.New("invalid validation type")
)
type Specs struct {
ClientID string
PrivateKey string
PublicKey string
ClientSecret string
HTTPMethod string
URI string
RawBody []byte
Timestamp string
AccessToken string
}
func Validate(signature string, valType ValidationType, specs Specs) error {
switch valType {
case AccessToken:
return validateAccessTokenSignature(signature, specs)
case Symmetric:
return validateSymmetricSignature(signature, specs)
case Asymmetric:
return validateAsymmetricSignature(signature, specs)
default:
return ErrInvalidValType
}
}
func validateAccessTokenSignature(signature string, specs Specs) error {
data := fmt.Sprintf("%s|%s", specs.ClientID, specs.Timestamp)
decodedSignature, err := hex.DecodeString(signature)
if err != nil {
return err
}
ok, err := SHA256WithRSAValidate(decodedSignature, []byte(specs.PublicKey), []byte(data))
if err != nil {
return err
}
if !ok {
return ErrInvalidHMAC
}
return nil
}
func validateSymmetricSignature(signature string, specs Specs) error {
transformedBody, err := transformBody(specs.RawBody)
if err != nil {
return err
}
data := fmt.Sprintf("%s:%s:%s:%s:%s", specs.HTTPMethod, specs.URI, specs.AccessToken, transformedBody, specs.Timestamp)
ok := SHA512HMACValidate([]byte(data), []byte(signature), []byte(specs.ClientSecret))
if !ok {
return ErrInvalidHMAC
}
return nil
}
func validateAsymmetricSignature(signature string, specs Specs) error {
transformedBody, err := transformBody(specs.RawBody)
if err != nil {
return err
}
data := fmt.Sprintf("%s:%s:%s:%s", specs.HTTPMethod, specs.URI, transformedBody, specs.Timestamp)
decodedSignature, err := hex.DecodeString(signature)
if err != nil {
return err
}
ok, err := SHA256WithRSAValidate(decodedSignature, []byte(specs.PublicKey), []byte(data))
if err != nil {
return err
}
if !ok {
return ErrInvalidHMAC
}
return nil
}
func transformBody(body []byte) (string, error) {
sha256Body := sha256.Sum256(body)
hexBody := hex.EncodeToString(sha256Body[:])
finalBody := strings.ToLower(hexBody)
return finalBody, nil
}
func SHA256WithRSAValidate(sig, pubPEM, data []byte) (bool, error) {
hashed := sha256.Sum256(data)
block, _ := pem.Decode(pubPEM)
if block == nil {
return false, errors.New("failed to decode public PEM")
}
pub, err := x509.ParsePKCS1PublicKey(block.Bytes)
if err != nil {
return false, err
}
err = rsa.VerifyPKCS1v15(pub, crypto.SHA256, hashed[:], sig)
if err != nil {
if errors.As(err, &rsa.ErrVerification) {
return false, nil
}
return false, err
}
return true, nil
}
func SHA512HMACValidate(message, messageMAC, key []byte) bool {
mac := hmac.New(sha512.New, key)
mac.Write(message)
expectedMAC := mac.Sum(nil)
expectedMacEncoded := hex.EncodeToString(expectedMAC)
return hmac.Equal(messageMAC, []byte(expectedMacEncoded))
}
This API will be used by Merchants to get the user information before initiating Top Up
Your request must contain the following information:
Parameter | Data Type | Mandatory | Description |
---|---|---|---|
partnerReferenceNo | String | M | Unique Transaction identifier on service consumer system. Value needs to be the same with the top-up call.Max: 64 chars |
customerNumber | String | M | Customers OVO Account Number which want to Top Up. Its Mandatory for Customer Top Up |
>amount | Object | M | |
>>value | String (ISO4217) | M | Net amount of the transactions. If it's IDR then the value includes 2 decimal digits. eg IDR 10,000,- will be placed with 10000.00 |
>>currency | String | M | Currency (IDR) |
transactionDate | yyyy-MM-ddThh:mm:ss+07:00 | O | transactions date : ISO 8601 |
>additionalInfo | Object | O | Additional information |
>>preInquiryFlag | String | O | Value = Y/N
Default = N Y -> For read only, meaning the Customer Topup inquiry data will not be used for customer top up validation. N -> Customer Topup Inquiry To be used for Customer Top Up Validation *usually value = N will be used the same with omitting this field, value = Y is only used when special events need to be catered for example when partners have some function to do Topup Inquiry without doing top up later on. |
>>senderInstitutionID | String | O | Contains the ID of Sender Institution that is a unique identifier for institutions like Banks or Collecting Agents. This could be a Transfer Bank Code, Collecting Agent Code, or any other unique code assigned to these institutions. This will need to be mapped to Institution Name at OVO side, and the name will be shown in OVO User Transaction History Detail. |
Parameter | Data Type | Mandatory | Description |
---|---|---|---|
responseCode | String | M | Response code |
responseMessage | String | M | Response description |
referenceNo | String | C | Transaction identifier on service provider system. Be filled upon successful transactions |
partnerReferenceNo | String | M | Transaction identifier on service consumer system |
customerNumber | String | M | Customers Account Number Rule of mask for UI XXXXXXXXX1857 |
customerName | String | C | Customers account name Rule of mask for UI: - 1 char = A - 2 chars = AA - 3 chars = A** - 4 chars = A A** - > =5 chars = AA**A |
customerMonthlyInLimit | Numeric | C | Customers monthly cash-in limit |
>minAmount | Object | O | |
>>value | String (ISO4217) | M | Net amount of the transactions. If it's IDR then the value includes 2 decimal digits. eg IDR 10,000,- will be placed with 10000.00 |
>>currency | String | M | Currency |
>maxAmount | Object | C | |
>>value | String (ISO4217) | M | Net amount of the transactions. If it's IDR then the value includes 2 decimal digits. eg IDR 10,000,- will be placed with 10000.00 |
>>currency | String | M | Currency |
>amount | Object | C | |
>>value | String (ISO4217) | M | Net amount of the transactions. If it's IDR then the value includes 2 decimal digits. eg IDR 10,000,- will be placed with 10000.00 |
>>currency | String | M | Currency |
>feeAmount | Object | C | |
>>value | String (ISO4217) | M | Fee amount of transaction. |
>>currency | String | M | Currency |
feeType | String | O | Fee type (Admin Fee) |
>additionalInfo | Object | O | Additional information |
>>preInquiryFlag | String | O | From the request |
>>responseInfo1 | String | O | Inquiry response additional info 1 |
>>senderInstitutionID | String | O | From the request |
Notes:
{
"partnerReferenceNo": "20220728000000001",
"customerNumber": "080000000001",
"amount": {
"value": "100000.00",
"currency": "IDR"
},
"transactionDate": "2022-07-28T10:00:00+07:00",
“additionalInfo”: {
“preInquiryFlag”: “N”
“senderInstitutionID“: “999”
}
}
{
"responseCode": "2003700",
"responseMessage": "Request has been processed successfully",
"referenceNo": "20220728000000001",
"partnerReferenceNo": "20220728000000001",
"customerNumber": "XXXXXXXX0001",
"customerName": "C**tomer Na**",
"customerMonthlyInLimit": "40000000",
"minAmount": {
"value": "10000.00",
"currency": "IDR"
},
"maxAmount": {
"value": "20000000.00",
"currency": "IDR"
},
"amount": {
"value": "100000.00",
"currency": "IDR"
},
"feeAmount": {
"value": "1000.00",
"currency": "IDR"
},
"feeType": "Admin fee",
“additionalInfo”: {
“preInquiryFlag”: “N”
“senderInstitutionID”: “999”
}
}
HTTP Code | Response Code | Error Message (English) | Remarks |
---|---|---|---|
200 | 2003700 | Request has been processed successfully | Request success |
403 | 4033718 | Customer Account Not Found | Request failed |
403 | 4033705 | Account or User Status is Inactive | Request failed |
403 | 4033702 | Exceeds Transaction Amount Limit | Request failed |
403 | 4033719 | Merchant Blacklisted (temporary disabled or missing authorization) | Request failed |
404 | 4043716 | Partner Not Found (missing configuration) | Request failed |
403 | 4033706 | Feature Not Allowed At This Time. In Maintenance Mode | Request failed |
400 | 4003702 | Invalid Mandatory Field partnerReferenceNo | Request failed |
400 | 4003701 | Invalid Field Format amount.value | Request failed |
400 | 4003702 | Invalid Mandatory Field value | Request failed |
400 | 4003701 | Invalid Field Format transactionDate: must be a valid date | Request failed |
400 | 4003702 | Invalid Mandatory Field customerNumber | Request failed |
404 | 4043713 | Invalid Amount | Request failed |
400 | 4003700 | Bad Request currency: must be a valid value | Request failed |
403 | 4033723 | Account Monthly Limit Exceed | Request failed |
409 | 4093700 | Conflict | Request failed |
500 | 5003700 | General Error (Internal server error) | Request failed |
500 | 5003702 | Unknown Error | Request failed |
Notes:
This API will be used by Merchants to Initiate Topup
Your request must contain the following information:
Parameter | Data Type | Mandatory | Description |
---|---|---|---|
partnerReferenceNo | String | M | Transaction identifier on service consumer system.Need to be the same value from Customer Topup Inquiry Request |
customerNumber | String | M | Customers Account numberNeed to be the same value from Customer Topup Inquiry Request |
customerName | String | O | Customers Account name |
>amount | Object | M | |
>>value | String (ISO4217) | M | Net amount of the transactions. If it's IDR then the value includes 2 decimal digits. eg IDR 10,000,- will be placed with 10000.00 Need to be the same value from Customer Topup Inquiry Request |
>>currency | String | M | Currency Need to be the same value from Customer Topup Inquiry Request |
>feeAmount | Object | M | |
>>value | String (ISO4217) | M | Transaction feeNeed to be the same value from Customer Topup Inquiry Response |
>>currency | String | M | Currency Need to be the same value from Customer Topup Inquiry Response |
transactionDate | yyyyMMddhhmmss | O | Transaction date |
sessionId | strings | O | Invoice transactions ID |
categoryId | numeric | O | Category ID |
notes | strings | O | Transaction note |
>additionalInfo | Object | O | Additional information |
>>senderInstitutionID | String | O | Contains the ID of Sender Institution that is a unique identifier for institutions like Banks or Collecting Agents. This could be a Transfer Bank Code, Collecting Agent Code, or any other unique code assigned to these institutions. This will need to be mapped to Institution Name at OVO side, and the name will be shown in OVO User Transaction History Detail. |
>>senderUniqueID | String | O | Contains a unique identifier of the sender. If it is sensitive data it needs to be hashed. |
Parameter | Data Type | Mandatory | Description |
---|---|---|---|
responseCode | String | M | Response code |
responseMessage | String | M | Response description |
referenceNo | String | C | Transaction identifier on service provider system. Must be filled upon successful transactions |
partnerReferenceNo | String | M | Transaction identifier on service consumer system |
sessionId | String | O | Transaction invoice ID |
customerNumber | String | O | Customers account number |
>amount | Object | C | |
>>value | String (ISO4217) | M | Net amount of the transactions. If it's IDR then the value includes 2 decimal digits. eg IDR 10,000,- will be placed with 10000.00 |
>>currency | String | M | Currency |
>additionalInfo | Object | O | Additional information |
>>responseInfo1 | String | O | Top up response additional info 1 |
>>senderInstitutionID | String | O | From the request |
>>senderUniqueID | String | O | From the request |
{
"partnerReferenceNo": "20220728000000001",
"customerNumber": "080000000001",
"amount": {
"value": "100000.00",
"currency": "IDR"
},
"feeAmount": {
"value": "1000.00",
"currency": "IDR"
},
"transactionDate": "2022-07-28T10:00:00+07:00",
"additionalInfo": {
"senderInstitutionID": "999",
"senderUniqueID": "9999999999999999"
}
}
Notes:
{
"responseCode": "2003800",
"responseMessage": "Request has been processed successfully",
"referenceNo": "20220728000000001",
"partnerReferenceNo": "20220728000000001",
"customerNumber": "XXXXXXXX6594",
"amount": {
"value": "100000.00",
"currency": "IDR"
},
"additionalInfo": {
"senderInstitutionID": "999",
"senderUniqueID": "9999999999999999"
}
}
HTTP Code | Response Code | Error Message (English) | Remarks |
---|---|---|---|
200 | 2003800 | Request has been processed successfully | Request success |
403 | 4033815 | Transaction Not Permitted | Request failed |
403 | 4033802 | Exceeds Transaction Amount Limit | Request failed |
403 | 4033823 | Account Monthly Limit Exceed | Request failed |
403 | 4033805 | Account or User status is abnormal | Request failed |
403 | 4033819 | Merchant Blacklisted (temporary disabled or missing authorization) | Request failed |
404 | 4043816 | Partner Not Found (missing configuration) | Request failed |
403 | 4033806 | Feature Not Allowed At This Time. In Maintenance Mode | Request failed |
404 | 4043813 | Invalid Amount | Request failed |
409 | 4093800 | Conflict | Request failed |
400 | 4003800 | Bad Request | Request failed |
400 | 4003802 | Invalid Mandatory Field partnerReferenceNo | Request failed |
400 | 4003802 | Invalid Mandatory Field customerNumber | Request failed |
400 | 4003802 | Invalid Mandatory Field value | Request failed |
400 | 4003801 | Invalid Field Format transactionDate: must be a valid date | Request failed |
400 | 4003800 | Bad Request currency: must be a valid value | Request failed |
500 | 5003800 | General Error (Internal server error) | Request failed |
500 | 5003802 | Unknown Error | UNKNOWN, please do check inquiry top up status |
504 | - | Timeout / Gateway timeout | UNKNOWN, please do check inquiry top up status |
5xx | - | Any unknown 5xx error | UNKNOWN, please do check inquiry top up status |
Notes:
This API will be used by Merchants to get top-up status for a specific top-up reference no
Parameter | Data Type | Mandatory | Description |
---|---|---|---|
originalPartneReferenceNo | String | O | Transaction identifier/reference generated by partners. |
originalReferenceNo | String | M | Transaction identifier/reference generated by PJP AIS Apart from Banks |
originalExternaIID | String | O | Original X EXTERNAL ID from top-up requests. |
serviceCode | String | M | To identify which transactions that need to be checked. (38) |
>additionalInfo | Object | O | Additional information |
Parameter | Data Type | Mandatory | Description |
---|---|---|---|
responseCode | String | M | Response code |
responseMesage | String | M | Response description |
originalPartnerReferenceNo | String | O | Transaction identifier/reference generated by partners. |
originalReferenceNo | String | M | Transaction identifier/reference generated by PJP AIS Apart from Banks. |
originalExternalID | String | O | Original X EXTERNAL ID from top-up requests. |
serviceCode | String | M | To identify which transactions that need to be checked. |
>amount | Object | C | |
>>value | String (ISO4217) | M | Net amount of the transactions. If it's IDR then the value includes 2 decimal digits. eg IDR 10,000,- will be placed with 10000.00 |
>>currency | String | Currency | |
latestTransactionStatus | String | M | 00 - Success 01 - Initiated 02 - Paying 03 - Pending 04 - Refunded 05 - Canceled 06 - Failed 07 -
Not foundThis field is valid when responseCode are: 200xx00, 404xx01
|
transactionStatusDesc | String | O | Description status transactions |
>additionalInfo | Object | O | Additional information |
{
"originalReferenceNo": "20220728000000001",
"serviceCode": "38"
}
{
"responseCode": "2003900",
"responseMessage": "Request has been processed successfully",
"originalPartnerReferenceNo": "",
"originalReferenceNo": "20220728000000001",
"serviceCode": "38",
"amount": {
"value": "100000.00",
"currency": "IDR"
},
"latestTransactionStatus": "00",
"transactionStatusDesc": "Success"
}
HTTP Code | Response Code | Error Message (English) | Remarks |
---|---|---|---|
200 | 2003900 | Request has been processed successfully | Request success.See “latestTransactionStatus” response for further action. |
404 | 4043901 | Transaction Not Found | Please create new trx |
409 | 4093900 | Conflict (X-EXTERNAL-ID) | Request failed |
404 | 4043916 | Partner Not Found (missing configuration) | Request failed |
400 | 4003900 | Bad Request | Request failed |
400 | 4003902 | Invalid Mandatory Field | Request failed |
500 | 5003900 | General Error (Internal server error) | UNKNOWN, please retry |
500 | 5003902 | Unknown Error | UNKNOWN, please retry |
504 | - | Timeout / Gateway timeout | UNKNOWN, please retry |
5xx | - | Any unknown error | UNKNOWN, please retry |
Notes:
This API will be used by Merchants to get top-up status for a specific top-up reference no
Method | URL |
---|---|
GET | /cashin/snap/v2.0/merchant/account/balance |
Parameter | Data Type | Mandatory | Description |
---|---|---|---|
>accountList | Object | ||
accountType | String | M | Merchant account type |
codeStr | String | M | Account Code |
>amount | Object | ||
currency | String | M | Currency |
value | Big Decimal | M | Account Balance Information |
Code | Response | Notes |
---|---|---|
200 |
{
|
Success |
400 |
{
|
Failed |
400 |
{
|
Failed |
400 |
{
|
Failed |
400 |
{
|
Failed |
400 |
{
|
Failed |
401 |
{
|
Failed |
401 |
{
|
Failed |
401 |
{
|
Failed |