Card provisioning

Link cards and bank accounts to a wallet profile so customers don't need to re-enter card details on every payment.

The Card Provisioning API lets wallet providers attach a customer's PAN or account number to their wallet profile. Once provisioned, the wallet can list the card in its UI, route purchases to it without re-prompting the customer, and offer multi-card management (default card, blocked card, etc.).

This is a separate API surface from the Remote API. The Remote API is the runtime payment engine; the Provisioning API is the wallet-management layer that runs alongside it.

For the rules, see Card Provisioning — business rules.


Base URLs

EnvironmentBase URL
Sandbox / QAhttps://qa.scantopay.io/pluto/provisioning
Productionhttps://scantopay.live/pluto/provisioning

All operations are POST and authenticated using the same Basic-Auth or Bearer credentials as the Remote API. See Authentication.


The provisioning lifecycle

                       ┌────────────┐
   customer adds card  │            │     customer removes card
   ───────────────────►│   LINKED   │◄─────────────────────────
                       │            │       /delink
                       └─────┬──────┘
                             │
                             │  customer reports card
                             │  lost or stolen
                             ▼
                       ┌────────────┐
                       │            │     customer recovers
                       │  BLOCKED   │     ───────────────►  back to LINKED
                       │            │       /unblock
                       └────────────┘

Plus two intermediate states for the registration flow itself:

  • COSMETIC — provisional state when the wallet wants to display the card before validation
  • DELINKED — terminal state after /delink

The seven operations

OperationPurposeEndpoint
RegisterAdd a card / account to a walletPOST /register
DelinkRemove a cardPOST /delink
BlockTemporarily disable a card without removing itPOST /block
UnblockRe-enable a blocked cardPOST /unblock
UpdateChange expiry, image, or cardholder namePOST /update
Check Card StatusQuery the current statePOST /checkCardStatus
Send Brand IndicatorUpload card art for display in the walletPOST /sendBrandIndicator

Register

Links a PAN or account number to a wallet identified by MSISDN.

Request fields:

FieldRequiredDescription
msisdnyesWallet owner's mobile number, international format
accountNumberyesPAN (14-19 digits, Luhn-10) or account number (16 digits: 6-BIN + 9-account + 1-check-digit)
accountconditionalAccount type — 10 (Savings), 20 (Current), 30 (Credit). Required if the BIN demands it (most debit cards).
expiryDateoptionalMMYY
imageIdoptionalReturned by Send Brand Indicator — drives the card art shown in the wallet
cardholderNameoptional3-26 characters
dateOfBirthconditionalCCYYMMDD. Required if validationMethod: DOB is used.
nodeoptionalThe wallet "node" the card is associated with (typically a bank scheme: SBSA, ABSA, etc.)
stateoptionalLINKED (default) or COSMETIC. See Business rules.
validationMethodoptionalSIMPLE (yes/no prompt) or DOB (date-of-birth confirmation)

Request:

curl -X POST https://qa.scantopay.io/pluto/provisioning/register \
  -u 'wallet_username:wallet_password' \
  -H 'Content-Type: application/json' \
  -d '{
    "msisdn": "27832006283",
    "accountNumber": "5221008264807699",
    "account": "30",
    "cardholderName": "J Smith",
    "expiryDate": "1228",
    "state": "LINKED",
    "node": "SBSA",
    "validationMethod": "SIMPLE",
    "dateOfBirth": "19830711"
  }'

Response:

{ "result": "SUCCESS" }

Possible result values:

ResultMeaning
SUCCESSCard registered.
CARD LINKED TO PROFILEAlready linked to this MSISDN (idempotent — no-op).
ALREADY LINKEDLinked to a different MSISDN. Reject the registration.
MAX CARDS LINKEDWallet has reached its card-count limit.
CARD BLACKLISTEDCard is on the platform blacklist.
CARD NOT SUPPORTEDBIN isn't in the supported issuer list.
CARD CHECK DIGITS FAILLuhn-10 check failed.
CARD EXPIREDExpiry is in the past.
EXPIRY INVALIDExpiry isn't MMYY or is otherwise malformed.
IMAGE ID INVALIDReferenced imageId doesn't exist.
CARDHOLDER NAME INVALIDCardholder name fails length / character validation.
MISSING ACCOUNTBIN requires account and it wasn't supplied.
INVALID CARD STATEstate isn't LINKED or COSMETIC.
FAILGeneric failure — log the request payload and contact support.

