Recurring payments
Collect repeat payments with One API. One consent the customer approves, then merchant-initiated collections that need no further customer action.
On this page12 sections
Build with AI 1 package
A build package is every page for one task, with the API operations they use. Copy the prompt into a coding assistant, or hand it the package itself: slim links to each page, full inlines all of them in one document.
- Take a recurring paymentEverything needed to collect from a customer on a schedule with One API, from the consent the customer gives once through to each collection and the webhook that reports it.
This guide walks you through integrating recurring payments via One API. Recurring payments follow a strict two-step process, a consent request that the customer approves once, followed by merchant-initiated collections that happen silently without any further customer action.
This guide uses the One API, Ozow's recommended API for new integrations. Recurring payments are not available on the older Payments API.
Limited availability
Recurring payments are available to approved merchants only. Contact your account manager or support@ozow.com to enquire about eligibility and onboarding.
Before you start
- Recurring payments must be enabled on your merchant profile by Ozow: contact your account manager to confirm this before integrating
- Your One API client must have the
subscriptionsscope, when creating your API client on the Ozow Dashboard, ensure this scope is included. Without it, all subscription endpoints will return an authorisation error - You have completed standard One API authentication setup: see Redirect: One API for the token flow
- If your business operates in a high-risk industry, Customer Identity VerificationCustomer Identity Verification Checking that the payment instrument belongs to the natural person making the payment. Ozow requires it for merchants it has classified as high-risk, on Pay by Bank, Absa Pay, Capitec Pay, Nedbank Direct EFT, FNB Payment Requests and PayShap Request, and can disable those methods where it is not implemented correctly. must be built into the consent step: see Customer Identity Verification
RedirectRedirect Sending the payer to the Ozow payment page to complete the payment, and returning them to your site afterwards. The alternative is embedding the checkout in your own page, where the payer never leaves it. only
The consent step uses a redirect flow. Embedded integration is not supported for recurring payments. Your customer must be redirected to the Ozow-hosted consent page to approve the subscription.
Environments
| Environment | Base URL | Dashboard |
|---|---|---|
| Production | https:/ |
dash.ozow.com |
| Staging | https:/ |
stagingdash.ozow.com |
How it works
Core integration
Step 1: Create a subscription (consent request)
Create a subscription to initiate the consent process. The customer must approve the consent in their Capitec app before any collections can be made.
POST https://one.ozow.com/v1/subscriptions
Authorization: Bearer YOUR_ACCESS_TOKEN
Content-Type: application/json
Request example
{
"siteCode": "YOUR_SITE_CODE",
"paymentMethod": "capitec",
"amount": {
"currency": "ZAR",
"value": 500.00
},
"amountConstraints": {
"min": { "currency": "ZAR", "value": 500 },
"max": { "currency": "ZAR", "value": 600 }
},
"description": "Meal kit",
"merchantReference": "SUB-001",
"bankReference": "MEALKIT",
"frequency": "Monthly",
"firstPaymentDate": "2026-09-01",
"occurrences": 12
}
Key request fields
| Field | Type | Required | Description |
|---|---|---|---|
site |
string | Yes | Your Ozow site codeSite code The unique code for a site registered under a merchant. A site is a place to transact: a website, or a branch of a store. A merchant can have several, and each transaction names the one it belongs to, so sending the wrong code files the payment against the wrong place. |
payment |
string | Recommended | Must be capitec. Always specify this explicitly, when card support is added in future, omitting this field will show a payment method selection screen to the customer |
amount. |
string | Yes | Must be ZAR |
amount. |
number | Yes | The recurring collection amount, at most 2 decimal places. Must fall inside the amount band |
amount |
object | Yes | Lower bound the customer authorises, as currency and value. Whole RandZAR The ISO 4217 code for the South African rand, and the currency every amount on this site is in unless a page says otherwise. Amounts are decimal rand rather than cents, so 100.00 is one hundred rand., no cents |
amount |
object | Yes | Upper bound the customer authorises, as currency and value. Whole Rand, no cents, at most 100000, and greater than min |
description |
string | Yes | What the customer is subscribing to, shown to them. At most 20 characters |
merchant |
string | Yes | Unique reference per subscription used for reconciliation. At most 50 characters, no spaces |
bank |
string | Yes | The reference that appears on your bank statement for each payment. At most 20 characters, letters and numbers only |
frequency |
string | Yes | Collection cadence, Daily, Weekly, Fortnightly, Monthly, Biannually, or Annually |
first |
string | Yes | Date from which collections may begin, today or later. Collections cannot be actioned before this date |
occurrences |
number | Yes | Total number of collections, 1 to 120. For indefinite subscriptions use 120 and create a new subscription when the limit is reached |
payable |
object | No | An immediate first charge, as amount and date. Not bound by amount |
identity |
object | No | Customer identity as type, country, and identifier. Required for high-risk industries: see Customer Identity Verification |
For the full request schema see One API reference.
Successful response
{
"subscriptionId": "00000000-0000-0000-0000-000000000000",
"status": "PendingAuthorization",
"redirectUrl": "https://pay.ozow.com/subscriptions/00000000-0000-0000-0000-000000000000",
"links": {
"self": "https://one.ozow.com/v1/subscriptions/00000000-0000-0000-0000-000000000000",
"cancel": "https://one.ozow.com/v1/subscriptions/00000000-0000-0000-0000-000000000000",
"transactions": "https://one.ozow.com/v1/subscriptions/00000000-0000-0000-0000-000000000000/transactions"
}
}
Store the subscriptionId, you will need it for all subsequent calls.
Step 2: Redirect the customer for consent
Redirect your customer's browser to the redirectUrl returned in the response. The customer will:
- Land on the Ozow payment page
- Enter their Capitec-linked cell phone number
- Approve the consent request in their Capitec app
3-minute window
Capitec allows 3 minutes for the customer to approve the consent request
in their Capitec app. If the customer does not approve within this window, the consent request
lapses and the subscription status changes to Expired. You must create a new subscription and
redirect the customer through the consent flow again.
Once the customer approves, Capitec notifies Ozow and the subscription status updates from
PendingAuthorization to Active. Only then can collections be actioned.
Customer Identity Verification
If your business operates in a high-risk industry, the Customer Identity Verification check must be included in this consent step; not in the action payment step. See Customer Identity Verification for requirements.
Step 3: Action a payment (trigger collection)
Once the subscription is Active and the firstPaymentDate has been reached, trigger a collection
by calling the transaction endpoint.
POST https://one.ozow.com/v1/subscriptions/{subscriptionId}/transactions
Authorization: Bearer YOUR_ACCESS_TOKEN
Content-Type: application/json
Replace {subscriptionId} with the ID returned in Step 1.
Request example
{
"amount": { "currency": "ZAR", "value": 500.00 },
"merchantReference": "SUB-001-SEP"
}
Both fields are required. amount.value must fall inside the amountConstraints band the customer
authorised. merchantReference identifies this individual collection, not the subscription itself.
Pre-conditions
Ozow validates all of the following before processing the collection. The call will be rejected if any condition is not met:
- The subscription exists and has
Activestatus - Today's date is on or after the
firstPaymentDatespecified during consent creation - The number of collections has not exceeded the
occurrenceslimit
The customer does not receive any authentication prompt, the debit happens silently based on the consent already granted.
Step 4: Handle the webhook notification
Ozow sends webhookWebhook A URL of yours that Ozow calls when something happens, rather than you polling to find out. The call carries no credential of yours and arrives at a public URL, so authenticate it before acting on it: a hash field on the Payments API, a Svix signature on One API. notifications for subscription events. Subscribe to these events in your One API client webhook configuration:
| Event | Description |
|---|---|
subscription. |
The customer approved the consent, and the subscription can be collected against |
subscription. |
The consent was not approved |
subscription. |
An individual collection succeeded |
subscription. |
An individual collection failed |
subscription. |
The subscription took all its scheduled occurrences |
subscription. |
The subscription was cancelled. One l, unlike Canceled on the status |
subscription. |
The authorisation lapsed before the subscription became active |
Subscribe to the name exactly as written. An event name the service does not know is rejected, so a subscription to something close is a subscription that never fires.
Important
A subscription webhook is delivered as thin whatever message type you register
it with, so data is the id, status and
reason and nothing more. Fetch the subscription or the
transaction for detail.
Handle these exactly as described in Step 4: Handle the webhook notification in the One API redirect guide, the same Svix signature verification process applies.
Subscription management
| Action | Endpoint | Description |
|---|---|---|
| Get subscription | GET / |
Retrieve details of a specific subscription |
| List subscriptions | GET / |
List subscriptions for a site, filterable by status. site is required |
| Cancel subscription | POST / |
Cancel an active subscription, communicates directly with Capitec to cancel on their side |
| List transactions | GET / |
List all collections made under a specific subscription |
Cancellation
Cancelling a subscription communicates directly with Capitec and cancels the consent on their side. This action cannot be undone. No further collections will be possible after cancellation.
Subscription statuses
| Status | Description |
|---|---|
Pending |
Subscription created, customer has not yet approved consent in the Capitec app |
Active |
Customer has approved consent, collections can now be actioned |
Canceled |
Subscription cancelled, no further collections possible |
Completed |
All scheduled occurrences have been collected |
Expired |
The authorisation lapsed before the subscription became active, create a new subscription |
Failed |
The subscription could not be established or sustained |
Unknown |
The status could not be determined |
Note
Canceled uses a single l. An individual collection carries its own status,
Pending, Successful, or Failed.
Go-live checklist
Next steps
- Review the Building a secure integration checklist before going live
- See the One API reference for the full subscription endpoint specifications
- Contact support@ozow.com to confirm recurring payments are enabled on your merchant profile
In the API reference
13 entries
- POST
/tokenGenerate Authentication Token One API - POST
/subscriptionsCreate Subscription One API - GET
/subscriptions/{subscriptionId}Get Subscription by Id One API - POST
/subscriptions/{subscriptionId}/transactionsCreate Subscription Transaction One API - POST
/subscriptions/{subscriptionId}/cancelCancel Subscription One API - POST Ozow sends your notification URLSubscription consent approved One API
- POST Ozow sends your notification URLSubscription consent not approved One API
- POST Ozow sends your notification URLSubscription collection succeeded One API
- POST Ozow sends your notification URLSubscription collection failed One API
- POST Ozow sends your notification URLSubscription completed One API
- POST Ozow sends your notification URLSubscription cancelled One API
- POST Ozow sends your notification URLSubscription expired One API
- SchemaWebhookEventData One API
Last updated