Managing Wallets
For Enterprise partners, the ability to issue and manage wallets is the core of the "Closed Loop" ecosystem. This allows you to create digital accounts for your users (students, parents, staff) and manage the funds within them.
1. Creating a Wallet
To issue a new wallet, make a request to the API. This creates a "Partner Wallet" which is owned by your organization but assigned to a specific user entity.
Endpoint: Create Wallet
Body (optional):
{
"rsaIdNumber": "9001015009087"
}
| Field | Requirement | Description |
|---|---|---|
rsaIdNumber | Optional | The wallet holder's 13 digit South African ID number. An empty body creates a plain partner wallet. |
Supplying an ID number
When you supply rsaIdNumber, Sticitt uses it to connect the wallet to the holder's Sticitt profile automatically:
- Once a Sticitt user with that ID number has verified their identity (now or later), the wallet is linked to that user — the same result as the user claiming it.
- Once that user also has address details captured, Sticitt Rewards is activated on the wallet.
- If the verified user already owns another Sticitt wallet, the new wallet is not linked and Sticitt support is notified to resolve the conflict with you.
The ID number itself is never stored on the wallet and is not returned by any wallet endpoint.
Response & Mapping
The API will return a Wallet Object. The most critical field is the walletId.
Sticitt does not store your user's personal details (Name, Email) on the wallet during this phase. You must store the walletId in your own database and map it to your internal User ID.
2. Funding Wallets
There are two ways to get money into a wallet:
- EFT: The user (or your organization) deposits directly into the wallet using its unique
accountReference. - From your partner account: You programmatically move funds out of your own partner account float into the wallet.
Option A: EFT
Every wallet created has a unique accountReference (e.g., SABCPXYZ). Funds are loaded into the wallet via standard EFT (Electronic Funds Transfer) using this reference.
Banking Details for EFT
To load funds, the user (or your organization) must make a bank transfer using the specific Account Reference found in the Wallet Object.
| Field | Value |
|---|---|
| Beneficiary | Sticitt |
| Bank | FNB (Cheque) |
| Account Number | 62719297922 |
| Branch Code | 250655 |
| Reference | <YOUR_WALLET_ACCOUNT_REFERENCE> |
- Funds typically clear within 15min - 48hours depending on the bank.
Funding in Test Mode
Since real money cannot be used in the Sandbox:
- Do not EFT to the live bank account using test references.
- Contact Support: Email technology@sticitt.co.za with your Test Wallet ID or Account Reference to have test funds allocated.
Option B: From Your Partner Account
If your partner account already holds funds, you can push them into any wallet you manage without an EFT. This is the usual mechanism for distributing an allowance or a bulk allocation from a central pot.
Endpoint: Transfer partner account funds to wallet
Body:
{
"amount": 50000,
"walletReference": "March allowance",
"partnerReference": "PAYRUN-2026-03"
}
| Field | Requirement | Description |
|---|---|---|
amount | Required | Amount in cents. 50000 = R500.00. Use a negative amount to sweep funds back out of the wallet into your partner account. |
walletReference | Optional | Reference shown on the wallet's side of the transaction. |
partnerReference | Optional | Your own reference, for reconciliation on the partner account side. |
autoCashout | Optional | Pay the funded amount straight out to the wallet holder's bank account instead of leaving it in the wallet. Requires the disbursement scope, described below. |
payoutReference | Optional | Reference the holder sees on their bank statement for the payout. At most 30 characters. Only read when autoCashout is set. |
rsaIdNumber, bankAccountNumber, bankBranchCode, bankAccountType, bankAccountHolderName | With autoCashout | Who is being paid and where. Detailed below. |
Returns: The updated Wallet Object.
Check your partner account balance before a funding run to confirm you have enough float to cover it.
Auto cashout and the disbursement scope
Funding a wallet and paying that money straight out again are separate permissions. Your access token needs the disbursement scope to set autoCashout, on top of the wallet scope the endpoint already requires.
Sticitt grants the disbursement scope per partner, so email technology@sticitt.co.za if you need it enabled. Once granted it appears in the scope claim of your access token as disbursement-api.
| Your token | autoCashout | Result |
|---|---|---|
| Wallet scope only | omitted or false | The wallet is funded as normal. |
| Wallet scope only | true | 403 Forbidden. The wallet is not funded. |
| Wallet and disbursement scopes | true | Checked against the requirements below. |
What a disbursement needs
A payout goes to a bank account, so autoCashout requires you to tell us where the money is going and who it is for. Everything below is checked before any money moves, so a request that is missing something is refused with nothing transferred.
| Field | Requirement | Description |
|---|---|---|
rsaIdNumber | Required | 13 digit South African ID number of the person being paid. |
bankAccountNumber | Required | Up to 16 digits. |
bankBranchCode | Required | Up to 6 digits. |
bankAccountHolderName | Required | At most 30 characters, as it appears on the account. |
bankAccountType | Required | See the table below. |
walletReference | Required | Optional for an ordinary funding, required for a disbursement. |
amount | Positive | You cannot pay out a sweep back to your partner account. |
bankAccountType | Account |
|---|---|
0 | Public recipient |
1 | Cheque or bond |
2 | Savings |
3 | Transmission |
4 | Bond |
6 | Subscription share |
The ID number is a cross-check
rsaIdNumber is not how we find the wallet, since you already named the wallet in the path. It is checked against the ID number that wallet was onboarded with, and the request is refused if the two disagree.
This exists to catch the expensive mistake. A wrong wallet id on an ordinary funding puts money in the wrong Sticitt wallet, which can be swept back. On a disbursement it would send that money to a stranger's bank account, which cannot. So we make you state who you think you are paying, and we check.
A wallet only has an onboarding record if it was created with an ID number, so a wallet created without one cannot be paid out.
Only that the details are present and well formed. Whether Sticitt has verified the holder's ID, bank account or address makes no difference to a disbursement, and the banking details you supply are used as given rather than compared against the holder's Sticitt profile. You can read the holder's verification state from Get wallet by ID if you want it for your own checks.
Once the requirements are met the wallet is funded and the payout is handed to Sticitt to send to the holder's bank account.
Which fee you pay
A disbursement is one instruction, so it is charged once. Your account pays the cashout fee instead of the load fee, not both, because the money only passes through the wallet on its way to the bank.
| Call | Fee charged |
|---|---|
| Fund a wallet | Load fee |
Fund a wallet with autoCashout | Cashout fee |
| Sweep funds back out | Load fee |
Both fees are flat amounts per instruction, configured on your partner account, and charged to that account rather than taken out of the wallet. Your available balance has to cover the amount and the fee together, and that is checked before anything moves, so a shortfall is refused rather than leaving a funded wallet with a failed payout.
Naming the payout
payoutReference is what the holder sees against the deposit on their bank statement, so it is worth setting to something they will recognise. Keep it to 30 characters; a longer value is rejected with 400 Bad Request rather than being cut short, so you always know what reached the bank. Omit it and the payout shows up as Sticitt Pay.
{
"amount": 50000,
"walletReference": "March allowance",
"partnerReference": "PAYRUN-2026-03",
"autoCashout": true,
"payoutReference": "Acme March allowance",
"rsaIdNumber": "9001015800085",
"bankAccountNumber": "1234567890",
"bankBranchCode": "250655",
"bankAccountType": 1,
"bankAccountHolderName": "A Ngcobo"
}
Funding a wallet keeps money inside Sticitt, where you can still sweep it back with a negative amount. A disbursement sends it to an external bank account, which you cannot reverse through this API. Treat autoCashout as final and confirm the amount before you send it.
3. Retrieving Your Partner Account Balance
Separate from the individual wallets, your partner account has its own account (the "float"). This is the pot that Option B funding draws from, so you will want to check it before any bulk allocation.
Endpoint: Get account balance
Request: No parameters or body. The account is resolved from the partner_id on your access token, so you always get the balance of your own partner account.
Response:
{
"availableBalance": 1250000
}
| Field | Type | Description |
|---|---|---|
availableBalance | integer | Funds available to distribute, in cents (ZAR). 1250000 = R12 500.00. |
availableBalance excludes funds already reserved by pending transactions. It is a cached figure, so a very recent EFT into your partner account may take a moment to reflect.
This endpoint returns your account balance only — it does not aggregate your wallets. To read an individual wallet's balance, use the wallet endpoints in the next section.
Topping Up Your Partner Account
Your partner account has its own accountReference, returned by Get your partner alongside your partnerId and displayName. It identifies the float account that Get account balance reads and that Option B funding draws from.
Response:
{
"partnerId": "3f1c9a2e-...",
"displayName": "Acme Schools",
"accountReference": "SPACME01"
}
Use this reference, not a wallet's, when arranging a top-up of your float with Sticitt, and to pick out your own account when a wallet transaction lists it as the accountCreditReference or accountDebitReference. In the Sandbox, email technology@sticitt.co.za with the reference to have test funds allocated to your partner account.
4. Retrieving Wallet Info
You can query the balance and status of wallets at any time.
- List Wallets: Get list of wallets
- Returns: List of wallets linked to your partner account.
- Wallet Details: Get wallet by ID
- Returns: Wallet Object with details such as balance, status and the wallet holder's verification flags (detailed below).
- Transaction History: Get wallet transactions
- Returns: Paged, date-filterable list of a wallet's transactions (detailed below).
Verification Status
Get wallet by ID also reports how far the wallet holder has progressed through FICA verification. The flags describe the user the wallet belongs to, not the wallet itself.
Response (verification fields only):
{
"verifiedRsaId": true,
"verifiedBank": true,
"verifiedAddress": false
}
| Field | Type | Description |
|---|---|---|
verifiedRsaId | boolean | The holder's South African ID has been verified, either manually or automatically. |
verifiedBank | boolean | The holder's banking details have been verified. |
verifiedAddress | boolean | The holder's residential address has been verified. |
Each flag is null rather than true/false when the wallet has no user attached, or when the verification status could not be resolved. A null means unknown, not unverified — treat it as unverified only if your flow requires a positive confirmation.
Get wallet by ID is the only endpoint that resolves these flags. The other endpoints returning a wallet object (create, fund and link) always report them as null, and Get list of wallets omits them entirely. Fetch the wallet by ID when you need a holder's verification status.
Transaction History
Retrieve a wallet's ledger — funds in and out — as a paged, date-filterable list.
Endpoint: Get wallet transactions
GET /v3/wallets/{walletId}/transactions
Query Parameters
| Parameter | Type | Default | Notes |
|---|---|---|---|
pageSize | integer | 50 | Results per page. Must be between 1 and 200. |
pageIndex | integer | 0 | Zero-based page number. |
fromDate | date-time | – | Optional. ISO-8601 UTC (e.g. 2026-01-01T00:00:00Z). Inclusive lower bound. |
toDate | date-time | – | Optional. Inclusive upper bound. Must be on or after fromDate. |
Response
Returns a paged result; transactions are ordered newest first.
{
"items": [
{
"transactionId": "0f8e1f2a-...",
"direction": "In",
"dateTime": "2026-07-15T12:00:00Z",
"amount": 7500,
"accountCreditReference": "SGTDPNPS",
"accountDebitReference": "SABCPXYZ",
"creditReference": "PAYRUN-2026-03",
"debitReference": "March allowance"
}
],
"pagination": {
"totalCount": 178,
"totalPages": 4,
"pageIndex": 0,
"pageSize": 50
}
}
The amount field is an integer in cents (e.g. 7500 = R75.00), not rand.
direction is reported from the perspective of the wallet you requested: In means the wallet received funds, Out means funds left the wallet. Use it rather than comparing account references yourself.
You can only read transactions for a wallet your partner account owns or is linked to. Requesting a wallet outside your ecosystem — or one that does not exist — returns 404 Not Found; no transaction data is exposed.
Use pagination.totalCount to drive paging, and pass fromDate/toDate to scope a statement period.
5. Executing Payments (Closed Loop)
Unlike the Standard Payment Flow where the User authorizes the payment via the SDK, Enterprise partners can programmatically execute payments on behalf of the wallet.
Requirement: This functionality is only available for Closed Loop transactions.
- The Merchant must be managed by you (the Partner).
- The Wallet must be managed by you (the Partner).
The Execution Call
You perform this by updating a pending payment with the funding walletId.
Endpoint: Update Payment
Set the payment status to 2 (Execute payment) and include the walletId in the request body. Optionally add a walletHolderName to identify the user for reporting purposes.
Body:
{
"status": 2,
"walletId": "7f8e1f2a-...",
"walletHolderName": "John Doe"
}
If you attempt to use a Partner Wallet to pay a Public Merchant (one you do not own), this call will fail. Partner Wallets are restricted to your own merchant ecosystem until the user "Links" the wallet.
6. Transferring Funds
Wallet to wallet transfers are deprecated and will be removed in a future version. Move funds through your partner account instead, as described below. Existing calls keep working for now, and every response carries a Deprecation: true header so you can find them in your logs.
You can programmatically transfer funds between any two wallets that are linked to your partner account. This is useful for peer-to-peer flows, such as a parent transferring allowance to a child's wallet, or distributing funds from a central pot to user wallets.
Endpoint: Transfer wallet funds
Constraints
- Same Ecosystem: Both the Source Wallet and the Destination Wallet must be linked to or created by your Partner account. You cannot transfer funds to a random Sticitt user who is not part of your integration.
- Funds Availability: The source wallet must have a sufficient balance.
Moving funds through your partner account instead
Two calls to Transfer partner account funds to wallet replace one transfer:
- Fund the source wallet with a negative
amount, sweeping the money back to your partner account. - Fund the destination wallet with the same amount as a positive value.
The constraints above still apply, since both wallets have to be yours to fund either of them.
This is more explicit, and it is the reason for the change: both legs land on your partner account statement, so a movement between two wallets is visible in your own reconciliation. A direct transfer never touches your account and leaves no trace there.
The two calls are independent. If the second fails, the money sits in your partner account rather than in either wallet, so check the response of the first before making the second and retry the second on its own if needed.
7. Claiming and Linking wallets
A wallet in your ecosystem can exist in one of three states. Understanding these states resolves the confusion around "who controls what."
| State | Description | Spend Scope | Partner Control |
|---|---|---|---|
| 1. Partner Wallet (Unclaimed) | A wallet you created via API. The user has no Sticitt account yet. It acts like a "Gift Card" specific to your platform. | Restricted (Your Merchants Only) | ✅ Full |
| 2. Claimed Wallet | The user has "claimed" this wallet by registering a full Sticitt profile. | Global (Any Sticitt Merchant) | ⚠️ Shared |
| 3. Linked Wallet | An existing Sticitt user (who already had an account) has authorized your platform to link to their wallet. | Global (Any Sticitt Merchant) | ⚠️ Shared |
Linking a Wallet
To gain access to an existing Sticitt user's wallet (State 3), you must perform a "Link" operation. This authorizes you as a partner to manage their wallet on their behalf.
Prerequisite: You must have obtained a User Access Token for the specific user you wish to link.
- See User Authentication for details on how to get this token.
Endpoint: Link a wallet
For this specific call, do not use your standard Client Credentials token. You must use the access_token you received from the User Login flow in the Authorization header.
Request:
Header: Authorization: Bearer <USER_ACCESS_TOKEN>
Body: (Empty)
Response: The API returns the Wallet Object