Delink

Removes a card from a wallet permanently. To re-add it, call /register again.

curl -X POST https://qa.scantopay.io/pluto/provisioning/delink \
  -u 'wallet_username:wallet_password' \
  -H 'Content-Type: application/json' \
  -d '{
    "msisdn": "27832006283",
    "accountNumber": "5338921234567891"
  }'

Response:

{ "result": "SUCCESS" }

Returns FAIL if the (msisdn, accountNumber) pair doesn't match a wallet record.


Block

Temporarily disables a card without delinking. Use when a customer reports a card lost / stolen and you don't want to lose the card-to-wallet association for the post-recovery flow.

curl -X POST https://qa.scantopay.io/pluto/provisioning/block \
  -u 'wallet_username:wallet_password' \
  -H 'Content-Type: application/json' \
  -d '{
    "msisdn": "27832006283",
    "accountNumber": "5338921234567891"
  }'

Returns SUCCESS or FAIL.


Unblock

Reverses a Block. Card transitions from BLOCKED back to LINKED.

curl -X POST https://qa.scantopay.io/pluto/provisioning/unblock \
  -u 'wallet_username:wallet_password' \
  -H 'Content-Type: application/json' \
  -d '{
    "msisdn": "27832006283",
    "accountNumber": "5338921234567891"
  }'

Returns SUCCESS or FAIL.


Update

Updates mutable fields on an existing link: expiryDate, imageId, cardholderName. At least one of these must be supplied.

curl -X POST https://qa.scantopay.io/pluto/provisioning/update \
  -u 'wallet_username:wallet_password' \
  -H 'Content-Type: application/json' \
  -d '{
    "msisdn": "27832006283",
    "accountNumber": "5338921234567891",
    "expiryDate": "1230",
    "imageId": 12345,
    "cardholderName": "Mr J Smith"
  }'

node, validationMethod, and state cannot be updated — those are register-time-only.

Possible result values are the same set as Register, plus:

  • CARD DELINKED — the card has been delinked; Update doesn't resurrect it. Re-register instead.

Check Card Status

Returns the card's current provisioning state.

curl -X POST https://qa.scantopay.io/pluto/provisioning/checkCardStatus \
  -u 'wallet_username:wallet_password' \
  -H 'Content-Type: application/json' \
  -d '{
    "msisdn": "27832006283",
    "accountNumber": "5338921234567891"
  }'

Response:

{ "result": "ACTIVE" }
ResultMeaning
ACTIVECard is LINKED and usable for purchases.
BLOCKEDCard is blocked. Unblock to re-enable.
DELINKEDCard has been delinked. Re-register if needed.

Send Brand Indicator

Uploads card art that will display in the wallet UI when this card is shown. Returns an imageId you pass on subsequent /register or /update calls.

curl -X POST https://qa.scantopay.io/pluto/provisioning/sendBrandIndicator \
  -u 'wallet_username:wallet_password' \
  -H 'Content-Type: application/json' \
  -d '{
    "description": "ABC Bank Gold Card",
    "image": "<base64-encoded-image-bytes>"
  }'

Response:

{ "imageId": 12345 }
FieldConstraint
descriptionMax 30 characters. Displayed alongside the image.
imageBase64-encoded byte array. Recommended PNG, 300×190 px aspect, < 100 KB.

imageIds are scoped to your wallet provider. You can have many active brand indicators (one per card product / tier).


Putting it together — a registration flow

1. Customer enters card in wallet UI
   ↓
2. Wallet calls /binLookup (Remote API) to discover required fields
   ↓
3. Wallet collects fields (CVV, DOB, etc.) the BIN requires
   ↓
4. Wallet calls /register with the collected data
   ├─► SUCCESS → display card in wallet, ready to use
   ├─► ALREADY LINKED → show "this card is registered to another wallet" message
   └─► other error → handle per the result table above

If you used validationMethod: SIMPLE or DOB, the customer will be prompted by Scan to Pay's validation flow (in the wallet app's WebView or via SMS, depending on your integration) before the state transitions from COSMETIC to LINKED. If no validationMethod was sent, the card is immediately LINKED.


What's next