Skip to main content

OVO Open API


Introduction#

OVO Open API Activation#

info

If you are personal seller, you can't use the OVO Open API due to the limitation from the OVO. Worry not! If you wish to receive payments from OVO, you can activate OVO Push Payment which enable you to receive payments from OVO.

Requirements#

  1. Client ID / Secret Key from OVO
  2. Jokul account. To access Jokul API, you need Jokul client id & Jokul client key that you can find in Jokul back office.

Integration Flow#

Here is the overview flow for OVO Open API :

Jokul Direct - OVO Open API Sequence DiagramJokul OVO Open API Merchant Flow

API list#

Here is the sample of request header to implement every API list below :

Client-Id: MCH-0001-10791114622547Request-Id: 15022aab-444f-4b04-afa8-ddfce89432ecRequest-Timestamp: 2020-08-11T08:45:42ZSignature: HMACSHA256=vl9DBTX5KhEiXmnpOD0TSm8PYQknuHPdyHSTSc3W6Ps=
Request Header Explanation
ParameterDescription
Client-IdClient ID retrieved from Jokul Back Office
Request-IdUnique random string (max 128 characters) generated from merchant side to protect duplicate request
Request-TimestampTimestamp request on UTC time in ISO8601 UTC+0 format. It means to proceed transaction on UTC+7 (WIB), merchant need to subtract time with 7. Ex: to proceed transaction on September 22th 2020 at 08:51:00 WIB, the timestamp should be 2020-09-22T01:51:00Z
SignatureSecurity parameter that needs to be generated on merchant Backend and placed to the header request to ensure that the request is coming from valid merchant. Please refer to this section to generate the signature

Merchant and Jokul must validate signature in API list, see how to generate signature. You can refer to Generate Signature.


User Account Linkage#

Merchant can binding OVO account to customer id, each OVO account can only binding to one customer on one merchant. Customer need to verify OTP and input PIN on OVO page.

API Request#

TypeValue
HTTP MethodPOST
API endpoint (Sandbox)https://api-sandbox.doku.com/ovo-open-api/v1/token
API endpoint (Production)https://api.doku.com/ovo-open-api/v1/token

Here is the sample of request body to binding OVO account to customer id :

{    "customer": {        "id": "CUSTOMER_OVOxDOKU",        "name": "TESTINGQA",        "phone": "087872180555",        "email": "test@gmail.com",        "additional_info": "None"    },    "ovo_account": {        "account_mobile_phone": "6287872180555",        "success_registration_url": "https://www.wtdteam.com/success",        "failed_registration_url": "https://www.wtdteam.com/failed"    }}
Request Body Explanation
ParameterTypeMandatoryDescription
customer.idstring (50)MandatoryMerchant customer id
customer.namestring (70)OptionalCustomer name
customer.emailstring (255)OptionalCustomer email
customer.phonestring (20)OptionalCustomer phone number
customer.additional_infostring (20)OptionalCustomer additional info
ovo_account.account_mobile_phonestring (20)MandatoryRegister phone number on OVO
ovo_account.success_registration_urlstring (2048)MandatoryURL for direct page after success register
ovo_account.failed_registration_urlstring (2048)MandatoryURL for direct page after failed register

API Response#

After hitting the above API request, Jokul will give the response.

TypeValue
HTTP Status201
ResultSUCCESS

Here is the sample of response body:

{    "customer": {        "id": "CUSTOMER_OVOxDOKU",        "name": "TESTINGQA",        "phone": "087872180555",        "email": "test@gmail.com",        "additional_info": "None"    },    "ovo_account": {        "registration_url": "https://jokul.doku.com/ovo-open-api/registration/sessionId/27817263817263817",        "status": "PENDING"    }}
Response Body Explanation
ParameterTypeMandatoryDescription
customer.idstring (50)MandatoryMerchant customer id
customer.namestring (70)OptionalCustomer name
customer.emailstring (255)OptionalCustomer email
customer.phonestring (20)OptionalCustomer phone number
customer.additional_infostring (20)OptionalCustomer additional info
ovo_account.account_mobile_phonestring (20)MandatoryRegister phone number on OVO
ovo_account.registration_urlstring (2048)MandatoryURL from DOKU for Customer to binding their account
ovo_account.statusstringMandatoryAlways PENDING for Successfull token request (waiting for OTP verification & PIN vervification)

