Rest API
Stitch provides an alternative REST interface to create payment requests for different payment methods. View the relevant guide for complete information on each payment method integration, including handling interaction URLs/redirects and webhooks.
Integration Overview
Follow the steps described in the client token guide to obtain a client token with the client_paymentrequest scope.
Use the Stitch REST API URL https://api.stitch.money/v2 for all requests on test and live clients. Standard HTTP status conventions are used for all API responses.
Payment Request Creation
A POST request is used to create a payment request for one or more payment methods. The payment request allows you to specify the amount, merchant details, payer information, and any other relevant references. The paymentMethods object indicates which payment methods are enabled and includes any method-specific information required to process the payment
The payerInformation object should be specified with stored information on the payer. The provided information is used to increase the efficacy of fraud risk checks done by Stitch. At a minimum, the payerId should always be specified within a request.
Initiate a POST request to create a token with the following request body:
curl -X POST 'https://api.stitch.money/v2/payment-requests' \
-H 'Content-Type: application/json' \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-d '{
"amount": {
"currency": "ZAR",
"quantity": 1
},
"externalReference": "TestPayment",
"expireAt": "2025-12-31T00:00:00Z",
"payerInformation": {
"payerId": "PAYER-001",
"identifyingDocument" {
"type": "identity_document",
"country": "ZA",
"number": "0401016727083"
},
"mobileNumber": "0711234567",
"email": "hello@stitch.money",
"fullName": "Lilo Pelekai"
},
"metadata": {
"deliveryMethod": "delivery"
}
"paymentMethods": {
"eft": {
"enabled": true,
"payerReference": "PayerReference",
"beneficiaryReference": "Stitch",
"beneficiary": {
"name": "Lilo",
"bank": "absa",
"accountNumber": "123456789"
},
"capitecPay": {
"enabled": true
},
"absaEft": {
"enabled": true
},
},
"card": {
"enabled": true
},
"crypto": {
"enabled": false
}
}
}'
| Field | Type | Description | |
|---|---|---|---|
amount.currency | string | The payment request currency. Possible values: ZAR | |
amount.quantity | numeric | The payment request value. | |
externalReference | string (optional) | A custom unique identifier associated with the request | |
expireAt | string | An ISO 8601 date that defines the expiration for the request | |
paymentMethods | object | An object specifying the payment methods enabled and their configuration. | |
metadata | object | Used for additional metadata relating to the request. Nested objects must be stringified JSON objects. |
Payer Information Fields
| Field | Type | Description | |
|---|---|---|---|
payerId | string (optional) | The client's internal identifier for the payer. | |
identifyingDocument | object (optional) | The payer's identification document. Required for Capitec Pay Verified Flow. | |
identifyingDocument.type | string (optional) | Type of identifying document. Possible values: identity_document, passport, temporary_residence. | |
identifyingDocument.country | string (optional) | The country code of the document (e.g., ZA). | |
identifyingDocument.number | string (optional) | The document number. | |
mobileNumber | string (optional) | The payer's contact number. | |
email | string (optional) | The payer's email address. | |
fullName | string (optional) | The payer's full name. | |
accountCreatedDate | string (optional) | The ISO date when the payer's account was created with the client. |
Payment Method Fields
Note that Pay by Bank is enabled on payment requests by default. Set paymentMethods.eft.enabled to false to create a payment request without Pay by Bank enabled. Capitec Pay and ABSA Pay require that eft is enabled and must be explicitly enabled.
eft Fields
| Field | Type | Description | |
|---|---|---|---|
eft | object (optional) | Pay by Bank payment method configuration. Enabled by default. | |
eft.enabled | boolean (optional) | Whether Pay by Bank is enabled. Defaults to true. | |
eft.payerReference | string (optional) | The payer's bank statement reference. Required for Pay by Bank. | |
eft.beneficiaryReference | string (optional) | The beneficiary's bank statement reference. | |
eft.beneficiary | object (optional) | The beneficiary's destination account. Required for Pay by Bank. | |
eft.beneficiary.name | string | The account holder's name. | |
eft.beneficiary.bank | string | The beneficiary’s bank. Must be a valid BankBeneficiaryBankId value. | |
eft.beneficiary.accountNumber | string | The beneficiary's account number. | |
eft.capitecPay | object (optional) | Configuration for Capitec Pay (when supported). | |
eft.capitecPay.enabled | boolean (optional) | Whether Capitec Pay is enabled. Defaults to false. | |
eft.absaEft | object (optional) | Configuration for ABSA Pay (when supported). | |
eft.absaEft.enabled | boolean (optional) | Whether ABSA Pay is enabled. Defaults to false. | |
card Fields
| Field | Type | Description | |
|---|---|---|---|
card | object (optional) | Card payment method configuration. | |
card.enabled | boolean (optional) | Whether card payments are enabled. Defaults to false. | |
crypto Fields
| Field | Type | Description | |
|---|---|---|---|
crypto | object (optional) | Cryptocurrency payment method configuration. | |
crypto.enabled | boolean (optional) | Whether crypto payments are enabled. Defaults to false. | |
The response includes the payment request id, status and relevant request information.
{
"id": "cGF5cmVxLzNiOTU1MDYwLWJkMTAtNGI1Mi05ZGMyLTg1OTE3OWJkMDIwOA==",
"amount": {
"currency": "ZAR",
"quantity": 1
},
"externalReference": "TestPayment",
"expireAt": "2025-12-31T00:00:00",
"status": "pending",
"url": "https://secure.stitch.money/connect/payment-request/3b955060-bd10-4b52-9dc2-859179bd0208"
}
Surface URL and Handle Callback
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 test clients, we
do have the following URLs whitelisted by default:
- https://localhost:8080
- https://localhost:8080/return
- https://localhost:3000
- https://localhost:3000/return
- https://localhost:9000
- https://localhost:9000/return
For example, if your whitelist URL configuration included the URL https://example.com/payment for payment requests,
you'd append the following query string to the url returned from the API: ?redirect_uri=https%3A%2F%2Fexample.com%2Fpayment.
The full URL you expose to the user should look like this
https://secure.stitch.money/connect/payment-request/3b955060-bd10-4b52-9dc2-859179bd0208?
redirect_uri=https%3A%2F%2Fexample.com%2Fpayment
To add or remove a URL from the whitelist, please reach out to the Stitch team.
Please note that production clients will not be allowed to use unsecure redirect_uri params such as http. For example:
Once the user completes or cancels the payment request, they'll be redirected back to the redirect_uri.
The below query string parameters will be passed back to the redirect_uri.
| Field | Description | Type |
|---|---|---|
| id | The unique Stitch ID | string |
| status | Status will have the value complete if successful, closed if the user clicked close in the UI, or failed if something went wrong when attempting the payment | string |
| externalReference | The optional unique identifier supplied in the POST request. It can be used to correlate transaction IDs within your system with the payment request initiated by Stitch | string |
The id can be used to retrieve the payment request status and other data from the Stitch API.
Using Multiple Internal Redirect URIs
For a situation where different callbacks lead to different internal URLs, you SHOULD have a single whitelisted redirect URL which can then have the logic handling the Stitch callback and redirect to the internal URLs. An overview of how to do this in NodeJS is as shown below:
const status = params.status;
switch (status) {
case "complete":
redirect("/eft-success");
case "closed":
case "failed":
redirect("/eft-retry");
default:
break;
}
Payment Request Expiry
It is highly recommended that an expireAt field is supplied in the request body. At the specified
date and time, the payment request status will automatically transition to state expired if the payment request is not yet completed.
Payment Request Statuses
The table below describes the different statuses for a payment request. A payment request is created with status pending.
| Status | Description |
|---|---|
| completed | The user has completed the payment and is a final state. |
| pending | The user hasn't yet completed the payment initiation request, or they exited Stitch SafeLink before fulfilling the payment. |
| cancelled | The payment request was manually cancelled by the client. |
| expired | The payment request has expired while awaiting user interaction. |
Retrieving Payment Request Status
Initiate a GET request to retrieve a specific request by ID:
curl -X GET 'https://api.stitch.money/v2/payment-requests/cGF5cmVxLzNiOTU1MDYwLWJkMTAtNGI1Mi05ZGMyLTg1OTE3OWJkMDIwOA==' \
-H 'Content-Type: application/json' \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
The response object is identical in structure to the one returned by the POST request used to create a payment request.
{
"id": "cGF5cmVxLzNiOTU1MDYwLWJkMTAtNGI1Mi05ZGMyLTg1OTE3OWJkMDIwOA==",
"amount": {
"currency": "ZAR",
"quantity": 1
},
"externalReference": "TestPayment",
"expireAt": "2025-12-31T00:00:00",
"status": "completed",
"url": "https://secure.stitch.money/connect/payment-request/3b955060-bd10-4b52-9dc2-859179bd0208"
}
Payment Request Cancellation
Payment requests that are not completed or expired i.e. in a terminal state can be cancelled before fulfilment.
Cancelled payment requests are not processed nor can be processed and have a cancelled status. Note that a payment request with an in-flight transaction cannot be cancelled.
Initiate a POST request to cancel a payment request with the following request body:
curl -X POST 'https://api.stitch.money/v2/payment-requests/cancel' \
-H 'Content-Type: application/json' \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-d '{
"id": "cGF5cmVxLzNiOTU1MDYwLWJkMTAtNGI1Mi05ZGMyLTg1OTE3OWJkMDIwOA==",
"reason": "duplicate_payment"
}'
| Field | Type | Description | |
|---|---|---|---|
id | string | The unique Stitch ID | |
reason | string | The cancellation reason |
The response includes the id of the payment request with status code 200 OK if cancellation is successful. Standard HTTP response codes are returned for non-success scenarios.
{
"id": "cGF5cmVxLzNiOTU1MDYwLWJkMTAtNGI1Mi05ZGMyLTg1OTE3OWJkMDIwOA=="
}
Error Handling
Error handling is communicated through standard HTTP status codes. Each response includes a clear status and message, helping you identify the issue and take the appropriate next steps.
Stitch returns an error response with the following format if a body is applicable for the status code, e.g. 400 BAD REQUEST
{
"title": "Bad Request",
"code": "BAD_USER_INPUT",
"detail": "Invalid beneficiary reference"
}
HTTP Status Codes
| Status Code | Meaning | Description |
|---|---|---|
| 200 | OK | The request was successful. The response body contains the payment request resource. |
| 201 | Created | The payment request was successfully created. The response body contains the new payment request resource. |
| 400 | Bad Request | The request was invalid. For example, a required field is missing or malformed. |
| 401 | Unauthorized | Authentication failed or no valid authentication credentials provided. |
| 403 | Forbidden | The authenticated user does not have permission to perform this action. |
| 404 | Not Found | The requested resource (e.g., disbursement) was not found. |
| 409 | Conflict | There is a duplicate nonce or other conflict with the request. |
| 429 | Too Many Requests | Too many requests have been made in a short period (rate limiting). |
| 500 | Internal Server Error | An unexpected error occurred on the Stitch platform. |