Notifications
Notifications¶
General¶
Receiving push notifications and showing in-app notifications is a task for the host app. When a user taps on an InvestSuite notification, the host app needs to:
- Ensure the Flutter engine is started
- Call the
handleNotificationmethod on theHandoversToFlutterService
The SDK will then navigate to the appropriate screen based on the notification data.
Notification Data Structure¶
Notifications use the InvestSuiteNotificationData message:
message InvestSuiteNotificationData {
string id = 1; // Unique notification identifier
string title = 2; // Notification title
string body = 3; // Notification body text
string type = 4; // Notification type (see types below)
string module = 5; // SDK module: "ROBO" or "SELF"
int64 createdAt = 6; // Timestamp in milliseconds
map<string, string> data = 7; // Additional data (portfolio_id, amount, etc.)
}
Notification Types¶
When the host app calls handleNotification, the SDK opens the deeplink corresponding to the notification type. The Deeplink URL column below shows the route that will be opened. Path parameters (e.g. :portfolioId) are populated from the data map (see Additional Data Fields).
Alternatively, the host app can decide to handle the deeplink itself (for example to apply custom navigation logic) by using the navigateTo handover with the same deeplink URL instead of calling handleNotification.
Robo Module¶
| Type | Description | Example body | Deeplink URL |
|---|---|---|---|
NEW_UNAUTHORIZED_TRANSACTION |
Unsigned transaction requiring approval | "You have 1 unsigned transaction" | /unsigned-transactions/:transaction_type/:transaction_id |
POLICY_CONSTRAINT_VIOLATION |
Opportunity to optimise portfolio | "We found an opportunity to further optimise your portfolio" | /robo/portfolio/:portfolioId/results/return |
ROBO_POLICY_CONSTRAINT_VIOLATION |
Policy constraint violation on portfolio | "Congratulations! Your portfolio has been activated and now ready for investment." | — (no in-app handler; notification is shown without navigation) |
PORTFOLIO_ACTIVATED |
Portfolio has been activated | "Congratulations! Your portfolio has been activated and now ready for investment." | / |
FIRST_TIME_CASH_RECEIVED |
First deposit received in portfolio | "Congratulations! Your funds have been received!" | /robo/portfolio/:portfolioId/results/return |
FIRST_TIME_ASSETS_PURCHASED |
First assets purchased in portfolio | "Your journey has started! Your funds have now been invested." | /robo/portfolio/:portfolioId/results/return |
CASH_RECEIVED |
Cash received in portfolio | "Another step towards your goal! Your funds have been received and will be invested soon." | /robo/portfolio/:portfolioId/history/funding |
ASSETS_PURCHASED |
Assets purchased in portfolio | "Your portfolio has been optimised, and new funds invested." | /robo/portfolio/:portfolioId/history/activity |
ASSETS_SOLD |
Assets sold from portfolio | "Assets have been sold to free up funds for your withdrawal instruction." | /robo/portfolio/:portfolioId/history/activity |
CASH_SENT |
Cash sent from portfolio to bank account | "Your funds are now on their way to your bank account." | /robo/portfolio/:portfolioId/history/funding |
REBALANCE_OUT_OF_BOUNDS |
Portfolio rebalanced due to drift | "Your portfolio was optimised to keep it in line with your risk profile!" | /robo/portfolio/:portfolioId/history/activity |
FREE_REBALANCE |
Free portfolio rebalance | "Your portfolio was optimised to ensure you are well positioned for the future" | /robo/portfolio/:portfolioId/history/activity |
PORTFOLIO_EDIT_INCOMPLETE |
Portfolio edits not yet finalised | "Your recent portfolio edits are incomplete, please finalise your changes to update your portfolio" | /robo/portfolio/:portfolioId/results/return |
MONTHLY_SAVINGS_REMINDER |
Reminder for monthly savings plan | "Just a gentle reminder of your planned monthly savings goals. Investing monthly helps to reach your goals." | /robo/portfolio/:portfolioId/history/activity |
ADVISORY_CASH_RECEIVED |
New funds received for advisory portfolio | "New funds have been received! Review and approve a proposal to have them invested." | /robo/portfolio/:portfolioId/results/return |
Self Investor Module¶
| Type | Description | Example body | Deeplink URL |
|---|---|---|---|
NEW_UNAUTHORIZED_TRANSACTION |
Unsigned transaction requiring approval | "You have 1 unsigned transaction" | /unsigned-transactions/:transaction_type/:transaction_id |
CASH_DEPOSIT_EXECUTED |
Cash deposit was processed | "Incoming cash transfer: 11.316,50 USD" | /self/portfolio/:portfolioId/composition/cash/history |
CASH_WITHDRAWAL_EXECUTED |
Cash withdrawal was processed | "Outgoing cash transfer: 2.500 USD" | /self/portfolio/:portfolioId/composition/cash/history |
BUY_ORDER_EXECUTED |
Buy order was executed | "Purchase of 5 Apple Corp. at 95,16 USD. Net total: 503,16 USD." | /self/portfolio/:portfolioId/composition/orders/history/tradeticket/:trade_ticket_id |
SELL_ORDER_EXECUTED |
Sell order was executed | "Sale of 5 Apple Corp. at 95,16 USD. Net total: 489,93 USD." | /self/portfolio/:portfolioId/composition/orders/history/tradeticket/:trade_ticket_id |
ORDER_PLACEMENT_FAILED |
Order placement failed | "Attention: your order Apple Corp. failed." | /self/portfolio/:portfolioId/composition/orders/overview |
ORDER_CANCELLATION_FAILED |
Order cancellation failed | "Attention: your order cancellation Apple Corp. failed." | /self/portfolio/:portfolioId/composition/orders/overview |
ORDER_EXPIRED |
Order has expired | "Your order Apple Corp. expired." | /self/portfolio/:portfolioId/composition/orders/history |
ORDER_CANCELLED_BY_USER |
Order cancelled by the user | "Your order Apple Corp. is cancelled." | /self/portfolio/:portfolioId/composition/orders/history |
ORDER_CANCELLED_BY_BROKER |
Order cancelled by the broker | "Your order Apple Corp. is cancelled." | /self/portfolio/:portfolioId/composition/orders/history |
ORDER_MODIFIED |
Order was modified | "Your order Apple Corp. is modified." | /self/portfolio/:portfolioId/composition/orders/overview |
ORDER_MODIFICATION_FAILED |
Order modification failed | "Attention: your order modification Apple Corp. failed." | /self/portfolio/:portfolioId/composition/orders/overview |
Additional Data Fields¶
The data map can contain notification-specific fields:
| Field | Description |
|---|---|
portfolio_id |
The portfolio related to this notification |
amount |
Transaction amount (as string) |
currency_code |
Currency code (e.g., "EUR", "USD") |
transaction_type |
Transaction type identifier (for NEW_UNAUTHORIZED_TRANSACTION) |
transaction_id |
Transaction identifier (for NEW_UNAUTHORIZED_TRANSACTION) |
Usage¶
val notificationData = HandoversToFlutterServiceOuterClass.InvestSuiteNotificationData.newBuilder()
.setId("notification-123")
.setTitle("Deposit Received")
.setBody("Your deposit of €1,234.50 has been processed")
.setType("CASH_DEPOSIT_EXECUTED")
.setModule("ROBO")
.setCreatedAt(System.currentTimeMillis())
.putData("portfolio_id", "P-ABC123")
.putData("amount", "1234.50")
.putData("currency_code", "EUR")
.build()
val request = HandoversToFlutterServiceOuterClass.HandleNotificationRequest.newBuilder()
.setNotificationData(notificationData)
.build()
InvestSuiteEmbedding.instance().handoversToFlutterService().handleNotification(request)
Info
You can check out the Android example app to see how notification handling works.
Task {
var notificationData = InvestSuiteNotificationData()
notificationData.id = "notification-123"
notificationData.title = "Deposit Received"
notificationData.body = "Your deposit of €1,234.50 has been processed"
notificationData.type = "CASH_DEPOSIT_EXECUTED"
notificationData.module = "ROBO"
notificationData.createdAt = Int64(Date().timeIntervalSince1970 * 1000)
notificationData.data = [
"portfolio_id": "P-ABC123",
"amount": "1234.50",
"currency_code": "EUR"
]
var request = HandleNotificationRequest()
request.notificationData = notificationData
let clientRequest = FlutterEmbeddingGRPCCore.ClientRequest<HandleNotificationRequest>(message: request)
try await InvestSuiteEmbedding.shared.handoversToFlutterService().handleNotification(request: clientRequest)
}
Info
You can check out the iOS example app to see how notification handling works.
const notificationData = InvestSuiteNotificationData.create({
id: 'notification-123',
title: 'Deposit Received',
body: 'Your deposit of €1,234.50 has been processed',
type: 'CASH_DEPOSIT_EXECUTED',
module: 'ROBO',
createdAt: BigInt(Date.now()),
data: {
portfolio_id: 'P-ABC123',
amount: '1234.50',
currency_code: 'EUR',
},
});
const request = HandleNotificationRequest.create({
notificationData,
});
await handoversToFlutterServiceClient.handleNotification(request);
Info
You can check out the React Native example app for more reference on how this works.
const notificationData = InvestSuiteNotificationData.create({
id: 'notification-123',
title: 'Deposit Received',
body: 'Your deposit of €1,234.50 has been processed',
type: 'CASH_DEPOSIT_EXECUTED',
module: 'ROBO',
createdAt: BigInt(Date.now()),
data: {
portfolio_id: 'P-ABC123',
amount: '1234.50',
currency_code: 'EUR',
},
});
const request = HandleNotificationRequest.create({
notificationData,
});
await handoversToFlutterServiceClient.handleNotification(request);
const notificationData = InvestSuiteNotificationData.create({
id: 'notification-123',
title: 'Deposit Received',
body: 'Your deposit of €1,234.50 has been processed',
type: 'CASH_DEPOSIT_EXECUTED',
module: 'ROBO',
createdAt: BigInt(Date.now()),
data: {
portfolio_id: 'P-ABC123',
amount: '1234.50',
currency_code: 'EUR',
},
});
const request = HandleNotificationRequest.create({
notificationData,
});
const client = this.embeddingService.handoversToFlutterServiceClient();
await client.handleNotification(request);