Card Use Cases

This section focuses on card issuing and management within Eclipse, including how cards are created, activated, and maintained throughout their lifecycle. It also covers scenarios where a tenant securely stores a customer’s card details for future use (Card-on-File). The use cases explain how cards can be issued, linked to customers, and used for both physical and digital transactions, as well as how stored card details support seamless repeat payments. For each scenario, the guide outlines the relevant APIs, required configurations, and the technical steps needed to integrate card issuing and Card-on-File functionality into your applications.

Card Management

Card Enabled Wallet Type and Wallet configurations

EFT Corporation-issued cards have a wide range of customisation settings that can be applied at a global wallet type level as well as an individual wallet instance level allowing customers to selectively customise their card experience. The following settings can be customised:

AttributesDescription
allowInternationalTransactionsControls whether international transactions are allowed on the card. True or false.
internationalMarkUpFeesAdditional fee charged for international card transactions
contactlessLimitThe limit under which contactless or tap transactions are enabled. By default, this is set to 500. To disable contactless transactions this can be set to 0.
SubProgramCodeForVirtualCardPostilion program card for issued virtual cards
SubProgramCodeForPhysicalCardPostilion program card for issued physical cards
alwaysCreateCardControls whether a card will be issued against a wallet when created. Can either be set as true or false. False means a card will need to be manually added to the wallet after creation
feesReversalAllowedControls whether a fee can be reversed, set as either true or false

Stop a Card

A customer's card may be stopped by the customer, organisation or tenant. It should be stopped immediately if the card is assumed to be lost or stolen.

Prerequisites

  • Valid JWT
  • Card ID

Stop Card
Request to stop the card
Change the card status to “LOST, STOLEN, DAMAGED, COUNTERFEIT, REPLACED ”

PUT /eclipse-conductor/rest/v1/tenants/{tenantId}/cards/{cardId}
{
	"cardRules": {
		"ecommerceTransactionsEnabled": true,
		"internationalTransactionsEnabled": true
	},
	"status": "CANCELLED",
	"reason": "DAMAGED"
}

Unstop a Card

A customer's card may be Unstopped by the customer, organisation or tenant. It can not be unstopped if the status is stolen or counterfeit.

Prerequisites

  • Valid JWT
  • Card ID

Step 1 – UnStop Card
Request to stop the card
Change the wallet status to “Active ”

PUT /eclipse-conductor/rest/v1/tenants/{tenantId}/cards/{cardId}
{
	"status": "ACTIVE",
	"reason": "UNBLOCKED"
}

Enable / Disable Card E-Commerce Transactions

A customer may enable or disable e-commerce transactions on a card if supported by the card program.

Prerequisites

  • Valid JWT
  • Card ID

Enable / Disable E-commerce on Card
Request to enable/disable.
Change the ecommerceTransactionEnabled card rule to True / False

PUT /eclipse-conductor/rest/v1/tenants/{tenantId}/cards/{cardId}
{
	"cardRules": {
		"ecommerceTransactionsEnabled": true
	}
}

Enable / Disable Card International Transactions

A customer can enable or disable international transactions on a card if supported by the card program.

Prerequisites

  • Valid JWT
  • Card IDS

Enable / Disable International
Request to enable/disable.
Change the internationalTransactionsEnabled card rule to True / False

PUT /eclipse-conductor/rest/v1/tenants/{tenantId}/cards/{cardId}
{
	"cardRules": {
		"internationalTransactionsEnabled": true
	}
}

Do a Physical Card Replacement

A customer can replace an existing physical card.

Prerequisites

  • If the card replacement is for a card that is still in an active state, you should stop the active card e.g. replace a card that is soon to expire.
  • Valid JWT

Create Card
Register and link the card using the Create Card
This refers to the following API in Swagger:

POST /eclipse-conductor/rest/v1/tenants/{tenantId}/customers/{customerId}/cards

You must populate one of the primaryPhysicalCardIdentifier fields with the replacement card details:

  • packID
  • PAN
  • QR Code

You also need to specify the cardId of the card you are replacing. Use the Wallet ID of the primary card (virtual card) wallet you wish to replace.

Do a Virtual Card Replacement

A customer can replace an existing virtual card.

Prerequisites

  • If the card replacement is for a card that is still in an active state, you should stop the active card. e.g. replace a card that is soon to expire.
  • Valid JWT

Create Card
Create the card using the Create Card
This refers to the following API in Swagger:

POST /eclipse-conductor/rest/v1/tenants/{tenantId}/customers/{customerId}/cards
{
  "cardRules": {
    "ecommerceTransactionsEnabled": true,
    "internationalTransactionsEnabled": true
  },
  "operationType": "ADDON_CARD",
  "status": "ACTIVE",
  "walletId": 1089
}

Do not populate any of the primaryPhysicalCardIdentifier fields. Instead, use the Wallet ID of the primary (virtual) card wallet you want the replacement card to be linked to.

Cancel Card Enabled Wallet (Card Wallet)

If a card wallet is closed or cancelled, all cards linked to it—whether primary, supplementary, or add-on—will be cancelled automatically. This is different from cancelling an individual card. When a single card (primary, supplementary, or add-on) is cancelled, only that card is affected; the other cards in the wallet remain active.

A card wallet can only be cancelled if its balance is zero. Customers are advised to transfer any remaining funds from the card wallet to their digital wallet before proceeding with the cancellation.

Prerequisites

  • The card wallet available balance should be zero.
  • Valid JWT

Step 1 – Cancel the card wallet

PUT /eclipse-conductor/rest/v1/tenants/{tenantId}/wallets/{walletId}
{
	"status": "CANCELLED",
}

Pin Management

Physical Card PIN Set/Change

Customers can set or change their pins on issued cards.

Prerequisites

  • A valid JWT
  • A card issued to a customer
  • The CardID of the card is set

The customer must be authenticated before setting or changing a PIN.

PCI-compliant tenants

PCI-compliant tenants can set card pins directly using either of these APIs - the pin is explicitly set in the request body:

PUT /eclipse-conductor/rest/v1/tenants/{tenantId}/cards/{cardId}
{
  "pin":"1234"
}
POST /eclipse-conductor/rest/v1/tenants/{tenantId}/cards/{cardId}/pin-sets
{
  "pin":"1234"
}

Non-PCI-compliant tenants

For tenants that are not PCI-compliant, the pin-sets API can be used in two ways:

SMS

When pinDeliveryMechanism is set to SMS in the request body and no PIN is provided, Eclipse will generate a random 4-digit PIN and send it via SMS to the phone number stored on the customer profile.

LINK

When pinDeliveryMechanism is set to LINK in the request body, Eclipse will return a captive portal link in the completionUrl field of the response. Tenants can display this URL in a webview, allowing customers to enter their PIN in a PCI-compliant captive portal hosted by Eclipse.
In this flow, the customer must also enter their Card Access Password (CAP). For details on setting the CAP see Set/Change Card Access Password (CAP).

📘

Note

If a CAP is required in the sandbox environment the SMS will not be sent, but a generic password ‘cap123’ can be used.

Physical Card PIN Counter Reset

The PIN attempt counter tracks how many times a customer has entered the wrong PIN when making payments. Once the allowed number of attempts is reached, the card may be blocked from further transactions. Resetting the counter restores the customer’s ability to use the card with the correct PIN.

Prerequisites

  • Valid JWT
  • CardID
  • The customer must be authenticated before allowing a PIN change request.

Reset PIN
Set the pinRetryCounter field to 0:

PUT /eclipse-conductor/rest/v1/tenants/{tenantId}/cards/{cardId}
{
	"pinRetryCounter":0
}

Set/Change Card Access Password (CAP)

To view sensitive card details, a user must be authenticated in one of two ways:

  1. By using a JWT issued to the user from the logged-in IP address, or
  2. By providing a valid Card Access Password (CAP) without a JWT.

There are two methods for setting the CAP:

1. Generate random CAP

Make an API call to create a CAP for the user (only needed once per customer) - set the identity field to "CAP":

POST /eclipse-conductor/rest/v1/tenants/{tenantId}/customers/{customerId}/identities
{
	"identity":"CAP"
}

Eclipse will generate a random CAP and SMS it to the customer's phone number on the profile.

📘

Note

On Sandbox the SMS will not be sent, but a generic password ‘cap123’ can be used.

2. Set CAP through the Captive Portal

If a user has the cardId, tenantId and customerId they can explicitly set the CAP using the following request.

GET {baseUrl}/payments-portal/card-ui?interactionType=createCap&userId=USERID&cardId={cardId}&tenantId={tenantId}&landingURL={URL}

When the provided URL is opened, an OTP is sent to the user’s registered mobile number. The user is then asked to enter a new Card Access Password (CAP) along with the OTP. If the OTP is valid, the CAP is set successfully. If the OTP is invalid, an error is returned.

3. Reset the CAP Password through the Captive Portal

If the user has the cardId, tenantId, customerId, and a valid CAP, they can reset the Card Access Password by sending the following request:

GET {baseUrl}/payments-portal/card-ui?interactionType=resetCap&tenantId={tenantId}&userId=USERID&cardId={cardId}&landingURL={URL}

