Skip to main content

Variable Payment Consents

For any variable recurring payments to be captured from a user, a consent must first be created and then authorised by the user, in order for it to be subsequently charged.

Based on your use-case, you may require to initiate a variable once-off, or variable recurring consent request.

A typical flow would involve the following steps:

  • A consent is created, with a specified frequency (such as monthly, or once-off), corresponding amount details, and user details.
  • The user is redirected to Stitch to initialise the consent request, and then approves bank authorization for the payment instruction, in their Capitec app.
  • The user is redirected back to the merchant platform, and the granted (successul) consent status is confirmed with a webhook notification from Stitch.
  • Once a consent is granted, charges may be made to debit the user. Transaction frequency and amounts must be in accordance with the granted consent terms.

A Payment Consent Request can be created using the paymentConsentRequestCreate mutation. Payment Consent Request creation requires a client token with the client_recurringpaymentconsentrequest scope. Follow the steps described in the client token guide to obtain a client token.

The GraphQL API URL https://api.stitch.money/graphql can be used for all consent requests (whether on test or live clients).

Two different types of Variable Payment Consent Requests exist: Once-off, and Recurring. Payment schedule details and possible amounts distinguish these two types.

Base Request Fields

For all types of Variable Consent Requests, the following mutation input fields apply:

FieldDescriptionTypeRequired
paymentMethods.capitecPay.enabledThis must be set to true to enable the Capitec VRP method for the consent request.BooleanYes
paymentMethods.capitecPay.paymentDescriptionA descriptive field for the consent, displayed to the user on their Capitec app during authorization.StringYes
payerInformationThe user's details as per your system. At a minimum, payerId (a unique payer identifier on your system) and mobileNumber are required within this object.PayerInformationYes
nonceA unique value, that may only be used once to ensure the uniqueness of the consent request.StringYes
User Authorization

To create a Payment Consent Request with Capitec Pay, the user will require one of the following payerInformation fields, when authorizing:

  • South African identity number, as registered with Capitec,
  • Mobile phone number, as registered with Capitec, or
  • Capitec bank account number.

Temporary residence numbers and passports are not currently supported.

The mutation to create a variable once-off consent request is shown below:

Specific fields applicable for Once-off Consents (within the capitecPay method, and in addition to the base fields) are as follows:

FieldDescriptionTypeRequired
paymentSchedule.frequencyThis must be set to ONCE_OFF to create a variable once-off request. This frequency will be displayed to the user on their mobile banking app.EnumYes
paymentOptions.variable.maxThis is the maximum amount for all combined charges on the consent. Displayed to the user on their Capitec app.MoneyYes
paymentOptions.tipOptions.amountThis is the tip amount that applies to the consent (included as part of the maximum amount). Displayed to the user on their Capitec app.MoneyOptional
Note

The tip amount specified on the consent is simply a UI feature, and is presented to the user on their Capitec banking app for approval.

An example mutation to create a variable consent request is shown below:

Payment Variability

The above mutation specifies a fixed recurring payment. However, a variable payment can be configured by specifying the paymentOptions.variable.max property instead.

Specific fields applicable for Recurring Consents (within the capitecPay method, and in addition to the base fields) are as follows:

FieldDescriptionTypeRequired
paymentSchedule.frequencyThis must be set to the expected frequency of transaction charges for the consent, and may be DAILY, WEEKLY, MONTHLY, or YEARLY. This frequency will be displayed to the user on their Capitec app during authorisation.EnumYes
paymentOptions.fixed.amountThis an amount that would be fixed per future transaction charged on the consent.MoneyYes, if a variable amount is not specified.
paymentOptions.variable.maxDefines a maximum amount for a variable recurring amount. Displayed to the user on their mobile banking app.MoneyYes, if a fixed amount is not specified.

Handle Interaction URL

The redirect URL returned by the API requires that a redirect_uri is appended as a query string parameter. Once a user is redirected to this URL, they will be guided through the process of authorising the consent request.

For example, if your allowlisted URL configuration included the URL https://example.com/subscription, you'd append the following query parameter to the url value returned from the API: &returnUrl=https://example.com/subscription. The full URL you expose to the user would then look like this:

https://secure.stitch.money/v2/consent?requestId=2b068bd5-6a5a-42e1-8a45-673cb3ede612&
clientId=test-195944A9-E957-4532-B574-D37BD5FD9297&
returnUrl=https://example.com/subscription
danger

The URL specified as the redirect_uri must be secure i.e. an HTTPS URL.

When the user completes or cancels the consent request, they'll be redirected back to the redirect_uri. The below query string parameters will be passed back to the redirect_uri.

ParameterDescriptionType
idThe unique consent ID of this payment consent request.ID
statusStatus will have the value complete if successful, closed if the user clicked close in the UI, or failed if something went wrong while authorizing.String

The id can be used to retrieve the final consent status and other details from the Stitch API, as well as relate to incoming webhooks.

Handling Granted Consents

