Skip to main content

Variable Recurring Consents

For any 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.

A Capitec Pay recurring payment can be created by creating a Stitch Payment Consent Request with the Capitec Pay method enabled. When creating a Payment Consent Request with the Capitec Pay method, detailed information about the user and the recurring payment is required. The user will be prompted to authorise the consent as per the provided details. Once authorised, the Payment Consent Request status will move to the PaymentConsentGranted status, and you can initiate a charge against the consent.

The below high-level diagram depicts Payment Consent Request creation on the Stitch API. The outcome of the Payment Consent Request creation is a redirect URL and a consent ID. After authorisation by the user, the Payment Consent Request will be in a PaymentConsentGranted status. The consent ID can then be used to invoke future payments.


  • Creating the Payment Consent Request,
  • Redirecting the user, and
  • Handling the resulting redirect, with webhook.

A Payment Consent Request can be created using the below 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.

To create a Payment Consent Request with Capitec Pay enabled, information about the user and the collection is required. A redirect URL will be returned for you to surface to your user, allowing them to provide any outstanding details, and to authorise the recurring payment.

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

Payment Variability

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

Request Fields

The table below describes the fields that can be populated when creating a payment request.

NameDescriptionType
nonceA nonce is a generated, unique, random value that can only be used once to ensure the uniqueness of the request.String
externalReferenceOptional value that will be returned in the redirect URL and on queries after the user grants consent.String
paymentOptionsCan be used to define whether the user will be charged a fixed, or variable recurring amount.Object
paymentOptions.fixedDefines a fixed recurring amount.Money
paymentOptions.variable.maxDefines a maximum amount for a variable recurring amount. Displayed to the user on their mobile banking app.Money
paymentSchedule.startThe date the payment consent will be active, and can be charged against. Displayed to the user on their mobile banking app.Date (ISO-8601)
paymentSchedule.frequencyIndicates how often the collection will occur. This can be ONCE_OFF, DAILY, WEEKLY, MONTHLY, or YEARLY. Displayed to the user on their mobile banking app.Enum
paymentDescriptionThe description displayed to the user on their banking app.String
payerInfo.identifyingDocumentThe user's valid South African identity number, as registered with Capitec.IdentifyingDocument
payerInfo.mobileNumberThe user's mobile number, as registered with Capitec.String
payerInfo.bankAccountNumberThe user's Capitec account number.String
User Authorization

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

  • South African identity number
  • Mobile phone number
  • Capitec account number

Temporary residence numbers and passports are not currently supported.

Handle Interaction URL

The redirect URL returned by the API requires that an allowlisted returnUrl is appended as a query string parameter. If a user is redirected to this URL, they will be guided through the process of authorising the consent request. For test clients, the following URLs are allowlisted by default:

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
Allowlisting Redirect URLs

To add or remove a URL from the allowlist, please reach out to the Stitch team.

Please note that production clients will not be allowed to use unsecure returnUrl parameters such as http.

http://example.com/subscription

https://example.com/subscription

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

Request FieldDescriptionType
idThe unique 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
externalReferenceThe externalReference that was used when creating the consent request, if it was provided.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.

danger

The status field should not be used for any database operations since an external party can alter it before redirecting. To secure yourself from attackers who can send a fake payload to your redirect or webhook endpoint, we recommend:

  1. using the webhooks as the source of truth as they are secure and will always be sent from Stitch.
  2. making use of signed webhooks to verify the signature of each incoming webhook's payload.

Using the webhooks also ensures you'll always be able to know the final status of a payment consent request. If for example the request times out due to a network issue.

Handling Granted Consents

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

In the case that a subscription has ended, or 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, or by a user revoking consent in their banking app. 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.
PaymentConsentExpiredThe consent request has expired 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

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
maxTransactionLimitExceededSimulates the user not being able to authorise the consent due to Capitec maximum transaction amount limit.PaymentConsentFailed
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
clientBlockedMerchSimulates 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
duplicateConsentSimulates the user not being able to authorise the consent due to an existing duplicate consent that has already been authorisedPaymentConsentFailed