When the provided URL is opened, an OTP is sent to the user’s registered mobile number. The user is then asked to enter a new Card Access Password (CAP) along with the OTP. If the OTP is valid, the CAP is set successfully. If the OTP is invalid, an error is returned.

📘

Landing URL

Specify the landing URL to direct the customer after completing the process, taking into account breakout points in all captive portal flows, such as "Cancel and go back" or "Done."

The landing URL can also be set as &landingURL without a redirect URL. This configuration enables all available options within the journey.

Retrieve Card Details for Customer

There are 3 ways in which sensitive card details can be retrieved:

  1. Card details can be retrieved directly if the call is made with the end user JWT and from the IP address of the logged-in device
  2. Card details can be retrieved directly if the call is made without a JWT, but a Card Access Password (CAP) is provided and the call is made from the IP address of the logged-in device the details can be retrieved
  3. Card details can be retrieved through a captive web portal if a Card Access Password (CAP) is provided

1. Retrieve Card Details for Customer (API)

Prerequisites

  • A customer must be set up, with a card already created. Have a cardId ready.
  • The JWT of the customer
  • API Call originating from the IP address of the logged-in device

Step 1 - Retrieve Card details
The user gets their card details from the app using the user JWT:

GET /eclipse-conductor/rest/v1/tenants/{tenantId}/cards/{cardId}?masked=false

2. Retrieve Card Details for Customers with CAP (API)

Ability to retrieve full card details for a customer.

Prerequisites

  • A customer must be set up, with a card already created. Have a cardId ready.
  • API Call originating from the IP address of the logged-in device

Step 1 –Create a CAP (Card Access Password)

Step 2 - User enters CAP, then Retrieve Card
The user gets their card details from the app without needing a JWT but the app asks them to enter the CAP they received by SMS to access their card details:

GET /eclipse-conductor/rest/v1/tenants/{tenantId}/cards/{cardId}?masked=false&cap=xxxxxx
📘

Note

The call to get unmasked card details must come directly from the customers personal device. It must not be made from the tenant's backend unless the backend is PCI/DSS compliant.

3. Retrieve Card Details for Customers (Captive Portal Flow)

Step 1 –Create a CAP (Card Access Password)

Step 2 – View Card

  • Prerequisites
  • tenantId
  • userId
  • cardId
  • CAP

Users can view his/her cards using the following request:

GET {baseUrl}/payments-portal/card-ui?interactionType=viewVirtualCard&tenantId={tenantId}&userId=USERID&cardId={cardId}&landingURL={URL}

Users need to enter the above URL in the browser then enter the valid CAP and the card data will be displayed.

Add On and Supplementary Cards

  1. Add-on Card
  2. Supplementary Card

Add-on and supplementary cards are additional cards issued against primary physical or virtual cards and form a secondary or supplementary card to each wallet.

Add-on and supplementary cards will have the same limits applied as the primary card.

658

Add on Card

Add On Cards

An add-on card is used to issue an additional card that is linked to the primary cardholder's wallet but is associated with a different cardholder. e.g. card used by a spouse.

In the API request, the new cardholder Customer ID and the primary device Wallet ID are required. If it is a physical card, the new PackID or QR is also required.

Prerequisites

  • The primary card must be Active.
  • The secondary cardholder must be registered in Eclipse as an active user and passed KYC
  • Valid JWT

Example for a physical add-on card:

POST /eclipse-conductor/rest/v1/tenants/{tenantId}/customers/{customerId}/cards
{
  "cardRules": {
    "ecommerceTransactionsEnabled": true,
    "internationalTransactionsEnabled": true
  },
  "operationType": "ADDON_CARD",
  "physicalCardIdentifier": {
    "cardId": 347,
    "packId": "0PRG17USD0000028622",
    "pan": "2307660000148442"
  },
  "status": "ACTIVE",
  "walletId": 1089
}

Example for a virtual add-on card:

POST /eclipse-conductor/rest/v1/tenants/{tenantId}/customers/{customerId}/cards
{
  "cardRules": {
    "ecommerceTransactionsEnabled": true,
    "internationalTransactionsEnabled": true
  },
  "operationType": "ADDON_CARD",
  "status": "ACTIVE",
  "walletId": 1089
}

Supplementary Cards

A supplementary card is an additional card, linked to the same wallet and primary cardholder. i.e. the same cardholder information as the primary card.

When requesting a supplementary card, the Wallet ID of the primary card is required and is used in the linking of the two (primary and supplementary) cards. If the supplementary card is a physical card, the PackID or QR code needs to be included in the API request.

All supplementary cards are treated independently of the primary card. Therefore the status of the primary card does not impact the status of the supplementary card.

All Debit Programs and all programs issuing supplementary cards should have the following two attributes configured on the card wallet type

SubProgramCodeForPhysicalCard = Physical Program Code configured on the CMS
SubProgramCodeForVirtualCard = Virtual Program Code configured on the CMS

Prerequisites

  • The primary card must be Active.
  • Valid JWT
  • Physical Add On Card Request Payload
POST https://eclipse-conductor/rest/v1/tenants/{tenantId}/wallets/{walletId}/cards

When a Wallet is locked, all associated cards, Supplementary cards and Add-On cards are stopped. If the wallet is then unlocked, all the associated cards remain locked and must be individually unlocked. This is to avoid the unlocking of a card that may need to remain locked.

Card-on-File Management

Card-on-file is when a business securely stores its customer’s card payment details, with the cardholder’s consent. Payment data storage comes along with PCI-DSS considerations and therefore businesses that would like to leverage card-on-file need to be compliant.

The cardholder can then reuse the securely stored card details for future payments (e.g. wallet top-ups in the context of Eclipse) thereby having a seamless checkout experience.

Eclipse provides the following options (which are PCI-DSS compliant) for card-on-file management:

  1. Add a card on file directly - specify the card details in the API call.
  2. Add a card on file but use a captive portal - specify callback URL in the API call - tenant system does not need to be PCI compliant.
  3. Add a card on file as part of a top-up - directly (same as (1))
  4. Add a card on file as part of a top-up - using the captive portal (same as (2))

1. Add Card Details Directly

This method allows users to save their card details by capturing the following information:

  • Alias
  • CardData (pan, CVV, expiry)

Prerequisites

  • Valid JWT with access to read the wallet.
  • The tenant must be PCI compliant.

Add Card on file:

POST /eclipse-conductor/rest/v1/tenants/{tenantId}/customers/{customerId}/cards-on-file
{
     "cardData": {
          "cvv": "562",
          "pan": "4242424242424242",
          "expiry": "0536",
          "cardholderName": "Mikel Arteta"
     },
     "alias": "Card-42"
}
{
  "cardOnFileId": "590f63a8-909f-4c67-88f8-2a21986789e4"
}

Refer to the Initiate Adding A Card On File documentation for full details.

📘

Note

The selected tenant must be end-end PCI-DSS compliant to pass card data directly.

2. Add a card on file via the captive portal

The second alternative method for storing card payment details is to pass a callback URL on the endpoint below. With this option, you don't need to populate any of the card details but only the callback URL to the captive portal.

When the request is sent, the system will return a completion URL (as shown in the sample JSON response below) which can be navigated to - you need to iFrame navigate to this URL to populate the card details i.e. PAN, CVV & expiry date.

Prerequisites

  • Valid JWT with access to read the wallet

Add Card on file:

POST /eclipse-conductor/rest/v1/tenants/{tenantId}/customers/{customerId}/cards-on-file
{
     "alias": "demo",
     "callbackUrl": "http://google.com"
}
{
  "completionUrl": "https://eclipse-java-sandbox.ukheshe.rocks/t/c6wJ8",
  "cardOnFileId": "edb452d3-a47b-4e5c-880d-3fe84c5b1649"
}

Refer to the screenshot below showing an example of a captive UI screen where users can capture their card details.

Refer to the screenshot below showing an example of a captive UI screen where users can capture their card details.

3. Add a card on file as part of a top-up

The user-provided card details will be saved for use in future transactions that is after a successful wallet top-up by card transaction. This approach follows the same process flow as outlined in the first option i.e. add card details directly.

Prerequisites

  • Valid JWT with access to read the wallet.
  • wallet ID.
POST /eclipse-conductor/rest/v1/tenants/{tenantId}/wallets/{walletId}/topups
{
     "topupCardData": {
          "expiry": "1125",
          "pan": "4242424242424242",
          "cardholderName": "CLAYT",
          "accountType": "Debit",
          "cvv": "123"
     },
     "amount": 500,
     "externalUniqueId": "ref890889",
     "type": "ZA_MASTERPASS_CARD"
}

4. Get a Card on file with a Cryptogram

A cryptogram value is returned when the Get Card-on-File API is called with the query parameter fields=cryptogram.

Prerequisites

  • Valid JWT with access to read the wallet.
  • Tenant ID
  • Customer ID
  • Card on file ID
  • Query parameter fields set to cryptogram