When a user approves the consent, it will move into a PaymentConsentGranted state. You will a receive a webhook to notify you of this status change. At this point, you may proceed to initiate transactions using the respective consent request ID as the token.

If a user chooses to remove their consent from your platform, you should revoke the consent request so that it is no longer possible to initiate transactions from their account.

A Payment Consent Request can be revoked directly via the Stitch API. A revocation would result in a Payment Consent Request with a status of PaymentConsentRevoked. The Payment Consent Request would be inactive and any payment attempts against it would fail.

In order to revoke a Payment Consent Request, you need to call the paymentConsentRequestRevoke mutation as detailed below:

The table below describes the fields detailed in the above mutation.

NameDescriptionType
idThe unique id of the original payment consent request ID as returned by the Stitch API when you create a payment consent request.ID
reasonThe reason for revoking the payment consent request. The revocation reason supplied needs to be one of the reasons as indicated in the "Reason" column below.String
ReasonDescription
CONTRACT_TERMINATEDThe contract has been terminated.
FRAUDRevoked due to fraud related activity by the user.
GENERALGeneral cancellation that isn't for one of the aforementioned reasons.
note

A Payment Consent Request can only move to a PaymentConsentRevoked status from a PaymentConsentGranted status.

A Payment Consent Request that has been created, and is still pending, can be cancelled in order to prevent a user from granting their consent on the current request. This can be done by executing the paymentConsentRequestCancel mutation with a consent ID and a reason. This is different to revocation in that a user has not previously granted consent to the recurring payment. See the status descriptions in the table below for more information.

An example of a cancellation mutation is shown below:

Payment Consent Request statuses can be queried directly or obtained via a subscription to the webhooks.

StatusDescription
PaymentConsentPendingThe initial status after creation via the API.
PaymentConsentGrantedThe consent request was authorised by the user, and can be charged against.
PaymentConsentCancelledThe consent request has been cancelled while it was still pending, before it was authorised.
PaymentConsentRevokedThe consent request was revoked and cannot be charged against.

While we encourage the use of webhooks for obtaining status updates, as they are immediate and don't require polling, the following query is an example of fetching a payment consent request by ID to obtain the status.

Below is a diagram depicting the possible Payment Consent Request Statuses

Subscribe to Webhooks

Webhooks for updates on consent requests can be subscribed to by running the following mutation:

If the webhook subscription is successfully created, the body returned by the request will look similar to the sample in the Example Response tab in widget above.

For more information on receiving webhook events, listing active webhook subscriptions, unsubscribing from webhooks and validating signed webhook subscriptions, please visit the Webhooks page.

Webhook Statuses

The payment-consent-request webhook will be dispatched for each of the following status updates:

  • PaymentConsentProcessing
  • PaymentConsentFailed
  • PaymentConsentGranted
  • PaymentConsentCancelled
  • PaymentConsentExpired
  • PaymentConsentRevoked
Example Variable Consent Request Payload
{
"clientId": "test-950f1098-dacf-4105-9958-c2319ab1a0bb",
"data": {
"createdAt": "2025-07-03T13:09:45.929+00:00",
"id": "cGF5bWVudGNvbnNlbnRyZXF1ZXN0LzhmZjA2YWE0LWZkMzYtNDFlYi05NTlmLTQ0ZDQ0OTYyYzhlNA==",
"status": "GRANTED",
"type": "CAPITEC_PAY_RECURRING",
"updatedAt": "2025-07-03T13:09:55.955+00:00"
},
"datetime": "2025-07-03T13:09:55.975Z",
"id": "cGF5bWVudGNvbnNlbnRyZXF1ZXN0LzhmZjA2YWE0LWZkMzYtNDFlYi05NTlmLTQ0ZDQ0OTYyYzhlNA==",
"type": "payment-consent-request"
}

Testing and Simulation

When using a test client, the default flow will result in a PaymentConsentGranted status, and the default transaction result will be successful. However, it is possible to simulate other outcomes.

Simulated Statuses

Payment consent request scenarios can be simulated by configuring the paymentDescription when creating the payment consent request.

paymentDescription valueScenarioConsent status outcome
successSimulates the user accepting the recurring payment in-app prompt. This is the default successful scenario, the same as if the field was left empty.PaymentConsentGranted
timeoutSimulates the user not responding to in-app prompt before the request expires. The user may be able to retry.PaymentConsentPending
declinedSimulates the user declining the in-app prompt on their device.PaymentConsentPending
clientTransactionLimitExceededSimulates the user not being able to authorise the consent due to transaction limits set in the Capitec app.PaymentConsentPending
clientAppNotFoundSimulates the user not being able to authorise the consent due to not having the Capitec app installed.PaymentConsentPending
clientDeactivatedSimulates the user not being able to authorise the consent due to a deactivated Capitec account.PaymentConsentPending
clientBlockedMerchantSimulates the user not being able to authorise the consent due to blocking the merchant on the Capitec app.PaymentConsentPending
clientNotFoundSimulates the user not entering a valid identifier for a Capitec account.PaymentConsentPending