---
updatedAt: 2026-05-19T19:37:26.000Z
agentTools:
  projectIndex: https://developer.eftcorp.com/llms.txt
---

# Tenant Initiated Notifications

Eclipse allows tenants to send notifications to their customers in the form of SMS, email, and in-application push notifications.

## SMS and Email Notifications

Email and SMS notifications can be sent to customers using the [notifications endpoint](https://developer.eftcorp.com/reference/post_eclipse-conductor-rest-v1-tenants-tenantid-notifications).

Eclipse uses the Mustache web template system to define the content of the email or SMS. Mustache parameters are passed in the `data` field in JSON format. Data is bound to a specific Mustache template, so the keys in `data` must match the placeholder keys used in the template.

For example, `"data": "{\"name\": \"Thabo\"}"` will pass the value `"Thabo"` to replace the `{{name}}` key in the Mustache template.

For easy sending of custom SMS messages there is a pre-existing generic Mustache template that allows tenants to send custom messages to customers as follows:

```json
POST /eclipse-conductor/rest/v1/tenants/{tenantId}/notifications
{
  "type": "SMS",
  "data": "{\"data\": \"Your OTP is 482917. Valid for 5 minutes.\", \"phone\": \"+27823456789\"}",
  "templateId": "generic"
}
```

The permission **Notification.CREATE.Allowed** must be enabled for the user initiating the request (typically the `TENANT_SYSTEM` user).

### Sending an Email Notification

To send an email using a custom template:

```json
POST /eclipse-conductor/rest/v1/tenants/{tenantId}/notifications
{
  "type": "EMAIL",
  "templateId": "transactionReceiptTemplate",
  "data": "{\"name\": \"Thabo Nkosi\", \"amount\": \"250.00\", \"currency\": \"ZAR\", \"reference\": \"TFR-20240315-0042\"}"
}
```

The template `transactionReceiptTemplate` must be defined as a global property on the tenant (see Template Structure below).

### SMS Gateways

Eclipse supports multiple SMS gateway integrations. The gateway used for a given tenant and phone number prefix is controlled by tenant configuration.

| SMS Gateway                     | Provider Class                                                    |
| :------------------------------ | :---------------------------------------------------------------- |
| AWS Simple Notification Service | com.ukheshe.libraries.messaging.sms.SnsSmsProvider                |
| DTB                             | com.ukheshe.libraries.messaging.sms.DTBSmsProvider                |
| Infobip                         | com.ukheshe.libraries.messaging.sms.InfobipSmsProvider            |
| Apprentice Valley               | com.ukheshe.libraries.messaging.sms.ApprenticeValleySmsProviderV2 |

The SMS gateway is controlled by the following tenant config keys:

| Config Key                  | Description                                    | Example Value                                                           |
| :-------------------------- | :--------------------------------------------- | :---------------------------------------------------------------------- |
| `smsProviderClass`          | Default SMS gateway for all traffic            | `com.ukheshe.libraries.messaging.sms.SnsSmsProvider`                    |
| `smsRoutingConfig`          | Per-prefix gateway routing (regex=class pairs) | `^27=com.ukheshe.libraries.messaging.sms.ApprenticeValleySmsProviderV2` |
| `infobip.sms.config.url`    | Infobip API endpoint URL                       | `https://qy6pl2.api.infobip.com/sms/2/text/advanced`                    |
| `infobip.sms.config.apiKey` | API key for Infobip authentication             | `Bearer abc123xyz...`                                                   |
| `infobip.sms.config.from`   | Sender name displayed to recipients            | `MyBank`                                                                |

> **SA Routing Example:** To route all South African numbers (`+27`) through Apprentice Valley while keeping all other traffic on AWS SNS, set `smsRoutingConfig` to `^27=com.ukheshe.libraries.messaging.sms.ApprenticeValleySmsProviderV2` and `smsProviderClass` to `com.ukheshe.libraries.messaging.sms.SnsSmsProvider`.

## In-Application Push Notifications

Eclipse can send in-app push notifications using the [device messages endpoint](https://developer.eftcorp.com/reference/post_eclipse-conductor-rest-v1-tenants-tenantid-customers-customerid-device-messages). Currently Firebase Cloud Messaging (FCM) is supported.

**Prerequisites**

* Tenant config `messaging.firebase.config` must be set to the Firebase service account key JSON for the specific mobile application.

### Step 1: Register a Device Token

FCM device tokens must be registered against a customer before push notifications can be sent. Tokens are typically captured by the mobile app at startup and submitted to Eclipse:

```json
POST /eclipse-conductor/rest/v1/tenants/{tenantId}/customers/{customerId}/device-tokens
{
  "tokenType": "FCM",
  "token": "fGz3kP9mT8...long-fcm-registration-token"
}
```

### Step 2: Send a Push Notification

Once a token is registered, push notifications can be sent to the customer using the [device messages endpoint](https://developer.eftcorp.com/reference/post_eclipse-conductor-rest-v1-tenants-tenantid-customers-customerid-device-messages):

```json
POST /eclipse-conductor/rest/v1/tenants/{tenantId}/customers/{customerId}/device-messages
{
  "deviceMessage": {
    "title": "Payment Received",
    "body": "R250.00 was deposited into your wallet. Available balance: R1 050.00."
  },
  "messageType": "FCM",
  "tokenId": 63456345645
}
```

The `tokenId` in the request is the numeric identifier returned by Eclipse when the device token was registered (not the FCM token string itself).

**Limitations**

* Push notifications are not supported for web-based tokens in the Safari browser due to Firebase limitations.
* Progressive Web Applications (PWAs) running on iOS do not support push notifications.

## Unified Template for Tenant Initiated Notifications

Eclipse provides a single unified template mechanism for all customer communications. This design offers:

* **Dynamic channel selection** per user or request.
* **Reduced redundancy** by consolidating templates across channels.
* **Simplified template management** with a single definition controlling multiple outputs.

Templates are implemented using **Handlebars**, enabling powerful runtime logic to determine **which channels** and **what content** to deliver based on user preferences or context.

To send a notification using a unified template, call one of the following endpoints:

```
POST /eclipse-conductor/rest/v1/tenants/{tenantId}/notifications
POST /eclipse-conductor/rest/v1/global/notifications
```

Example request body using a unified template:

```json
POST /eclipse-conductor/rest/v1/tenants/{tenantId}/notifications
{
  "customerId": 12345,
  "data": "{\"sender\": \"Thabo Nkosi\", \"userId\": \"12345\", \"amount\": \"500.00\", \"currency\": \"ZAR\"}",
  "templateId": "walletCreditTemplate",
  "type": "TEMPLATE",
  "deviceMessage": {
    "title": "Funds Received"
  }
}
```

The `templateId` refers to the name of the Handlebars template stored as a global property on the tenant (see Template Structure below).

### Template Structure

Templates support multi-channel content definitions within a single Handlebars file. Channels can include SMS, Email, and Push Notifications. Dynamic content can be fetched from an external URL data source using the `#UrlDataSource` directive.

#### Template Header Directives

| Directive                                           | Purpose                                                               | Example                                               |
| :-------------------------------------------------- | :-------------------------------------------------------------------- | :---------------------------------------------------- |
| `#Type: Handlebars`                                 | Declares the template engine                                          | `#Type: Handlebars`                                   |
| `#UrlDataSource: name=path`                         | Fetches a data object from an Eclipse API path and binds it to `name` | `#UrlDataSource: user=/rest/v1/users/{{data.userId}}` |
| `#SMS-Start` / `#SMS-End`                           | Marks the SMS content block                                           |                                                       |
| `#To: phone`                                        | Recipient phone number for SMS                                        | `#To: {{user.phone1}}`                                |
| `#Email-Start` / `#Email-End`                       | Marks the email content block                                         |                                                       |
| `#From: address`                                    | Sender email address                                                  | `#From: ++comms.email.address++`                      |
| `#To: email`                                        | Recipient email address                                               | `#To: {{user.email1}}`                                |
| `#Subject: text`                                    | Email subject line                                                    | `#Subject: Payment received`                          |
| `#PushNotification-Start` / `#PushNotification-End` | Marks the push notification content block                             |                                                       |
| `++property.name++`                                 | Inlines the value of a global property at render time                 | `++comms.email.address++`                             |

This template example sends communications based on the communication preference stored on the customer object:

```
#Type: Handlebars
#UrlDataSource: user=/rest/v1/users/{{data.userId}}

{{#if (or (eq user.communicationPreference "SMS") (eq user.communicationPreference null))}}
#SMS-Start
#To: {{user.phone1}}
Hi {{user.firstName}}, you received R{{data.amount}} from {{data.sender}}.
#SMS-End
{{/if}}

{{#eq user.communicationPreference "EMAIL"}}
#Email-Start
#From: ++comms.email.address++
#To: {{user.email1}}
#Subject: Payment received
Hi {{user.firstName}}, R{{data.amount}} has been credited to your account from {{data.sender}}.
#Email-End
{{/eq}}

{{#eq user.communicationPreference "PUSH"}}
#PushNotification-Start
R{{data.amount}} received from {{data.sender}}.
#PushNotification-End
{{/eq}}
```

This template example sends a push notification only when the wallet's channel preference is set to `PUSH`:

```
#Type: Handlebars
#UrlDataSource: user=/rest/v1/users/{{data.userId}}

{{#eq wallet.channelPreference "PUSH"}}
#PushNotification-Start
Your wallet received R{{data.amount}}.
#PushNotification-End
{{/eq}}
```

### Storing Templates as Global Properties

Unified Handlebars templates are stored as global properties on the tenant. The property name is used as the `templateId` in the notification request.

For example, to store the template `walletCreditTemplate`:

```
POST /eclipse-conductor/rest/v1/global/properties
{
  "name": "handlebar.template.{tenantId}.walletCreditTemplate",
  "value": "<template content as above>"
}
```

Replace `{tenantId}` with the numeric tenant ID. The `handlebar.template.{tenantId}.` prefix is required for Handlebars templates.