Merchant management
Create, list, update, suspend, and unsuspend merchants via the Portal API — the programmatic version of the Portal's merchant management UI.
The merchant-management endpoints are the programmatic way for PSPs and acquirers to onboard, update, and lifecycle-manage their merchants. They're the API behind the Portal UI's merchant screens.
For the conceptual walk-through and decision tree, see Merchant Onboarding. For auth setup, see Authentication.
Endpoints
| Method | Path | Purpose | Allowed callers |
|---|---|---|---|
| GET | /restful/merchant/list | List merchants in your scope | PSP, Acquirer |
| POST | /restful/merchant/create | Onboard a new merchant | PSP, Acquirer |
| POST | /restful/merchant/update | Update an existing merchant | PSP, Acquirer |
| POST | /restful/merchant/suspend | Suspend an ACTIVE merchant | PSP, Acquirer |
| POST | /restful/merchant/unsuspend | Unsuspend a SUSPENDED merchant | PSP, Acquirer |
All requests use Basic Auth with a ROLE_REMOTE-enabled profile — see Authentication.
List merchants
Returns every merchant in your scope. For a PSP, that's merchants where pspId matches the caller. For an acquirer, that's merchants where acquirer matches the caller.
Request:
curl -X GET https://qa.scantopay.io/portal/restful/merchant/list \
-u 'PSP_42:yourPspApiPassword'Response:
[
{
"merchantId": 25,
"merchantName": "Acme Coffee Pty Ltd",
"merchantCategoryCode": "5812",
"cardAcceptorTerminalId": "12345678",
"cardAcceptorIdentificationCode": "8765432",
"cardAcceptorNameLocation": "ZA",
"email": "[email protected]",
"acquirer": "SBSA",
"pspId": 42,
"merchantStatus": "ACTIVE",
"acceptedCards": ["master", "visa"],
"acceptedPayments": "AMT,SECURE_CODE"
}
]Returns an empty array if you own no merchants. There's no pagination today — the full list comes back in one response.
Create a merchant
Onboards a new merchant on the platform. Returns the freshly-created merchant including its assigned merchantId.
Request body — ApiMerchantBean:
| Field | Required | Description |
|---|---|---|
merchantName | yes | Up to 45 chars |
merchantCategoryCode | yes | Exactly 4 chars (e.g. 5812 for eating places) |
cardAcceptorTerminalId | yes | Acquirer-issued terminal ID. SBSA requires exactly 8 chars. |
cardAcceptorIdentificationCode | yes | Acquirer-issued merchant code. SBSA requires 7-15 chars. |
cardAcceptorNameLocation | yes | 2-char country code (e.g. ZA) |
email | yes | Valid email address |
acquirer | conditional | Required when caller is PSP — the acquirer name (e.g. ABSA, SBSA, Nedbank, ECLIPSE). Ignored when caller is acquirer (taken from the caller). |
pspId | conditional | Required when caller is acquirer — assigns the merchant to a PSP. Ignored when caller is PSP (taken from the caller). |
secureCodeMerchantId | optional | If supplied, the platform creates a Secure Code config using the acquirer's defaults |
address | optional | Nested location object — see below |
acceptedCards | optional | List of card brands the merchant accepts — master, visa, maestro, amex, diners, cup |
payShapInfo | optional | Nested PayShap config — supply if onboarding the merchant on PayShap as well |
Nested address object:
| Field | Description |
|---|---|
addressLine1 | Street address |
addressLine2 | Optional |
city | City |
suburb | Suburb / district |
country | Country |
postalCode | Postal code |
latitude | Float, optional |
longitude | Float, optional |
Sample request:
curl -X POST https://qa.scantopay.io/portal/restful/merchant/create \
-u 'PSP_42:yourPspApiPassword' \
-H 'Content-Type: application/json' \
-d '{
"merchantName": "Acme Coffee Pty Ltd",
"merchantCategoryCode": "5812",
"cardAcceptorTerminalId": "12345678",
"cardAcceptorIdentificationCode": "8765432",
"cardAcceptorNameLocation": "ZA",
"email": "[email protected]",
"acquirer": "SBSA",
"acceptedCards": ["master", "visa"],
"address": {
"addressLine1": "1 Main Road",
"city": "Cape Town",
"country": "South Africa",
"postalCode": "8001"
}
}'Response:
The full ApiMerchantBean of the new merchant, including the assigned merchantId and current merchantStatus.
Common errors:
| HTTP | Body | Cause |
|---|---|---|
400 | "Invalid 'pspId' Field" | Acquirer didn't supply pspId, or the supplied PSP doesn't exist |
400 | "Invalid 'acquirer' Field" | PSP supplied an acquirer name that isn't in the supported list |
400 | "Invalid 'Terminal Id' Field, must be 8 length" | SBSA-specific terminal ID validation |
400 | "Invalid 'cardAcceptorIdentificationCode' Field, must be between 7 and 15 length" | SBSA-specific identification code validation |
400 | (PayShap validation message) | payShapInfo was supplied but invalid |
Update a merchant
Two modes:
| Mode | Trigger | Behaviour |
|---|---|---|
| Full update | updateOnlyPresentFields: false (default) | Every required field must be supplied — missing fields fail validation |
| Selective update | updateOnlyPresentFields: true | Only fields present in the request body are changed; everything else is preserved |
Selective update is the safer choice for most use cases.
Sample request — selective update changing only the email:
curl -X POST https://qa.scantopay.io/portal/restful/merchant/update \
-u 'PSP_42:yourPspApiPassword' \
-H 'Content-Type: application/json' \
-d '{
"merchantId": 25,
"updateOnlyPresentFields": true,
"email": "[email protected]"
}'Response: the updated ApiMerchantBean.
Update constraints:
merchantIdis mandatory- Merchant must be in
ACTIVEstate - Ownership check applies (PSP/acquirer can only update merchants they own)
acquirercan be changed (PSP-only) provided the new acquirer is in the supported list
For the rules around mutating PayShap info, see PayShap management.
Suspend a merchant
Moves a merchant from ACTIVE to SUSPENDED. The merchant stops being able to accept new transactions until unsuspended.
Request:
curl -X POST https://qa.scantopay.io/portal/restful/merchant/suspend \
-u 'PSP_42:yourPspApiPassword' \
-H 'Content-Type: application/json' \
-d '{
"merchantId": 25,
"reason": "Compliance hold pending document review"
}'Request fields:
| Field | Required | Description |
|---|---|---|
merchantId | yes | Merchant to suspend |
reason | yes | Free-text reason — captured in the audit log |
Response: HTTP 200 OK with no body.
Common errors:
| HTTP | Body | Cause |
|---|---|---|
400 | "Merchant not in 'ACTIVE' state" | Merchant is already suspended, waiting activation, or terminated |
400 | "Invalid 'merchantId'" | Ownership check failed |
Unsuspend a merchant
Reverses a suspension — moves from SUSPENDED back to ACTIVE.
Request:
curl -X POST https://qa.scantopay.io/portal/restful/merchant/unsuspend \
-u 'PSP_42:yourPspApiPassword' \
-H 'Content-Type: application/json' \
-d '{
"merchantId": 25,
"reason": "Documents received and verified"
}'Same request body as suspend. The reason is captured in the audit log.
Common errors:
| HTTP | Body | Cause |
|---|---|---|
400 | "Merchant not in 'SUSPENDED' state" | Merchant is already active, or in a non-suspended state |
400 | "Invalid 'merchantId'" | Ownership check failed |
What about activation?
Newly-created merchants are activated automatically as part of the /restful/merchant/create flow — no separate activation step is required. The legacy /restful/merchant/activate/{merchantId} endpoint is deprecated and not documented here.
If a merchant ends up in WAITING ACTIVATION for some reason (typically a back-office configuration step), contact [email protected] to resolve.
What's next
- Conceptual walk-through of onboarding → Merchant Onboarding
- Configure the merchant's webhook → Notifications
- Generate the merchant's API password → API credentials
- Generate Lib Lite tokens for in-app payments → Lib Lite tokens
- Cross-cutting rules → Business rules
Updated about 23 hours ago