Get List Token (OVO)#

After successful account linkage, merchant can get OVO token that can be used for that customer to payment using OVO. Token is created by Jokul, and valid for 1 year.

API Request#

TypeValue
HTTP MethodPOST
API endpoint (Sandbox)https://api-sandbox.doku.com/tokenization/v1/tokens
API endpoint (Production)https://api.doku.com/tokenization/v1/tokens

Here is the sample of request body to get Token for OVO :

{    "customer": {        "id": "CUSTOMER_OVOxDOKU"    },    "token_data": {        "type": "WALLET"    }}
Request Body Explanation
ParameterTypeMandatoryDescription
customer.idstring (50)MandatoryCustomer id that already have active token
token_data.typestringOptionalDIRECT_DEBIT / CREDIT_CARD / WALLET, if not specified get all payment channel token

API Response#

After hitting the above API request, Jokul will give the response.

TypeValue
HTTP Status200
ResultSUCCESS
{    "customer": {        "id": "CUSTOMER_OVOxDOKU",        "name": "TESTINGQA"    },    "token_data": {        "type": "WALLET"    },    "wallet": {        "issuer": "OVO",        "token_id": "fc72c4b0aedff916ab92e39cb80d3675",        "masked_phone_number": "****1454"    }}
Response Body Explanation
ParameterTypeMandatoryDescription
customer.idstring (50)MandatoryMerchant customer id
customer.namestring (70)OptionalCustomer name
token_data.typestringMandatoryToken Type : CREDIT CARD, DIRECT DEBIT , or WALLET
wallet.issuerstring (255)MandatoryIssuer for wallet binding
wallet.token_idstring (128)MandatoryToken generated by DOKU
wallet.masked_phone_numberstring (8)MandatoryPhone number masked

Get Account Balance#

This balance check API allows users to check their latest OVO balance. The user should be able to access their balance at any time so they can make accurate and up to date decision regarding their transactions.

API Request#

TypeValue
HTTP MethodPOST
API endpoint (Sandbox)https://api-sandbox.doku.com/ovo-open-api/v1/balance
API endpoint (Production)https://api.doku.com/ovo-open-api/v1/balance

Here is the sample of request body to get balance for OVO :

{    "customer": {        "id": "CUSTOMER_OVOxDOKU"    },    "ovo_account": {        "token_id": "fc72c4b0aedff916ab92e39cb80d3111"    }}
Request Body Explanation
ParameterTypeMandatoryDescription
customer.idstring (64)MandatoryCustomer id that already have active token
ovo_account.token_idstring (128)MandatoryToken generated by DOKU

API Response#

After hitting the above API request, Jokul will give the response.

TypeValue
HTTP Status201
ResultSUCCESS
{    "customer": {        "id": "CUSTOMER_OVOxDOKU",        "name": "TESTINGQA",        "phone": "087872180555",        "email": "test@gmail.com",        "additional_info": "None"    },    "ovo_account": {        "ovo_cash_balance": "100000",        "ovo_point_balance": "100000"    }}
Response Body Explanation
ParameterTypeMandatoryDescription
customer.idstring (50)MandatoryMerchant customer id
customer.namestring (70)OptionalCustomer name
customer.emailstring (255)OptionalCustomer email
customer.phonestring (20)OptionalCustomer phone number
customer.additional_infostring (20)OptionalCustomer additional info
ovo_account.ovo_cash_balancenumber (10)MandatoryOVO Cash Balance
ovo_account.ovo_point_balancenumber (10)MandatoryOVO Point Balance

