6.1. LinkPay Early Access


This chapter includes information about features or aspects of the platform that are deemed Early Access.

Early Access features has added stability and will not encounter breaking changes, offering a backward compatible API Schema.

Certain Early Access features may not be accessible to all Stitch users by default. These features can be enabled on a per-client basis on request.


LinkPay enables clients to tokenize user bank accounts for the purpose of faster-returning payments. Similar to card tokenization, LinkPay enable a connection between the end user and client bank account. This connection allows for payments to be made without presenting the user with the Stitch interface after an account has been linked (unless a user interaction such as multifactor authentication is required).

This payment type is recommended for fintech-driven use-cases such as wallet funding, investments, and other experiences where tokenization or account linking would be beneficial for reducing conversion hurdles over time for repeat users.

LinkPay may also be used in concert with the data product, allowing you to verify that the user's identity and account information matches the details you have on file. This enables you to mitigate fraud and prevent deposits from bank accounts that do not match the on-file KYC you have for a customer.

Understanding the Integration Process

Integration Process

  1. Retrieve client token
  2. Create payment authorization request
  3. Present user with authorization flow
  4. Retrieve user tokens
  5. Check authorization status
  6. Initiate payment
  7. Handle user-interaction and payment errors
  8. Subscribe to webhooks

In LinkPay, a payment authorization request represents a resource created that allows users to authorize and set up payments to a specific beneficiary.

A client token is needed to create a payment authorization request. A client token can be obtained by following the client token guide, making sure to request the client_paymentauthorizationrequest scope.

Once the authorization request has been completed, you obtain a user token which can be used to initiate payments at any time, using the userInitiatePayment mutation on the Stitch API. If no user interaction is required, the payment will complete instantly. However, if an interaction such as multifactor authentication is necessary, then the user may be presented with a web interface within your application, allowing them to complete the payment after supplying the required input.

This flow has been summarized in the diagram below:

LinkPay Flow Overview

Postman Collection

The above integration has been demonstrated in the Postman collection available for download here. Please import and review the collection's documentation, supplying the variables where required.

Creating a payment authorization request

Once you have created a client token, you are able to use it to create the payment authorization request. An example mutation demonstrating the creation of the authorization request may be seen below.

Note that the two references provided on payer and beneficiary reflect the reference that will appear on the payer and beneficiary's statement respectively.

The payer field requires that email and contact number are provided.

The result of this mutation returns the authorizationRequestUrl, which is the URL that replaces the default URL used in the user authorization flow. If you wish to issue disbursements to the user's linked account. See the disbursements guide here.

There is also the option of including an initial payment from the user when they go through the initial linking flow. This can be done by including the initialPayment field inside the mutation input:

1mutation CreatePaymentAuthorizationRequest {
2 clientPaymentAuthorizationRequestCreate(input: {
3 ...
4 initialPayment: {
5 amount: {
6 quantity: "1", currency: "ZAR"
7 }
8 }
9 }

Initiate Payment

Once you have obtained a user token, you can use the token to initiate a payment. An example query that initiates a payment can be seen below. The external reference field may be used to correlate transaction IDs within your system with the payments initiated by Stitch.

Handling user-interaction required

Similar to card, with 3D Secure, there are instances where a payment cannot complete without user interaction. This might be because the bank requires that a multifactor challenge be completed before the payment is processed, or that the user needs to accept a prompt, such as updated terms and conditions, on their account.

In this case, the payment initiation mutation will return an error, as well as a payment URL. The user will need to be redirected to this URL in order to complete the payment. The URL returned by the API requires that a whitelisted redirect_uri is appended to it as a query string argument. An example of this response can be found below:


Link the test data Capitec account to simulate this response when using a test client.

2 "errors": [
3 {
4 "message": "Multifactor Required to continue payment.",
5 "extensions": {
7 "redirectUrl": ""
8 },
9 "locations": [
10 {
11 "line": 4,
12 "column": 23
13 }
14 ],
15 "path": [
16 "userInitiatePayment"
17 ]
18 }
19 ],
20 "data": {
21 "__typename": "Mutation",
22 "userInitiatePayment": null
23 }

Directing users to complete a user-interaction

The URL returned by the API requires that a whitelisted redirect_uri is appended to it as a query string argument. If you direct a user to this URL, they will be guided through the process of completing the payment.

For example, if your whitelist included the URL for payment requests, you'd append the following query string to the url returned from the API: ?


To add or remove a URL from the whitelist, please reach out to a Stitch Engineer via the usual support channels on Slack or our Support Form.

Handling the user-interaction callback

Once the user completes or cancels the user-interaction request, they'll be redirected back to the redirect_uri. The redirect uri will be passed three query string parameters.

Payment Request Callback Query Parameters
idThe unique id of this payment requestID
statusStatus will have the value "complete" if successful or "closed" if the user clicked close in the UIString
externalReferenceThe value that was provided to the externalReference field when the payment was initiated.String

The id can be used to retrieve payment details from the Stitch API and relate to incoming payment completion webhooks.

Handling payment failed errors

An example of a failed payment response can be found below:

2 "errors": [
3 {
4 "message": "Payment failed because insufficient funds were available.",
5 "locations": [
6 {
7 "line": 4,
8 "column": 23
9 }
10 ],
11 "path": [
12 "userInitiatePayment"
13 ],
14 "extensions": {
15 "code": "PAYMENT_FAILED",
16 "reason": "insufficient_funds"
17 }
18 }
19 ],
20 "data": {
21 "__typename": "Mutation",
22 "userInitiatePayment": null
23 }
Possible Payment Errors

Payment Error Reasons

This table describes the reasons you may encounter within the PAYMENT_FAILED error:

Payment Failed Error Reasons
bank_errorPayment failed because a bank error has occurred.
blockedPayment failed due to blocked account.
declinedPayment has been declined.
duplicate_paymentPayment failed because a duplicate payment has already occurred.
invalid_destination_accountPayment failed due to an invalid destination account.
invalid_source_accountPayment failed due to an invalid source account.
limits_exceededPayment failed due to account limits exceeded.
limits_not_metPayment failed due to payment minimum not met.
readonly_account_errorPayment failed as this account is read only.
timeoutPayment failed due to a timeout.
payment_pendingError marking payment as complete. Please contact the Stitch team if you encounter this error.
unknownPayment failed due to an unknown error.

Checking Authorization Status

In certain scenarios you may want to proactively check the status of a payment link, and/or retrieve information about the bank account it is linked to, before initiating a payment. In these cases you can query the paymentAuthorization on the user field.


This may trigger a login notification in the user's banking app.

If the status returns "valid", the link to the user's account is active. Alternatively, you may receive a REAUTHORIZATION_REQUIRED response. In this case you may ask the user to login again by redirecting them to the URL in the response, as per the reauthorization guide. Alternatively, you could simply attempt to initiate a payment and handle any USER_INTERACTION_REQUIRED response.

Receiving webhooks on payment completion

To receive a webhook upon payment completion you will need to create a subscription for your client. Please see our documentation on webhook subscriptions for information on how to do so.

Viewing all initiated payments

To view the collection of initiated payments, you may query the Client.paymentInitiations field on the API. This will return a paged collection of initiations, dated from most recent to least.

Retrieving a payment request status

When a user has successfully initiated the payment, the state will be PaymentInitiationRequestCompleted and contain details of the payment, including all references and the specific beneficiary the payment was made to.

To retrieve the status of a payment request, as described above, you'll need a client token with the client_paymentrequest scope.