GET /eclipse-conductor/rest/v1/tenants/{tenantId}/customers/{customerId}/cards-on-file/{cardsOnFileId}?fields=cryptogram
{
  "alias": "zttydgbovO",
  "cardOnFileId": "16174808-15a7-4c9e-886d-9d84584cfb02",
  "last4Digits": "2999",
  "expires": "2025-12-01T00:00:00.000Z",
  "status": "ACTIVE",
  "schemeTokenType": "VISA",
  "schemeToken": "17f551c1cbgyuhhjc143ab1f7425bcd002",
  "schemeTokenStatus": "ACTIVE",
  "cardArtUrl": "https://cardsonfile-content-public.s3-eu-west-1.amazonaws.com/22af01f2bdf445e497895d502dd1f1ae-digitalCardArt.pdf",
  "bin": "489537",
  "cryptogram": "AwAAAAAAPuEtjg4Am00eAtgqsAAAA="
}

Customization of Eclipse Hosted and Captive Portal UI

Eclipse offers hosted pages for many scenarios:

  • Card viewing and card management in a captive portal within the Eclipse PCI environment. This caters for the scenario where tenants are not PCI compliant and therefore can not serve this sensitive data.
  • Hosted checkout for easy e-commerce integration.
  • Hosted AWS Liveness for easy integration of AWS liveness into a tenant's KYC process.

For all of these hosted pages, the user interface can be customised according to a tenant's logo & colour scheme. This customization can be implemented by configuring a global property for the tenant.

Prerequisites

The following parameters can be configured:

PropertyProperty Value
Property namepublic.tenant.{tenant ID}
tenantNamexxxxxx
merchantNamexxxxxx
titlexxxxxx
capLabelLabel when setting CAP - e.g. 4-digit passcode
capDigitNumber of digits for CAP - e.g. 4
isCapNumOnlyAllow only numbers for CAP - e.g. true
paymentTypePayment types for Hosted checkout - e.g. mastercard,ozow,pnpcash
primaryBackgroundColour#FFFFFF (Colour)
primaryColour#0083C2 (Colour)
primaryTextColour#FFFFFF (Colour)
primaryButtonColour#0083C2 (Colour)
secondaryColor#FFFFFF (Colour)
primaryButtonTextColour#FFFFFF (Colour)
secondaryButtonColourtransparent
secondaryButtonTextColour#0083C2 (Colour)
buttonDisabledColor#FFFFFF (Colour)
alignmentOfCardHorizontalhorizontal
inputRadius100px
borderRadius5px
mobileNumberRegex
bankEFTAccountNumber
pnpInstructionSMSTemplateId
pnpDepositRangeRange of accepted values for PnP payments - .e.g. 50-3000
pnpAmountRoundingThe logic for rounding PnP payments to whole numbers - default HALF_UP
errorCodes
  • Sandbox *- <property>public.tenant.card-payments-pwa-sandbox.ukheshe.rocks.errorcodes<property>
  • Production *- <property>public.tenant.card-payments-pwa.ukheshe.co.za.errorcodes<property>
imageBase64data:image/png;base64 (Logo is added to an image to Base64 convert)
virtualCardTemplateBase64data:image/png;base64 (Logo is added to an image to Base64 convert)
successIconBase64data:image/png;base64 (Logo is added to an image to Base64 convert)
lockIconBase64data:image/png;base64 (Logo is added to an image to Base64 convert)
cardCSSpublic.tenant.{tenantID}.card.css - this defines the CSS for displaying custom cards

Example cardCSS public property: public.tenant.{tenantID}.card.css:

{
"alignmentOfCardHorizontal": "true",
"cardBackground": {
    "backgroundImage": "url(data:image/png;base64,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)",
    "height": "191px",
    "width": "300px",
    "borderRadius": "8px",
    "backgroundSize": "cover"
  },
  "gridCardNumber": {
    "letterSpacing": "3px",
    "display": "flex",
    "gap": "8px",
    "marginLeft": "4%",
    "marginTop": "26%"
  },
  "gridValidThru": {
    "display": "flex",
    "gap": "4px",
    "marginTop": "8%",
    "marginLeft": "6%"
  },
  "gridCvv": {
    "display": "flex",
    "gap": "4px",
    "marginTop": "-8.7%",
    "marginLeft": "34%"
  },
   "typoCardNumber": {
    "fontSize": "12px",
    "fontWeight": "500",
    "padding": "0px 6px",
    "border": "1pxsolid",
    "borderRadius": "2px",
    "color": "#ffffff",
	"cursor":"pointer"
  },
  "copyDivStyle": {
    "display": "flex",
    "justifyContent": "center",
    "alignItems": "center"
  },
    "typoValidThruAndCvv": {
    "fontSize": "10px",
    "fontWeight": "500",
    "padding": "0px 6px",
    "border": "1pxsolid",
    "borderRadius": "2px",
    "color": "#ffffff",
	"cursor":"pointer"
  }
}

Property to configure termsAndConditions on the card-ui captive portal: <property>public.tenant.{tenantid}.cardui.tnc<property>

The following parameters can be configured:

PropertyProperty Value
termsAndConditions<property>public.tenant.{tenantID}.cardui.tnc<property>
footerBackgroundColor#007834
footerTextColor#000000
partnerLogopublicly accessible image
securePaymentByLogopublicly accessible image

These configurations can also be managed through the Admin Portal at an Organisation level:

Captive portal configuration in the Admin Portal

Captive portal configuration in the Admin Portal

Run the Captive Portal/Card UI in an iFrame

The captive portal (card UI) can be embedded directly inside a tenant's own page using an <iframe>, so the customer completes payment without leaving the page. Card data is captured on Eclipse's PCI-compliant origin, keeping the tenant's page out of PCI scope.

To generate the payment link itself, see Hosted Checkout. To brand the embedded UI, see Customization of Eclipse Hosted and Captive Portal UI above.

Prerequisites

Step 1 — Resolve the completion URL before embedding

The completionUrl returned when creating a payment is a short link of the form .../t/XXXX, which responds with an HTTP 307 redirect to the card-UI URL.

🚧

Do not set the /t/XXXX link as the iframe src directly

A browser following a cross-origin 307 inside a third-party iframe aborts the load (net::ERR_ABORTED) and the frame renders blank. Resolve the redirect once, server-side, and embed the resolved URL instead.

Resolve it on the backend by reading the Location header without following the redirect:

curl -s -D - -o /dev/null 'https://eclipse-java-sandbox.ukheshe.rocks/t/XXXX' | grep -i '^location'
# location: https://card-payments-pwa-sandbox.ukheshe.rocks/payments-portal/card-ui?tenantId=...&paymentId=...&...

Step 2 — Embed the resolved URL

<div style="border:1px solid #e2e6ea;border-radius:10px;overflow:hidden;">
  <iframe
    id="paymentFrame"
    title="Secure card payment"
    allow="payment"
    style="width:100%;height:720px;border:0;display:block;">
  </iframe>
</div>

<script>
  // Fetch the resolved URL + paymentId from your backend, then embed.
  const res = await fetch('/api/create-payment', { method: 'POST' });
  const { resolvedUrl, paymentId } = await res.json();
  document.getElementById('paymentFrame').src = resolvedUrl;
</script>

Step 3 — Redirect vs. messaging

The card UI can either redirect the frame on completion, or stay in place and post a status message to the parent — controlled per request:

  • Include landingUrl → on completion the frame redirects to that URL.
  • Exclude landingUrl → no redirect; the card UI posts the status to the parent via postMessage, leaving the parent page in control. Use this for a seamless embedded experience.

Statuses:

StatusDescription
'CANCELLED'Terminate the journey
'ERROR_PERM'Permanent failure scenarios
'ERROR_TEMP'Temporary error scenarios
'PENDING'Pending scenarios
'SUCCESSFUL'Successful scenarios
'TIMEOUT'Timeout scenarios

The captive portal includes multiple journeys, and each journey returns the appropriate callback status message to the parent.

Journeys:

  • paymentLink
  • makePayment
  • pnpCashDeposit
  • eftPayment
  • add-cof
  • createCap
  • resetCap
  • viewVirtualCard

Step 4 — Handle the callback status (parent-side)

When a journey completes, the card UI posts this message to the parent window:

{
  "eftCaptivePortalCallbackResponse": {
    "type": "makePayment",
    "status": "SUCCESSFUL"
  }
}

status is one of the values in the Statuses table above; type is one of the Journeys above. Example listener:

window.addEventListener('message', (event) => {
  // Verify the sender: compare event.origin to your card-UI origin.
  const data = event.data;
  const res = data && data.eftCaptivePortalCallbackResponse;
  if (!res) return;

  switch (String(res.status).toUpperCase()) {
    case 'SUCCESSFUL':                 /* show success, then confirm server-side */ break;
    case 'PENDING':                    /* keep waiting */ break;
    case 'CANCELLED':
    case 'ERROR_PERM':
    case 'ERROR_TEMP':
    case 'TIMEOUT':                    /* show failure */ break;
  }
});

Step 5 — Confirm the outcome server-side (required)

⚠️

Warning

The postMessage status is a display hint only. Never fulfil an order, release goods or credit a wallet on the client-side message alone — the visual "successful" screen can appear while the payment is still PENDING server-side.

Confirm the real outcome using either:

  • The callbackUrl webhook supplied when the payment was created (the authoritative server-to-server notification), or
  • A status poll of the payment:
GET {baseUrl}/eclipse-conductor/rest/v1/tenants/{tenantId}/payments/{paymentId}
Authorization: Bearer {token}
{ "paymentId": 0000000, "status": "PENDING", "amount": 1, "currency": "ZAR" }