Payment Using Token#

Payment using OVO token from OVO cash balance or/and OVO point balance. When OVO have program for payment using OVO point, customer can paying using OVO point balance on merchant. Payment using mixed OVO point and OVO cash, OVO point will be deducted first and the remaining will be deducted from OVO cash. Customer need to verify payment by input PIN on OVO page.

API Request#

TypeValue
HTTP MethodPOST
API endpoint (Sandbox)https://api-sandbox.doku.com/ovo-open-api/v1/payment
API endpoint (Production)https://api.doku.com/ovo-open-api/v1/payment

Here is the sample of request body to do payment using OVO Token :

{    "customer": {        "id": "CUSTOMER_OVOxDOKU",        "name": "TESTINGQA",        "phone": "087872180555",        "email": "test@gmail.com",        "additional_info": "None"    },    "additional_info": {           },    "order": {        "invoice_number": "MINV20201231468",        "line_items": [            {                "name": "bola",                "price": 10000,                "quantity": 1            },            {                "name": "ubi",                "price": 5000,                "quantity": 1            }        ],        "amount": 15000    },    "ovo_account": {        "token_id":"bcdbcdbcdbcbdbcdb-bcdbcd-bcdbcdb",        "payment_use_ovo_point": false,        "success_payment_url": "https://www.wtdteam/success",        "failed_payment_url": "https://www.wtdteam/failed"    }}
Request Body Explanation
ParameterTypeMandatoryDescription
customer.idstring (50)MandatoryMerchant customer id
customer.namestring (70)OptionalCustomer name
customer.emailstring (255)OptionalCustomer email
customer.phonestring (20)OptionalCustomer phone number
customer.additional_infostring (20)OptionalCustomer additional info
additional_infoJsonOptionaladditional info
order.invoice_numberstring (32)MandatoryMerchant transaction id unique per client id, only accept alphanumeric, _ and - Min length is 3, max length is 32
order.line_items.namestringOptionalPrivacy concern so optional, but if send will help our risk engine
order.line_items.pricenumberOptionalPrivacy concern so optional, but if send will help our risk engine
order.line_items.quantitynumberMandatoryPrivacy concern so optional, but if send will help our risk engine
order.amountnumber (10)MandatoryConverted total amount.
ovo_account.token_idstring (128)MandatoryOVO E-Wallet Token
ovo_account.payment_use_ovo_pointstring (5)OptionalDefault false, if True will use all OVO Point first before use OVO Cash
ovo_account.success_payment_urlstring (2048)MandatoryURL for direct page after success payment
ovo_account.failed_payment_urlstring (2048)MandatoryURL for direct page after failed payment

API Response#

After hitting the above API request, Jokul will give the response.

TypeValue
HTTP Status201
ResultSUCCESS
{    "customer": {        "id": "CUSTOMER_OVOxDOKU",        "name": "TESTINGQA",        "phone": "087872180555",        "email": "test@gmail.com",        "additional_info": "None"    },    "additional_info": {           },    "order": {        "invoice_number": "MINV20201231468",        "line_items": [            {                "name": "bola",                "price": 10000,                "quantity": 1            },            {                "name": "ubi",                "price": 5000,                "quantity": 1            }        ],        "amount": 15000    },    "payment": {        "ovo_payment_url": "https://jokul.doku.com/ovo-open-api/payment/sessionId/27817263817263817263817",        "status": "PENDING"    }}
Response Body Explanation
ParameterTypeMandatoryDescription
customer.idstring (50)MandatoryMerchant customer id
customer.namestring (70)OptionalCustomer name
customer.emailstring (255)OptionalCustomer email
customer.phonestring (20)OptionalCustomer phone number
customer.additional_infostring (20)OptionalCustomer additional info
additional_infoJsonOptionaladditional info
order.invoice_numberstring (32)MandatoryMerchant transaction id unique per client id, only accept alphanumeric, _ and - Min length is 3, max length is 32
order.line_items.namestringOptionalPrivacy concern so optional, but if send will help our risk engine
order.line_items.pricenumberOptionalPrivacy concern so optional, but if send will help our risk engine
order.line_items.quantitynumberMandatoryPrivacy concern so optional, but if send will help our risk engine
order.amountnumber (10)MandatoryConverted total amount.
payment.ovo_payment_urlstring (255)Mandatoryurl from DOKU for customer to input pin for transaction
ovo_account.payment_use_ovo_pointstring (5)OptionalDefault false, if True will use all OVO Point first before use OVO Cash
payment.statusstringMandatoryURL for direct page after success payment
ovo_account.failed_payment_urlstring (2048)MandatoryPENDING for successful token request (waiting for OTP verification) / SUCCESS if not need OTP, TOKEN_EXPIRED (need to input PIN twice and still can proceed to transaction)

