OVO Recurring
OVO Recurring enables merchants to charge customers automatically for subscription-based services using the OVO wallet, one of the top e-wallets in Indonesia. Customers authorize a subscription once, allowing merchants to perform future debits without manual approval for every transaction.
This capability is commonly used for SaaS and digital subscriptions, gaming memberships and in-app subscriptions, streaming and entertainment services, e-learning platforms, and utilities and telecom services.
Key Features
| Feature | Purpose | Benefit |
|---|---|---|
| Enrollment Authorization | Customer enrollment approval. | Enables secure customer consent while removing the need for repeated authorization for each payment. |
| Merchant Initiated Charges | Create new charges linked to a previously accepted enrollment. | Simplifies billing automation and reduces friction for subscription-based services. |
| Subscription Lifecycle Management | Provides the ability to query, cancel, or manage subscription enrollments. | Gives merchants operational control over subscriptions and improves customer account management. |
| Payment Notifications | Sends asynchronous updates whenever payment status changes. | Ensures merchants receive real-time transaction updates for reconciliation and order fulfillment. |
How it works
- Subscription Enrollment - Merchant registers the subscription and redirects the user to authorize it in OVO.
- Recurring Payment Request - Merchant triggers a recurring charge linked to the enrollment when required.
- Payment Confirmation - EBANX sends payment status notifications to the merchant.
- Minimum Amount: IDR 1,000 (approx. $0.06 USD)
- Maximum Amount (Regular / Non-KYC User): IDR 2,000,000 (approx. $123 USD)
- Maximum Amount (Premium / KYC User): IDR 20,000,000 (approx. $1,227 USD)
Requirements
- API credentials - Ensure you have your EBANX integration key. If not, complete the Merchant Signup Form.
Instructions
Follow the steps below.
- Select your environment
Select the appropriate environment for your integration. Use the sandbox environment for testing or the production environment for live transactions.
Select the appropriate environment for your integration. Use the sandbox environment for testing, or the production environment for live transactions. Use the URL for your HTTP requests based on your selection.
https://sandbox.ebanx.com/ws/userenrollment - Define enrollment parameters
To start the recurring payment process, enroll the subscription using the
/ws/userenrollmentendpoint. This step involves collecting essential customer details and subscription parameters to establish the recurring billing agreement.Users will be required to complete 2FA to accept this enrollment in their app. Once the process is complete, the customer will be enrolled for the recurring payment cycle.
Basic parameters
Parameter Requirement Description integration_keyRequired Your EBANX integration key. operationRequired Must be enrollment.payment_type_codeRequired Must be ovo-recurring.Enrollment parameters
Parameter Requirement Description enrollment.merchant_enrollment_codeRequired Unique identifier for the enrollment. enrollment.emailRequired Customer email. enrollment.phone_numberRequired Customer phone number. enrollment.countryRequired Set to IDfor Indonesia.enrollment.back_urls.successRequired URL to redirect on success. enrollment.back_urls.failureRequired URL to redirect on failure. enrollment.subscription.subscription_nameRequired Subscription description (1-35 characters). enrollment.subscription.expiration_dateRequired Expiration date in YYYY-MM-DDformat (must be a future date).enrollment.subscription.frequencyRequired Set to ondemand.enrollment.subscription.min_amountRequired Minimum charge amount. enrollment.subscription.max_amountRequired Maximum charge amount. - Enrollment request
Enroll the customer in OVO Recurring using the /ws/userenrollment endpoint.
Sample request
curl -X POST \
--location 'https://sandbox.ebanx.com/ws/userenrollment' \
--header 'Content-Type: application/json' \
--data '{
"integration_key": "{{integration_key}}",
"operation": "enrollment",
"payment_type_code": "ovo-recurring",
"enrollment": {
"merchant_enrollment_code": "{{unique_enrollment_code}}",
"email": "john.doe@example.com",
"phone_number": "6281299221630",
"country": "ID",
"back_urls": {
"success": "https://your-success-url.com",
"failure": "https://your-failure-url.com"
},
"subscription": {
"subscription_name": "{{description}}",
"expiration_date": "{{YYYY-MM-DD}}",
"frequency": "ondemand",
"min_amount": "{{min_amount}}",
"max_amount": "{{max_amount}}"
}
}
}' - Enrollment response
A successful request will return a JSON response like the one below:
{
"status": "SUCCESS",
"redirect_url": "https://sandbox.ebanx.com/ws/redirect/execute?hash=<{hash_here}>",
"enrollment": {
"merchant_enrollment_code": "{{unique_enrollment_code}}",
"country": "ID",
"email": "john.doe@example.com",
"phone_number": "6281299221630",
"back_urls": {
"success": "https://your-success-url.com",
"failure": "https://your-failure-url.com"
},
"subscription": {
"subscription_name": "{{description}}",
"expiration_date": "{{YYYY-MM-DD}}",
"frequency": "{{frequency}}",
"min_amount": "{{min_amount}}",
"max_amount": "{{max_amount}}"
}
}
}Important notes about enrollment- On-demand frequency provides merchants with the flexibility to initiate charges at any time within the subscription validity period, without being restricted to a fixed billing schedule.
- The enrollment request does not trigger a debit from the customer's bank account. It only serves as a one-time authorization, allowing merchants to initiate future debits according to the subscription parameters.
- Users have 5 minutes to confirm enrollments, after which the enrollment will expire.
Subsequent paymentsSave the
merchant_enrollment_codefor subsequent payment requests. - Confirm the enrollment
As soon as the enrollment is confirmed by the customer in their banking app, the enrollment status changes from
pendingtoaccepted, and a Status Update Notification is sent to the URL defined in your merchant configuration.Notification example:
operation=enrollment_status_change¬ification_type=update&merchant_enrollment_code=99911110104 - Query enrollment status
Before requesting any payments, call the
/ws/userenrollments/queryendpoint using themerchant_enrollment_codeto get the latest status of the enrollment.Sample request
curl -X POST \
--location 'https://sandbox.ebanx.com/ws/userenrollments/query' \
--header 'Content-Type: application/json' \
--data '{
"integration_key": "{{integration_key}}",
"payment_type_code": "ovo-recurring",
"enrollment": {
"country": "id",
"merchant_enrollment_code": "{{unique_enrollment_code}}"
}
}'Sample response
{
"status": "SUCCESS",
"enrollment": {
"status": "accepted"
}
}The response will indicate one of the following values for enrollment status:
accepted- Enrollment approved by the customer.not accepted- Enrollment rejected by the customer.paused- Enrollment temporarily paused.pending- Enrollment awaiting customer action.expired- Enrollment expired.not_found- Enrollment not found.revoked- Enrollment cancelled.
If your enrollment has the status
accepted, you can start requesting recurring payments. - Define payment parameters
After the enrollment is accepted, you can create recurring payment requests. The payment follows the usual standards of
/ws/directpayment requests, with the addition of specific parameters related to enrollment.Parameter Requirement Description integration_keyRequired Your EBANX integration key. operationRequired Set to request.payment.nameRequired Full name of the payer. payment.emailRequired Customer email. payment.phone_numberRequired Customer contact number. payment.countryRequired Set to IDfor Indonesia.payment.payment_type_codeRequired Set to ovo-recurring.payment.merchant_payment_codeRequired Unique code for the payment. payment.currency_codeRequired Set to IDR.payment.amount_totalRequired Payment amount. payment.enrollment.merchant_enrollment_codeRequired Unique identifier associated with the enrollment. - Create payment request
Sample request
curl -X POST \
--location 'https://sandbox.ebanx.com/ws/direct' \
--header 'Content-Type: application/json' \
--data '{
"integration_key": "{{integration_key}}",
"operation": "request",
"payment": {
"name": "John Doe",
"email": "john.doe@example.com",
"country": "ID",
"phone_number": "6281299221630",
"payment_type_code": "ovo-recurring",
"merchant_payment_code": "{{merchant_payment_code}}",
"currency_code": "IDR",
"amount_total": 200,
"enrollment": {
"merchant_enrollment_code": "{{unique_enrollment_code}}",
"email": "john.doe@example.com"
}
}
}'ImportantThe
merchant_enrollment_codeassociated with the enrollment is required for every subsequent charge. - Payment response
A successful request will return a JSON response like the one below. The OVO Recurring payment will have a pending (
PE) status until confirmed.{
"payment": {
"hash": "<{hash_here}>",
"country": "id",
"merchant_payment_code": "{{merchant_payment_code}}",
"order_number": null,
"status": "PE",
"status_date": "{{YYYY-MM-DD HH:mm:ss}}",
"open_date": "{{YYYY-MM-DD HH:mm:ss}}",
"confirm_date": "{{YYYY-MM-DD HH:mm:ss}}",
"transfer_date": "{{YYYY-MM-DD HH:mm:ss}}",
"amount_br": "200.00",
"amount_ext": "200.00",
"amount_iof": "0.00",
"currency_rate": "1.0000",
"currency_ext": "IDR",
"due_date": "{{YYYY-MM-DD}}",
"instalments": "1",
"payment_type_code": "ovo-recurring",
"pre_approved": false,
"capture_available": null,
"customer": {
"email": "john.doe@example.com",
"name": "John Doe",
"birth_date": "{{YYYY-MM-DD}}"
},
"single_transaction": {
"amount_local": "0.00",
"amount_crossborder": "100.00"
},
"currency_ext_base": "IDR"
},
"status": "SUCCESS"
}Billing engineEBANX does not offer a recurrent billing engine. Merchants are required to maintain their own charge schedules.
- Monitor payment for status changes
Notifications
-
EBANX will send a notification whenever a payment status changes.
-
Make sure your system is set up to receive notifications from EBANX for any changes in payment status.
Status
-
After receiving a notification that the status has changed, retrieve the payment status.
-
When a payment is confirmed, the status will change from pending (PE) to confirmed (CO).
-
- Congratulations!
You have successfully integrated OVO Recurring.
For more information, refer to theDirect API reference guidechevron_right
Error Scenarios
This section outlines potential errors that may occur during enrollment creation and recurring payment requests in OVO Recurring. These are synchronous error scenarios triggered by EBANX, in accordance with the product business rules and required fields.
| EBANX Code | EBANX Message | Details |
|---|---|---|
BP-UE-18 | Field enrollment.subscription.expiration_date must be a future date | Incorrect expiration date. |
BP-UE-03 | Field enrollment.email or enrollment.phone_number is required | Mandatory field is missing. |
BP-UE-17 | Field enrollment.subscription.min/max amount is required. | Min/max amount is blank. |
BP-UE-30 | The field subscription_name size must be between 1 and 35 characters. | Subscription name character limit exceeded. |
BP-UE-23 | Field enrollment.subscription.frequency is required | Frequency field is blank. |
Cancel Enrollment
Merchants can revoke an active subscription by sending a cancel request with the merchant enrollment code.
Ensure enrollment status is Pending or Accepted
You can only cancel an enrollment if its status is pending or accepted. You can check the status using the /ws/userenrollments/query endpoint referencing its merchant_enrollment_code.
Sample request
curl -X POST \
--location 'https://sandbox.ebanx.com/ws/userenrollments/query' \
--header 'Content-Type: application/json' \
--data '{
"integration_key": "{{integration_key}}",
"payment_type_code": "ovo-recurring",
"enrollment": {
"country": "id",
"merchant_enrollment_code": "{{unique_enrollment_code}}"
}
}'
Sample response
{
"status": "SUCCESS",
"payment_type": "ovo-recurring",
"enrollment": {
"status": "accepted",
"email": ""
}
}
Enrollments with a status of accepted or pending are eligible for cancellation. Other possible enrollment statuses include expired, not_found, and revoked, none of which can be cancelled.
Cancel the enrollment
To cancel an enrollment, call the /ws/userenrollment endpoint (from your server) with the following required fields:
| Parameter | Requirement | Description |
|---|---|---|
integration_key | Required | Your unique and secret integration key. |
operation | Required | Must be cancel. |
payment_type_code | Required | Must be ovo-recurring. |
enrollment.country | Required | Must be ID. |
enrollment.merchant_enrollment_code | Required | The unique enrollment identifier. |
Sample request
curl -X POST \
--location 'https://sandbox.ebanx.com/ws/userenrollment' \
--header 'Content-Type: application/json' \
--data '{
"integration_key": "{{integration_key}}",
"operation": "cancel",
"payment_type_code": "ovo-recurring",
"enrollment": {
"merchant_enrollment_code": "{{unique_enrollment_code}}",
"email": "john.doe@example.com",
"country": "ID"
}
}'
Sample response
A successful request will return a JSON response with a status of revoked.
{
"status": "SUCCESS",
"payment_type": "ovo-recurring",
"enrollment": {
"status": "revoked"
}
}
Resources
Use the following resources when testing in your sandbox environment.
API Reference
Click here to access detailed API documentation to integrate efficiently.
Mock Customer Data
Click here to view mock customer data for testing and validating user flows.
Error Codes
Click here to review common error codes to troubleshoot and resolve issues quickly.
Still need help?
We hope this article was helpful. If you still have questions, you can explore the following options:
- Merchant support: Contact our support team at sales.engineering@ebanx.com for assistance.
- Not a partner yet? Please complete the Merchant Signup Form, and our commercial team will reach out to you.