Poll (proxied through the tenant's backend so the token stays private) until the status is terminal, then act on it.

Security notes

  • Create payments and poll status from the backend; never expose the API token to the browser.
  • Validate event.origin in the message listener; do not accept messages from arbitrary origins.
  • Confirm server-side (webhook or status poll) before fulfilling — the iframe result and client-side message are display-only.

Example branded screens

Pin set

View card

Payment link (hosted checkout)

Bring Your Own Hosted Checkout

Instead of landing customers on Eclipse's branded checkout, a tenant can point payment links at a page hosted on their own infrastructure. Eclipse redirects the customer there — with the payment details passed as query parameters — instead of to Eclipse's captive portal. This is configured with the same tenant property used for Customization of Eclipse Hosted and Captive Portal UI above: captive.portal.config.baseUrl.

Use Cases

  • A fully white-labelled checkout that never shows an ukheshe.live or ukheshe.rocks domain to the customer.
  • Running your own payment-method selection screen (EFT instructions, closed-loop wallet, cash deposit, etc.) in front of Eclipse, falling back to Eclipse only for the card leg.
  • Embedding checkout inside a native app's webview under the tenant's own domain.

PCI Compliance Limitation

📘

Note

This is the single most important constraint on this feature — read it before implementing.

Tenant PCI statusWhat you can do
PCI-compliant (pciCompliant tenant config = true)Your hosted checkout can own the entire journey for all payment types, including capturing card details yourself and submitting them to the Eclipse payments API.
Not PCI-compliantYour hosted checkout can still be the return URL for payment links (e.g. to run your own branded landing/method-selection page), but it must not capture or transmit raw card data. For the card leg specifically, the customer must be handed off to Eclipse's own captive portal, which runs inside Eclipse's PCI-compliant environment.

This isn't just policy — it's enforced server-side. If a non-PCI-compliant tenant submits a payment with raw card data (paymentCardData), the API rejects it:

[{"code":"CON049","description":"Tenant must be PCI Compliant to pass the payment card data"}]

For the card leg, hand the customer to Eclipse's own captive portal using the default card-UI URL (not your captive.portal.config.baseUrl override) — see Run the Captive Portal/Card UI in an iFrame above for the embed/redirect and callback mechanics. Use landingUrl (see below) to bring the customer back to your own checkout once that leg completes.

Prerequisites

  • Tenant config captive.portal.config.baseUrl set to your own hosted checkout URL.
  • A page on that URL able to read and act on query-string parameters (below).
  • If not PCI-compliant: a plan for embedding/redirecting to Eclipse's default captive portal for the card leg, and reading the landingUrl you set when creating the payment.

Scoping the Override

captive.portal.config.baseUrl can be overridden at merchant, sub-merchant, or organisation level instead of tenant-wide, letting you run a custom checkout for some merchants/orgs while others keep Eclipse's default. The most specific match wins:

PropertyScope
captive.portal.config.submerchant.{subMerchantName}.baseUrlSub-merchant (checked first)
captive.portal.config.merchant.{merchantName}.baseUrlMerchant
captive.portal.config.org.{organisationId}.baseUrlOrganisation
captive.portal.config.baseUrlTenant-wide default

If none of these are set, Eclipse falls back to its own captive portal (the Sandbox/Production URLs listed under Customization above).

What Eclipse Sends to Your Checkout

When a GLOBAL_PAYMENT_LINK payment is created, Eclipse resolves captive.portal.config.baseUrl for the tenant/org/merchant and appends the payment's details as a query string, then shortens the result. The completionUrl returned in the payment response is that short link (e.g. https://ukheshe.live/t/5vV4A) — it responds with an HTTP 307 redirect to your checkout URL with the parameters below attached.

ParameterAlways presentDescription
tenantIdYesThe tenant the payment belongs to
interactionTypeYesAlways makePayment for a payment link
paymentIdYesUse this to fetch full payment details (see below)
merchantNameNoURL-encoded, if set on the payment
subMerchantNameNoURL-encoded, if set on the payment
referenceNoURL-encoded merchant reference
organisationIdNoAcquiring organisation ID
msisdnNoCustomer's phone number, if known
defaultOptionNoDefault payment method to pre-select

A GLOBAL_REUSABLE_PAYMENT_LINK (reusable/QR-based link) appends the same core parameters plus amount, description (URL-encoded), uniqueId, expiryDate, qrCode, and a signature.

📘

Note

The signature on a reusable link is an HMAC-SHA256 of amount, description, and reference, keyed with the link's HMACKey. It lets you detect tampering with those three fields specifically on reusable links — it is not present on single-use GLOBAL_PAYMENT_LINK links, and it does not cover the rest of the query string. Treat paymentId as the source of truth and re-fetch the payment from the API rather than trusting amount/reference values from the URL. General platform message-signing (HMAC/RSA on webhooks) and full payload encryption (JWE) are covered in Encryption and Integrity — those apply to the callbackUrl webhook and direct API calls, not to this redirect's query string.

Validating the Redirect and Obtaining an authCode

The redirect only carries identifiers, not the full payment, and your checkout does not hold a tenant-level JWT — it isn't an authenticated caller. Before you can do anything else, exchange the redirect's parameters for a short-lived, payment-scoped token by calling the payment-links endpoint, forwarding whichever of amount, reference, description, signature, uniqueId, expiryDate and qrcode were present on the redirect:

GET /eclipse-conductor/rest/v1/payment-links/{paymentId}?amount={amount}&reference={reference}&description={description}&signature={signature}
{
  "paymentId": 4467928,
  "tenantId": 1234,
  "walletId": 197798,
  "amount": 123,
  "currency": "ZAR",
  "status": "PENDING",
  "authCode": "eyJhbGciOiJSUzI1NiJ9..."
}

For a GLOBAL_REUSABLE_PAYMENT_LINK, this re-checks signature against amount, description and reference, and returns a 403 if any of the three was tampered with in transit. A single-use GLOBAL_PAYMENT_LINK skips that check but still returns an authCode.

  • authCode — a JWT valid for 10 minutes, scoped to submitting card data for this paymentId only. It cannot be refreshed; if your customer takes longer than that, call this endpoint again for a fresh one.
  • walletId — the wallet to pay into. Use it as destinationWalletId in the next step.
📘

Note

This is what lets an unauthenticated checkout page submit a real payment. The authCode's narrow scope authorises creating a payment (and, if needed, a temporary card-on-file) for this specific paymentId only — it grants no other access.

Submitting the Payment

Call the payments API with authCode as the bearer token and walletId as destinationWalletId:

POST /eclipse-conductor/rest/v1/tenants/{tenantId}/payments
Authorization: Bearer {authCode}
Content-Type: application/json

{
  "type": "GLOBAL_ECOM_ACQUIRING",
  "amount": 123,
  "currency": "ZAR",
  "destinationWalletId": 197798,
  "paymentMechanism": "CARD"
}

What you add to this body depends on your PCI status from the PCI Compliance Limitation table above:

  • PCI-compliant — include paymentCardData directly in the body and the payment completes immediately.
  • Not PCI-compliant — omit paymentCardData/cardOnFileId and include landingUrl instead. Eclipse responds with a completionUrl rather than completing the payment — embed or redirect to it using the iFrame pattern above so card capture and 3DS happen inside Eclipse's captive portal, not on your page. Eclipse sends the customer to landingUrl once that leg completes.

See GLOBAL_ECOM_ACQUIRING for the full set of request options.

Sending the Customer Back

Set landingUrl in the payment-creation request body (mapped internally to the payment's customerLandingUrl). Once the payment finishes — whether the customer completed it on your own checkout (PCI-compliant tenants) or via Eclipse's captive portal for the card leg (non-PCI tenants) — the customer is sent to that URL.

Confirming the Outcome

As with any Eclipse-hosted flow, the redirect back to landingUrl is a display hint, not proof of payment. Confirm the real outcome server-side — using your own tenant credentials, not the single-use authCode — with the callbackUrl webhook supplied when the payment was created, or by polling:

GET /eclipse-conductor/rest/v1/tenants/{tenantId}/payments/{paymentId}
Authorization: Bearer {jwt}
{ "paymentId": 4467928, "status": "SUCCESSFUL", "amount": 123, "currency": "ZAR" }

Poll until the payment reaches a terminal state before fulfilling an order or crediting a wallet.

MCC and MID logic to deny or allow transactions

A common requirement for card payment processing is to be able to deny or allow transactions based on Merchant Category Code (MCC) and Merchant ID access and deny lists. Eclipse supports a wide degree of flexibility in configuring this behaviour so tenants have fine-tuned control over their transactions.

The following wallet-type attributes determine the logic to deny or access a card transaction:

AttributeDescription
mcc.whitelista white list of approved merchant category codes.
mcc.blacklista blacklist of merchant category codes that should be denied. A common example here is denying gambling-related transactions.
mcc.whitelistRegexA white list regular expression of approved merchant category codes.
mcc.blacklistRegexA blacklist of regular expressions of merchant category codes that should be denied.
mid.whitelistA white list of approved merchant IDs.
mid.blacklistA blacklist of merchant IDs that should be denied.
mid.whitelistRegexA white list of regular expressions of approved merchant IDs.
mid.blacklistRegexA blacklist of regular expression of merchant IDs that should be denied.

Typically customers will have different logic they want to apply, for example:

  • Allow everything unless present on a blacklist
  • Deny everything unless present on a whitelist
  • Allow everything unless present on a blacklist and then the whitelist can override the blacklist
  • Deny everything unless present on a whitelist and then the blacklist can override the whitelist

To cater for this wide range of logic tenants can apply different logic by setting the wallet type attribute: mcc.mid.logic. This refers to a global property mcc.mid.logic.{logic_name} e.g. if mcc.mid.logic=Simple then global property mcc.mid.logic.Simple will be used. These properties define Javassist which determines whether or not the transaction should be allowed.

Below is simple example logic that allows everything unless present on a blacklist. This would typically be the default behaviour with a MccBlacklist defined with MCC 7995 (Gambling) blacklisted.

public boolean isAllowed(String mcc, String mid,
            Boolean inMccWhitelist, Boolean inMccBlacklist,
            Boolean inMidWhitelist, Boolean inMidBlacklist,
            Boolean matchesMccWhitelistRegex, Boolean matchesMccBlacklistRegex,
            Boolean matchesMidWhitelistRegex, Boolean matchesMidBlacklistRegex) {

        return (inMccBlacklist == null || Boolean.FALSE.equals(inMccBlacklist)) && (inMidBlacklist == null || Boolean.FALSE.equals(inMidBlacklist));
    }

Below is an example logic that denies everything unless present on a whitelist and then the blacklist can override the whitelist (if no whitelists present then the transaction is allowed). This would typically cover the gift card or industry card (e.g. fuel) use cases.

public boolean complexBlacklistsPriorityOverWhitelists(String mcc, String mid,
            Boolean inMccWhitelist, Boolean inMccBlacklist,
            Boolean inMidWhitelist, Boolean inMidBlacklist,
            Boolean matchesMccWhitelistRegex, Boolean matchesMccBlacklistRegex,
            Boolean matchesMidWhitelistRegex, Boolean matchesMidBlacklistRegex) {

        if (Boolean.TRUE.equals(inMccBlacklist) || Boolean.TRUE.equals(inMidBlacklist)) return false;  //present in either blacklist 
        if (Boolean.TRUE.equals(inMccWhitelist) || Boolean.TRUE.equals(inMidWhitelist)) return true;  //present in either whitelist 
        if (inMccWhitelist == null && inMidWhitelist == null) return true;    //no whitelists
        return false;
}

Card Tokenisation

Card tokenisation replaces a card’s sensitive Primary Account Number (PAN) with a surrogate value (a token) so that the PAN itself is no longer transmitted or stored in less secure systems. Broadly speaking, there are two types of tokenisation: issuer tokenisation and acquirer tokenisation. Issuer tokenisation is a process mandated for card issuers and includes tasks such as eligibility checks and token lifecycle management. Acquirer tokenisation sits on the merchant or acquiring side and is used for card-on-file and recurring payments. In this case, the acquirer receives a token mapped to the real card, so merchants never handle the PAN directly. In short, issuer tokens are “bank or scheme side” tokens tied to the card product lifecycle, while acquirer tokens are “merchant or acquirer side” tokens tied to the payment processing lifecycle.

Eclipse supports both issuer and acquirer tokenisation.

Acquirer Tokenisation

Eclipse supports the following methods for acquirer tokenisation:

  • Eclipse proprietary tokenisation - when storing a card on file, the PAN is stored and referenced using a unique card on file ID
  • Visa Token Service (VTS) - this utilises Visa's tokenisation service to tokenise Visa cards
  • Mastercard Digital Enablement Service (MDES) - this utilises Mastercard's tokenisation service to tokenise Mastercard cards

Card schemes encourage the use of scheme tokenisation and some services, for example, Visa QR payments, mandate that scheme tokenisation (Visa or Mastercard) be used for transactions.

Storing a card on file:

  1. Eclipse will generate a unique card on file ID - this is Eclipse's proprietary tokenisation
  2. If scheme tokenisation is enabled on the tenant the scheme token provider is called to request a scheme token
  3. The returned token is securely stored as part of the card on file metadata on Eclipse
  4. Eclipse returns the card on file ID as well as the scheme reference to the tenant

Initiating a payment with a tokenised card:

  1. Tenant initiates payment and passes in the Eclipse card on file ID of tokenised card
  2. Eclipse uses the stored scheme token to request a cryptogram from the scheme token provider
  3. Eclipse processes the payment using the scheme token and cryptogram response - this step is dependent on the payment type - e.g. card processing, QR acquiring, etc.
  4. Ultimately the acquiring bank calls the scheme token provider to detokenise the scheme token for the payment

Pre-requisites:

  • Tenant config enableVisaTokenization set to true to enable Visa Token Services
  • Tenant config enableMastercardTokenization set to true to enable Mastercard Digital Enablement Services
  • Tenant config vtsClientAppID set to ukheshe

For example, for API calls to store a card on file please refer to the card on file management section.

For example, API calls to initiate a payment using a tokenised card refer to the card-specific payment use cases e.g. Payment of EMVCO QR.

Issuer Tokenisation

Card tokenisation replaces a card's Primary Account Number (PAN) with a surrogate value -a token - so that the PAN itself is no longer transmitted or stored in less secure systems. Eclipse supports issuer tokenisation for both Card-on-File (CoF) / eCommerce and xPay use cases. This capability applies to cards issued through Eclipse as well as Postilion.

How It Works

When a cardholder adds a card to a digital wallet such as Apple Pay or Google Pay, the real card number is never stored on the device. Instead a Token Service Provider (TSP) like Visa's Token Service (VTS) issues a token — a surrogate value locked to that specific device and wallet. The issuing bank must participate in this process: VTS requires the issuer to validate every card before a token is minted, and to manage tokens over their lifetime.

Eclipse sits between TSPs and the customer's Postilion switch, handling all issuer tokenisation responsibilities on the customer's behalf.

Visa Token Service (VTS)


The diagram above shows the high-level flow across the three parties involved in issuer tokenisation. Visa VTS initiates all inbound requests to Eclipse: eligibility checks, the provisioning decision, ID&V and token notifications. Eclipse orchestrates the response. It queries Postilion for card status, decides whether to approve the token, delivers one-time passcodes to the cardholder, and keeps its own record of every token. The customer's systems interact with Eclipse via the tenant APIs for token lifecycle and PAN update operations.

Visa signs and encrypts every inbound request. Eclipse verifies the signature and decrypts the payload with the issuer keys set up for your tenant during onboarding.

1. VTS Token Request Processing

When a wallet or merchant requests a token for a card, Visa VTS calls Eclipse twice: first to check that the card can be tokenised, then to get the provisioning decision. Without this integration, a BIN cannot be tokenised, and any provisioning attempt fails at the issuer authorisation step.

Eligibility check

Eclipse sends an ISO 8583 account verification request to Postilion. The card is eligible unless Postilion doesn't recognise the PAN (response code 56), or a token already exists for the same card and token requestor. Eclipse also returns the card art profile for the wallet, which is configured per BIN and can be overridden on the wallet type with cardArtworkProfileId.

Provisioning decision

Visa then calls approveProvisioning. Eclipse checks the card with Postilion again, including the expiry date and CVV2, applies its risk checks, stores a token record with status PENDING, and returns an action code:

Action codeMeaningWhen
00ApproveThe card is active and passes the risk checks
85Step-up requiredThe cardholder must complete ID&V. Returned for device tokens (anything other than ECOMMERCE) when no CVV2 was captured, and when the wallet's risk data calls for it
05DeclineThe PAN is unknown, the card is blocked, or the wallet's risk data calls for a decline
54Decline: expiredThe expiry date is wrong or the card has expired
N7Decline: CVV2The CVV2 is wrong

The risk checks use the device and account scores and reason codes that Apple Pay, Google Pay and Samsung Pay send with the request. They are built into Eclipse and are not configurable per BIN.

Key APIs (Visa calls Eclipse):

POST /eclipse-conductor/vtis/v1/checkEligibility
POST /eclipse-conductor/vtis/v2/tokenRequestors/{tokenRequestorID}/tokens/{tokenReferenceID}/approveProvisioning

2. Token ID&V (Identity & Verification)

When the decision is step-up (85), Visa requires the cardholder to confirm they own the card before the token is activated. Visa asks Eclipse which verification methods to offer, the cardholder picks one in their wallet, and for OTP methods Visa generates the passcode and asks Eclipse to deliver it.

Three verification methods are available:

MethodHow it worksNotes
OTPSMSEclipse sends the Visa-generated passcode by SMS to the cardholderUses the mobile number on the card record, falling back to the customer's profile
OTPEMAILEclipse sends the Visa-generated passcode by email to the cardholderUses the email address on the card record, falling back to the customer's profile
CUSTOMERSERVICEThe cardholder calls your call centre, and your agent activates the token through the tenant API (CALL_CENTER_ACTIVATION)The call centre number is set per BIN

The methods offered are set per BIN during onboarding. Eclipse offers only the call centre when the wallet flags the request as high risk, when the cardholder has no mobile number or email address on record, or when the maximum number of OTP attempts has been reached. Passcodes are sent with the issuer.tokenisation.otp.notification template, which can be set per card BIN.

The cardholder enters the passcode in the wallet and Visa validates it. Eclipse does not see the passcode the cardholder enters.

For device binding requests, Eclipse checks that the token matches its own record and always asks for step-up verification.

Key APIs (Visa calls Eclipse):

POST /eclipse-conductor/vtis/v1/retrieveStepUpMethods
POST /eclipse-conductor/vtis/v1/sendPasscode
POST /eclipse-conductor/vtis/v1/tokenRequestors/{tokenRequestorID}/tokens/{tokenReferenceID}/deviceBinding

3. Token Lifecycle Management (TLCM)

Once a token exists, it must be managed over its lifetime. Changes come from two directions.

Changes made by Visa

Visa calls tokenChanged when a token's state changes at Visa. The eventType query parameter is required:

eventTypeWhat Eclipse does
TOKEN_CREATEDUpdates its token record with the token's status, last four digits and expiry
TOKEN_STATUS_UPDATEDUpdates its token record with the token's status, last four digits and expiry
TOKEN_ACTIVATION_STIPRecords the event only

Any other eventType value returns HTTP 400.

Key APIs (Visa calls Eclipse):

POST /eclipse-conductor/vtis/v2/tokenRequestors/{tokenRequestorID}/tokens/{tokenReferenceID}/tokenChanged?eventType={eventType}

Changes made by you

EventTriggerAction
Card or device reported lostCustomer opsSuspend token
Card or device foundCustomer opsResume token
Cardholder verified by call centreCall centreActivate token
Card cancelledCustomer ops or CMSDelete token, or close the PAN (see section 4)
Card replaced or reissuedCMSUpdate the PAN (see section 4)

To suspend, resume, activate or delete a token, call the tenant API. Eclipse sends the change to Visa and updates its own record. The same call works for Mastercard tokens.

Key APIs (customer calls Eclipse):

PUT /eclipse-conductor/rest/v1/tenants/{tenantId}/cards/{cardId}/issuer-card-tokens/{tokenReferenceId}?tokenRequestorId={tokenRequestorId}
Authorization: Bearer {jwt}
Content-Type: application/json

{
  "operationType": "SUSPEND",
  "operationReason": "LOST_DEVICE"
}
FieldTypeRequiredDescription
operationTypestringYesSUSPEND, RESUME, CALL_CENTER_ACTIVATION or DELETE
operationReasonstringYesFRAUD, LOST_CARD, STOLEN_CARD, LOST_DEVICE, STOLEN_DEVICE, CUSTOMER_REQUEST, CLOSED, FOUND_DEVICE, FOUND_CARD or OTHER

To find a card's tokens, and to see each token's current status at Visa, list them with onUs=false:

GET /eclipse-conductor/rest/v1/tenants/{tenantId}/cards/{cardId}/issuer-card-tokens?onUs=false
Authorization: Bearer {jwt}

With onUs=true (the default), Eclipse returns only the token data it holds. With onUs=false, Eclipse also fetches each token's current details from Visa and updates its own record if the status has changed. Token values are masked in the response. If the card has no tokens, the call returns an error rather than an empty list.

Token metadata is also visible to the customer through Visa Access (Visa's issuer portal).

4. PAN / CMS Update — Token Sync

When a card is replaced, reissued with a new expiry date or closed, the tokens linked to it at Visa must be updated. Call the PAN update API when your CMS makes the change. Eclipse sends the update to Visa, which moves the card's tokens to the new PAN or expiry date, or deletes them when the card is closed.

Key APIs (customer calls Eclipse):

PUT /eclipse-conductor/rest/v1/tenants/{tenantId}/cards/{cardId}/issuer-card-tokens/pan
Authorization: Bearer {jwt}
Content-Type: application/json

{
  "replacePan": "{newPan}",
  "replaceExpiry": "0931",
  "reason": "Card replaced"
}
FieldTypeRequiredDescription
replacePanstringConditionalThe new PAN. For an expiry-only change, send the current PAN. Leave out with replaceExpiry to close the card
replaceExpirystringConditionalThe new expiry date in MMYY format. Send it together with replacePan
reasonstringYesFree-text reason for the change
You sendVisa update
replacePan and replaceExpiry with a different PANAccount update: tokens move to the new PAN
replacePan (the current PAN) and replaceExpiryExpiry date update
Neither replacePan nor replaceExpiryAccount closed: tokens are deleted
📘

Note

This call contains a full PAN. Make it only from a PCI DSS-compliant backend, never from a customer device.

5. Push Provisioning

🚧

Not yet available

Push provisioning (where the customer's banking app pushes a card into a digital wallet) is not yet available. The card-provisions endpoints appear in the API reference, but calls to them return an error. Contact your EFT Corporation account manager if you need push provisioning.

API Reference

Eclipse exposes two distinct sets of APIs for issuer tokenisation. Understanding the direction of each call is important when planning the integration.

Inbound from Visa (VTIS — scheme-specific)

These endpoints implement Visa's VTIS (Visa Token Issuer Service) specification. They are called by Visa's VTS system against Eclipse during provisioning and lifecycle events. They are Visa-specific because the protocol is defined by Visa.

POST /eclipse-conductor/vtis/v1/checkEligibility
POST /eclipse-conductor/vtis/v1/retrieveStepUpMethods
POST /eclipse-conductor/vtis/v1/sendPasscode
POST /eclipse-conductor/vtis/v1/tokenRequestors/{tokenRequestorID}/tokens/{tokenReferenceID}/deviceBinding
POST /eclipse-conductor/vtis/v2/tokenRequestors/{tokenRequestorID}/tokens/{tokenReferenceID}/approveProvisioning
POST /eclipse-conductor/vtis/v2/tokenRequestors/{tokenRequestorID}/tokens/{tokenReferenceID}/tokenChanged?eventType={eventType}

eventType on tokenChanged is a required query parameter. Valid values: TOKEN_CREATED, TOKEN_STATUS_UPDATED, TOKEN_ACTIVATION_STIP.

Outbound from Customer (Tenant APIs — scheme-agnostic)

These endpoints are called by the customer's app or systems to view and manage a card's tokens. Listing and lifecycle updates work for both Visa and Mastercard tokens.

GET /eclipse-conductor/rest/v1/tenants/{tenantId}/cards/{cardId}/issuer-card-tokens?onUs={true|false}
GET /eclipse-conductor/rest/v1/tenants/{tenantId}/cards/{cardId}/issuer-card-tokens/{tokenReferenceId}?tokenRequestorId={tokenRequestorId}
PUT /eclipse-conductor/rest/v1/tenants/{tenantId}/cards/{cardId}/issuer-card-tokens/{tokenReferenceId}?tokenRequestorId={tokenRequestorId}
PUT /eclipse-conductor/rest/v1/tenants/{tenantId}/cards/{cardId}/issuer-card-tokens/pan
📘

Note

The single-token GET and the PAN update PUT are Visa only. For Mastercard tokens, use the list endpoint with onUs=false.

📘

VTS vs VTIS

These refer to the same system from different perspectives. VTS (Visa Token Service) is Visa's name for the overall platform. VTIS (Visa Token Issuer Service) is the API specification Visa publishes for issuers to implement — it is the issuer-facing side of VTS.

Token Provisioning Flow

The following describes the full sequence when a cardholder adds a card to a digital wallet (reactive provisioning).

Phase 1 — Eligibility

  1. Cardholder initiates "add card" in their wallet app
  2. Wallet sends a token request to Visa VTS
  3. Visa VTS calls Eclipse: POST /vtis/v1/checkEligibility
  4. Eclipse queries Postilion via ISO message: does this card exist?
  5. Postilion responds; Eclipse returns the eligibility result and card art profile to Visa

Phase 2 — Provisioning decision

  1. Visa calls Eclipse: POST /vtis/v2/.../approveProvisioning
  2. Eclipse checks the card's status, expiry date and CVV2 with Postilion and applies its risk checks
  3. Eclipse returns approve (00), step-up (85) or decline to Visa

Phase 3 — Identity & verification (step-up only)

  1. Visa calls Eclipse: POST /vtis/v1/retrieveStepUpMethods. Eclipse returns the methods available for the card
  2. Cardholder chooses SMS or email; Visa calls POST /vtis/v1/sendPasscode with the passcode
  3. Eclipse sends the passcode to the cardholder
  4. Cardholder enters the passcode in the wallet, and Visa validates it

Phase 4 — Token active

  1. Visa mints the token and returns it to the wallet
  2. Visa calls Eclipse: POST /vtis/v2/.../tokenChanged. Eclipse updates its token record
  3. Token is live — the cardholder can now transact digitally

Mastercard MDES


The diagram above shows the high-level flow across the three parties involved in Mastercard issuer tokenisation. Mastercard MDES (Mastercard Digital Enablement Service) initiates all inbound requests to Eclipse: token authorisation, activation and token notifications. Eclipse orchestrates the response. It checks the card with Postilion, applies the risk rules, sends activation codes to the cardholder, and keeps its own record of every token. The customer's systems interact with Eclipse via the tenant APIs for token lifecycle operations.

Mastercard encrypts the card data in MDES requests. Eclipse decrypts it with the issuer keys set up for your tenant during onboarding.

1. MDES Token Request Processing

When a wallet or merchant requests a token for a card, MDES calls Eclipse to authorise it. Eclipse decrypts the card details and sends a card status enquiry to Postilion. Any response other than 00 declines the request. If the card is in good standing, Eclipse applies the risk rules, stores a token record against the card, and returns its decision to MDES.

DecisionMeaning
APPROVEDThe token is issued with no further checks
REQUIRE_ADDITIONAL_AUTHENTICATIONThe cardholder must complete activation (ID&V) before the token goes live. Eclipse returns the available activation methods with the decision
DECLINEDThe token is not issued

Risk assessment rules

EFT Corporation sets up token risk rules for each card BIN. If a BIN has no rules, Eclipse uses the decision the wallet provider recommends, and declines the request if the wallet provider gives no recommendation.

The standard rule set:

  • Declines the request when the wallet provider's device or account score is 1 or lower, and asks for additional authentication when it is 2 or 3
  • Follows the wallet provider's recommendation to decline or to ask for additional authentication
  • For device tokens (anything other than CLOUD_TOKEN), asks for additional authentication when the wallet account is less than 30 days old, when the cardholder name or mobile number in the request doesn't match the card record, or when no security code (CVC) was captured
  • Declines the request when a token limit below is reached
LimitConfig keyDefault
Tokens for the same cardmdes.risk.tokenCountLimitSamePan20
Tokens on the same devicemdes.risk.tokenLimitSetForSameDevice10
Tokens on the same device in one daymdes.risk.tokenOnDeviceInDay5

Each limit can be changed per BIN. Contact your EFT Corporation account manager to change the rules for your cards.

Key APIs (Mastercard calls Eclipse):

POST /eclipse-conductor/mdes/1/0/authorizeService

2. MDES Token ID&V (Identity & Verification)

When the decision is REQUIRE_ADDITIONAL_AUTHENTICATION, the cardholder must prove they own the card before the token goes live. The cardholder picks one of the activation methods Eclipse offers in their wallet.

Three activation methods are available:

MethodHow it worksNotes
TEXT_TO_CARDHOLDER_NUMBEREclipse sends an activation code by SMS to the cardholder's mobile numberOffered by default
EMAIL_TO_CARDHOLDER_ADDRESSEclipse sends an activation code by email to the cardholder's email addressMust be enabled for the BIN
CARDHOLDER_TO_CALL_MANNED_NUMBERThe cardholder calls your call centre, and your agent activates the token through the tenant API (CALL_CENTER_ACTIVATION)Offered by default. The call centre number is set per BIN

The methods offered are set per BIN during onboarding. Activation codes are sent with the issuer.tokenisation.otp.notification template.

Key APIs (Mastercard calls Eclipse):

POST /eclipse-conductor/mdes/1/0/requestActivationMethods
POST /eclipse-conductor/mdes/1/0/deliverActivationCode
POST /eclipse-conductor/mdes/1/0/notifyServiceActivated

notifyServiceActivated tells Eclipse that the token is live. Eclipse updates its token record with the final token, device and wallet details.

3. MDES Token Lifecycle Management (TLCM)

Once a token exists, it must be managed over its lifetime. Changes come from two directions.

Changes made by Mastercard

MDES calls notifyTokenUpdated when a token changes. Eclipse updates its token record according to the reasonCode:

reasonCodeWhat Eclipse does
STATUS_UPDATEUpdates the token status (ACTIVE, INACTIVE, SUSPENDED, DEACTIVATED), who suspended it, and the token expiry
REDIGITIZATION_COMPLETEStores the new token and token expiry
FUNDING_ACCOUNT_UPDATEUpdates the card details linked to the token, for example after a card replacement
AUTHENTICATION_PERFORMEDUpdates the token expiry
TOKEN_BINDING, ACCOUNT_BINDINGStores the binding and authenticator details
DELETED_FROM_CONSUMER_APP, PAYMENT_ACCOUNT_REFERENCE_UPDATEDNo change

After each update, Eclipse notifies the cardholder using the mdes.notify.token.updated template. SMS is used by default; the delivery method can be set per BIN.

Key APIs (Mastercard calls Eclipse):

POST /eclipse-conductor/mdes/1/0/notifyTokenUpdated

Changes made by you

EventTriggerAction
Device reported lost or stolenCustomer opsSuspend token
Device foundCustomer opsResume token
Cardholder verified by call centreCall centreActivate token
Card cancelledCustomer ops or CMSDelete token

To suspend, resume, activate or delete a token, call the tenant API. Eclipse sends the change to MDES and updates its own record. The same call works for Visa tokens.

Key APIs (customer calls Eclipse):

PUT /eclipse-conductor/rest/v1/tenants/{tenantId}/cards/{cardId}/issuer-card-tokens/{tokenReferenceId}?tokenRequestorId={tokenRequestorId}
Authorization: Bearer {jwt}
Content-Type: application/json

{
  "operationType": "SUSPEND",
  "operationReason": "LOST_DEVICE"
}
FieldTypeRequiredDescription
operationTypestringYesSUSPEND, RESUME, CALL_CENTER_ACTIVATION or DELETE
operationReasonstringYesFRAUD, LOST_CARD, STOLEN_CARD, LOST_DEVICE, STOLEN_DEVICE, CUSTOMER_REQUEST, CLOSED, FOUND_DEVICE, FOUND_CARD or OTHER
operationTypeToken status afterwards
SUSPENDSUSPENDED
RESUMEACTIVE
CALL_CENTER_ACTIVATIONACTIVE
DELETEDEACTIVATED

To find the tokenReferenceId and tokenRequestorId, list the card's tokens:

GET /eclipse-conductor/rest/v1/tenants/{tenantId}/cards/{cardId}/issuer-card-tokens?onUs=false
Authorization: Bearer {jwt}

With onUs=true (the default), Eclipse returns only the token data it holds. With onUs=false, Eclipse also fetches each token's current details from Mastercard. Token values are masked in the response.

4. MDES Suspicious Activity

MDES calls notifySuspiciousEvents when it detects suspicious activity while replenishing a cloud token on a device. Eclipse records each event, then suspends the token both in Eclipse and at Mastercard with the reason "Suspected fraud". To reinstate the token, use the RESUME operation above.

Key APIs (Mastercard calls Eclipse):

POST /eclipse-conductor/mdes/1/0/notifySuspiciousEvents

MDES API Reference

Inbound from Mastercard (MDES — scheme-specific)

These endpoints implement Mastercard's MDES issuer specification. Mastercard's MDES system calls them on Eclipse during provisioning and lifecycle events. They are Mastercard-specific because the protocol is defined by Mastercard.

POST /eclipse-conductor/mdes/1/0/authorizeService
POST /eclipse-conductor/mdes/1/0/requestActivationMethods
POST /eclipse-conductor/mdes/1/0/deliverActivationCode
POST /eclipse-conductor/mdes/1/0/notifyServiceActivated
POST /eclipse-conductor/mdes/1/0/notifyTokenUpdated
POST /eclipse-conductor/mdes/1/0/notifySuspiciousEvents

When a notification can't be processed, Eclipse returns HTTP 200 with errorCode set in the response body: INVALID_FIELD_VALUE (for example an unknown tokenUniqueReference) or INTERNAL_SERVICE_FAILURE.

Outbound from Customer (MDES)

The tenant APIs for listing a card's tokens and changing their status are the same for Visa and Mastercard. See Outbound from Customer (Tenant APIs — scheme-agnostic) in the Visa section above. The single-token GET and the PAN update PUT are Visa only.

📘

MDES events

Eclipse records an event for each MDES interaction: mdes.notify.service.activated, mdes.deliver.activation.code, mdes.notify.token.updated, mdes.notify.suspicious.event and mdes.token.lifecycle. These events are recorded at platform level, not against your tenant, so you can't route them with your tenant's event publisher configuration.

MDES Token Provisioning Flow

The following describes the full sequence when a cardholder adds a Mastercard to a digital wallet.

Phase 1 — Token authorisation

  1. Cardholder initiates "add card" in their wallet app
  2. Wallet sends a token request to Mastercard MDES
  3. MDES calls Eclipse: POST /mdes/1/0/authorizeService
  4. Eclipse queries Postilion via ISO message: is this card active and valid?
  5. Eclipse applies the risk rules and returns APPROVED, DECLINED or REQUIRE_ADDITIONAL_AUTHENTICATION to MDES

Phase 2 — Activation (ID&V), only when additional authentication is required

  1. MDES presents the activation methods to the cardholder; it can call POST /mdes/1/0/requestActivationMethods to fetch them again
  2. Cardholder chooses SMS or email; MDES calls POST /mdes/1/0/deliverActivationCode
  3. Eclipse sends the activation code to the cardholder
  4. Cardholder enters the code in the wallet, and MDES validates it

Phase 3 — Token active

  1. MDES activates the token in the wallet
  2. MDES calls Eclipse: POST /mdes/1/0/notifyServiceActivated
  3. Eclipse stores the final token details. The cardholder can now transact digitally

EFT Corporation can also provide an Issuer Wallet Token Requestor solution — available as an SDK or white-label mobile app — through a trusted technical partner.

Card Production File Creation

A card production batch orders a set of new physical cards for one of your card programmes. You send one request. Eclipse then places the order with Postilion and receives the generated personalisation (perso) file. It gives every card a card pack ID and a QR code, and delivers the completed file to your card bureau for printing. Once the cards are printed, you can link each one to a customer by its pack ID or QR code.

Prerequisites

  • A physical card programme configured for your tenant. The cardProgramName you send must match the Postilion card programme name, the same value set as SubProgramCodeForPhysicalCard on your card wallet type (see Card Enabled Wallet Type and Wallet configurations).
  • Your card bureau, card manufacturer and QR code format configured by EFT Corporation during onboarding.
  • A callback URL that can receive POST requests.
  • Valid JWT with the permissions listed below.

How the process works

  1. You request a production batch for a card programme and a number of cards.
  2. Eclipse places the card order with Postilion. The batch status becomes SENT.
  3. Postilion generates the perso file. Eclipse picks it up, checks its integrity and loads every card into the batch. The batch status becomes DATA_LOADED, and the batch number changes from the BUILDING placeholder to the number in the perso file.
  4. Eclipse assigns a card pack ID and a QR code to every card.
  5. Once every card has a QR code, the batch status becomes DATA_UPLOADING.
  6. Eclipse delivers the completed perso file to your card bureau. The batch status becomes SUCCESS.
StatusMeaning
SENTThe card order was placed with Postilion
DATA_LOADEDThe perso file was received and loaded; card pack IDs and QR codes are being assigned
DATA_UPLOADINGAll cards have QR codes; the file is queued for delivery to your card bureau
SUCCESSThe perso file was delivered to your card bureau. Final status
FAILEDThe order or the perso file load failed. The comment field gives the reason. Final status
📘

Note

Eclipse does not send a callback or email when a batch reaches DATA_UPLOADING or SUCCESS. To confirm that the file reached your card bureau, poll the batch (Step 2) until the status is SUCCESS or FAILED.

Step 1 — Request a production batch

POST /eclipse-conductor/rest/v1/tenants/{tenantId}/batches
Authorization: Bearer {jwt}
Content-Type: application/json

{
  "type": "POSTILION_CARDS",
  "info": "{\"cardProgramName\": \"<card programme name>\", \"numberOfCards\": \"500\"}",
  "email": "[email protected]",
  "callbackUrl": "https://your-server.example.com/card-batches/callback"
}
FieldTypeRequiredDescription
typestringYesMust be POSTILION_CARDS
infostringYesA JSON object written as a string, with cardProgramName (the Postilion card programme name) and numberOfCards (how many cards to produce)
emailstringNoAddress that receives the batch confirmation email. If you leave it out, your tenant's configured card operations address is used
callbackUrlstringYeshttp or https URL, 10–2000 characters, that receives batch status callbacks

Cards in the batch get an expiry date a set number of years from the request date. The default is 5 years; EFT Corporation can change this for your tenant.

Response (200 OK):

{
  "type": "POSTILION_CARDS",
  "info": "{\"batchId\":1234,\"tenantId\":688,\"batchNumber\":\"BUILDING\",\"qrcodeType\":\"RANDOM_10\",\"status\":\"SENT\",\"cardProgramName\":\"<card programme name>\",\"requested\":\"...\",\"email\":\"[email protected]\"}"
}

info is the new batch written as a JSON string. Keep the batchId: you use it to track the batch. batchNumber stays BUILDING until the perso file loads. If status is FAILED, the order was not placed.

Step 2 — Track the batch

Poll the batch until its status is SUCCESS or FAILED.

GET /eclipse-conductor/rest/v1/tenants/{tenantId}/batches/{batchId}?type=POSTILION_CARDS
Authorization: Bearer {jwt}

Response (200 OK):

{
  "type": "POSTILION_CARDS",
  "info": "{\"batchId\":1234,\"tenantId\":688,\"batchNumber\":\"000123\",\"qrcodeType\":\"RANDOM_10\",\"status\":\"SUCCESS\",\"batchType\":\"POSTILION_CARDS\",\"created\":\"...\",\"lastModified\":\"...\"}"
}
📘

Note

Production batches can't be downloaded through this API. file=true is not supported for POSTILION_CARDS. Eclipse delivers the perso file straight to your card bureau.

Notifications

WhenWhat is sent
Batch requestedA confirmation email to email, and a callback to callbackUrl
Perso file loaded (DATA_LOADED)A callback to callbackUrl
Batch failed (FAILED)A callback to callbackUrl

Callbacks are POST requests with this body:

{
  "batchId": 1234,
  "tenantId": 688,
  "batchNumber": "000123",
  "sequenceNumber": "01",
  "qrcodeType": "RANDOM_10",
  "status": "DATA_LOADED",
  "cardProgramName": "<card programme name>",
  "comment": null,
  "requested": "...",
  "lastModified": "..."
}
📘

Note

The callback sent when the batch is requested contains the same JSON as the Step 1 info value, but as a JSON string, so it must be parsed twice. The later callbacks are plain JSON objects.

Configure the confirmation email

Set the email template in the global property mustache.email.postilion.card.file.creation:

#From: ++comms.email.address++
#To: {{data.email}}

#Subject: Card production batch {{data.batchId}} requested for tenant ID {{data.tenantId}}

++email.top++

Batch ID: {{data.batchId}} <br>
Card programme: {{data.cardProgramName}} <br>
Status: {{data.status}} <br>
QR code type: {{data.qrcodeType}} <br>
Requested: {{data.requested}} <br>

++email.bottom++

Card pack IDs and QR codes

Every card in a batch gets a card pack ID and a QR code. These are printed on the card pack so the card can be linked to a customer. The QR code format is set for your tenant during onboarding:

qrcodeTypeQR code source
RANDOM_10Generated by Eclipse, unique within the platform
ZA_MASTERPASSA Masterpass QR code created by Eclipse for each card pack ID
EXTERNAL_REFSupplied by your card bureau or an external system

Link a produced card to a customer

Once the card is printed and handed to the customer, create the card against the customer's wallet using its card pack ID, PAN or QR code. The flow is the same as Do a Physical Card Replacement, without a card being replaced.

Permissions Required

PermissionDescription
EclipseTenantBatch.POSTILION_CARDS.CREATE.AllowedRequest a card production batch. EclipseTenantBatch.CREATE.Allowed also works, but covers every batch type
EclipseTenantBatch.POSTILION_CARDS.READ.AllowedTrack a card production batch. EclipseTenantBatch.READ.Allowed also works, but covers every batch type

Card Expiry Notifications

Eclipse can generate card expiry notifications to inform customers when their cards are approaching expiry. These notifications are produced as events and delivered through the standard Eclipse event-driven notifications framework.

The notification capability uses the same flexible mechanism described in the event-driven notifications section of the developer guide.

Using this approach, card expiry reminders are published as events, and tenants can configure how those events are delivered to customers. Notifications can be sent via email, SMS, or push, depending on the customer’s communication preference and the configured templates.

Prerequisites

Card expiry notifications are controlled at tenant level using the following configuration properties:

PropertyDescription
cardExpiryNotificationEnabledEnables card expiry notification events for the tenant. Example value: true/false
expireWithinMonthNumber of months before the card expiry date when notification events should be generated. Example value: 2
eventPublishers.card.expiry.notificationPublishes card expiry events to the Eclipse notification framework. Example value: com.ukheshe.eclipse.conductor.listener.EclipseEventNotificationListener
events.notification.template.card.expiry.notificationDefines the Handlebars or Mustache template used for the notification. Example value: cardExpiryNotification

Notification Templates

Notifications are generated using the Eclipse template engine. Tenants can define templates that send email, SMS, or other message types based on customer preferences.

The example below shows a Handlebars template that sends an email by default, or an SMS if the customer preference is set to SMS.

Example Handlebars template

#Type: Handlebars
{{!-- ================= EMAIL (default if null) ================= --}}
{{#if (and (or (eq data.communicationPreference "EMAIL") (eq data.communicationPreference null) (eq data.communicationPreference "")) data.email)}}
#EMAIL-Start
#From: ++comms.email.address++
#To: {{data.email}}
#Subject: Card Expiry Notification

<p>Dear {{data.name}},</p>

<p>We hope this email finds you well.</p>

<p>
This is a reminder that your card ending in
<strong>{{data.cardLastFour}}</strong>
will expire on <strong>{{data.expiry_month}}/{{data.expiry_year}}</strong>.
To avoid any disruption in your services, please update or renew your card details.
</p>

<p>To ensure uninterrupted service, you can update your card details by:</p>

<ul>
  <li>Logging into your account</li>
  <li>Visiting our website</li>
  <li>Contacting customer support</li>
</ul>

<p>
<strong>Important:</strong>
If your card is not updated before the expiry date, recurring payments or automatic transactions may fail.
</p>

<p>
If you have already updated your details, please ignore this message.
Otherwise, we recommend taking action at the earliest convenience.
</p>

<p>
Best regards,<br>
The EFT Team
</p>

#EMAIL-End
{{/if}}

{{!-- ===================== SMS ===================== --}}
{{#if (and (eq data.communicationPreference "SMS") data.phone)}}
#SMS-Start
#To: {{data.phone}}

Hi {{data.name}}, your card ending in {{data.cardLastFour}} will expire on {{data.expiry_month}}/{{data.expiry_year}}.
Please update your card details to avoid service disruption.

Sent by EFT
#SMS-End
{{/if}}

Did this page help you?