Refund#

Refund OVO transaction. For payment using mixed OVO cash and OVO point, OVO point will be refunded first.

API Request#

TypeValue
HTTP MethodPOST
API endpoint (Sandbox)https://api-sandbox.doku.com/ovo-open-api/v1/payment-refund
API endpoint (Production)https://api.doku.com/ovo-open-api/v1/payment-refund

Here is the sample of request body to do refund for OVO Transaction :

{    "order": {        "invoice_number": "MINV20201231468"    },    "payment": {        "original_request_id": "82014"    },    "refund": {        "amount": 1000,        "reason": "Cancel Order"    }}
Request Body Explanation
ParameterTypeMandatoryDescription
order.invoice_numberstring (32)MandatoryInvoice number of the transaction that being refunded, same as the request payment
payment.original_request_idstring (128)MandatoryRequest ID from Payment Initiation of the transaction that being refunded
refund.amountnumberMandatoryTransaction amount that wants to be refunded
refund.reasonstring (255)OptionalReason refund

API Response#

After hitting the above API request, Jokul will give the response.

TypeValue
HTTP Status201
ResultSUCCESS
{    "order": {        "invoice_number": "MINV20201231468"    },    "payment": {        "original_request_id": "82014"    },    "refund": {        "amount": 1000,        "reason": "Cancel Order",        "status": "SUCCESS",        "message": "SUCCESS"    }}
Response Body Explanation
ParameterTypeMandatoryDescription
order.invoice_numberstring (32)MandatorySame as the request
payment.original_request_idstring (128)MandatorySame as the request
refund.amountnumberMandatoryAmount to be refunded
refund.reasonstring (255)OptionalReason refund
refund.statusstringMandatorySUCCESS / FAILED
refund.messagestring (10)OptionalReason if failed refund

Unbind Linked Account#

Customer should always have option to unlink their OVO account from any merchant.

API Request#

TypeValue
HTTP MethodPOST
API endpoint (Sandbox)https://api-sandbox.doku.com/ovo-open-api/v1/token-delete
API endpoint (Production)https://api.doku.com/ovo-open-api/v1/token-delete

Here is the sample of request body to unlink their OVO Account :

{    "customer": {        "id": "TEST-CIMBXDOKU-05",        "name": "DOKUXCIMB"    },    "ovo_account": {        "token_id": "1614dc147e404f41f6d2de877fda1f94"    }}
Request Body Explanation
ParameterTypeMandatoryDescription
customer.idstring (50)MandatoryMerchant id
customer.namestring (50)MandatoryMerchant name
ovo_account.token_idstring (128)MandatoryToken created from register ovo account that owned by this customer id

API Response#

After hitting the above API request, Jokul will give the response.

