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