TypeValue
HTTP Status201
ResultSUCCESS
{    "customer": {        "id": "TEST-CIMBXDOKU-05",        "name": "DOKUXCIMB"    },    "ovo_account": {        "token_id": "1614dc147e404f41f6d2de877fda1f94",        "status": "SUCCESS",        "message": "Success Unbiding OVO Account"    }}
Response Body Explanation
ParameterTypeMandatoryDescription
customer.idstring (50)MandatoryMerchant id
customer.namestring (50)MandatoryMerchant name
ovo_account.token_idstring (128)MandatoryToken created from register ovo account that owned by this customer id
ovo_account.statusstringMandatoryDELETED Token
ovo_account.messagestringOptionalSUCCESS unbind token_id from customer

Technical Reference#

Payment Notification#

Guide how to handle payment notification can refer to Handling HTTP Notification.


Handling Idempotent Request#

Idempotency is a concept where a request can be sent multiple times with the same result as the first request, that means the system only performs one process for identical requests.

The examples below illustrate how idempotency is works.

Two Request, Connectivity Lost

Situation:

T0: Partner sends a payment request to DOKU T1: DOKU server receives this request and processes it successfully. With response http status 200 T2: Partner's server loses power prior to receiving the response in T1. T3: Partner's server power is restored and the same payment request is sent with all the same parameters (same request-ID and request details but updated requestTimestamp) to the DOKU server.

Outcome:

In this case the DOKU server reply with the same reply given at T1 since all the parameters, except for responseTimestamp, are the same. The user is only debited once, at T0. T3 has no monetary impact to the user.

Please note

DOKU reply http status 409 (CONFLICT) with same response if any potential loss for DOKU or Partner. For example, when process transaction if merchant can't handle properly idempotency response, and probably they will define as another success order.

List of Error Code#

Error messageError CodeHTTP Status CodeExplanation
Invalid Header Signatureinvalid_signature400Invalid Signature
Idempotent Requestidempotent_request400Double request with same request id under 20 second
OVO Account not available please register to OVOaccount_error400OVO account not found
Customer id must not be emptyinvalid_parameter400Not input object customer id (applied to every mandatory parameter)
Attribute customer id must not bigger than 50 character(s)invalid_parameter400Object customer id > 50 character (applied to every parameter that more than data type max length)
Email format must be validinvalid_parameter400Invalid format in customer email
Account mobile phone format must be 62xxxxinvalid_parameter400Invalid format in Account mobile phone number
Invalid url for attribute success registration urlinvalid_parameter400Invalid format in success registration url
Invalid url for attribute failed registration urlinvalid_parameter400Invalid format in failed registration url
Attribute refund reason must not bigger than 255 character(s)invalid_parameter404Object refund reasong > 255 character (applied to every parameter that more than data type max length)
Invalid token idinvalid_parameter400Invalid token id
Customer change phone numberaccount_error400Customer change phone number on OVO Platform, please proceed to unbind linked account
Charge payment failedaccount_error400Charge payment failed
High risk transactionre_error400High risk transaction
Attribute account_mobile_phone must be 10-20 digitsinvalid_parameter400account_mobile_phone not in valid range 10 - 20 digits
Something wrong in OVOaccount_error400Something wrong in OVO system please contact Jokul team
Exceeds attempt limit, not allowed request OTP for 30minaccount_error400Exceeds OTP request limit for this account_mobile_phone
Transaction not foundaccount_error400Refund can't be processed, transaction not yet done / not found
OVO Account Blocked Temporaryaccount_error400OVO Account block temporary because of wrong PIN attempt
Account Mobile Phone already usedinvalid_access401OVO is already registered to other customer
Invalid token idinvalid_access401OVO account already unbind
Customer ID is already usedinvalid_access401Customer already linked with another ovo account
Token not foundnot_found404Token ID not found
Given customer token not match with saved customer tokennot_found404Customer token not match with saved customer id merchant
Customer not foundnot_found404Customer not found
Original transaction not foundnot_found404Original payment not found
Refund amount is greater than paid amountaccount_error400Refund amount greater than paid amount
Merchant not foundnot_found404Merchant not found