π Notification Service
The Notification Service is a robust and scalable microservice designed to handle multi-channel notifications, including Email, SMS, Slack, and Push notifications. It supports templated messages, rate limiting, retry mechanisms, and integrates seamlessly with external providers like Twilio, Slack, Firebase Cloud Messaging, and SMTP servers.
π Features
- Multi-Channel Notifications: Supports Email, SMS, Slack, and Push notifications with Firebase Cloud Messaging (optional)
- Intelligent Bulk Sending: Automatic bulk optimization for multiple recipients with OS-based grouping and rate limiting
- Advanced Targeted Notifications: Send notifications to specific users, groups, or company-wide audiences with wallet-based filtering
- Wallet-Based Targeting: Target users based on wallet balance criteria (available balance, current balance, withdrawal balance)
- Templated Messages: Dynamic templates for personalized notifications (Thymeleaf for email, Slack blocks for Slack, etc)
- Push Notification Support: Native iOS and Android push notifications with configurable priority levels and display styles (requires Firebase)
- Rate Limiting: Prevents abuse by limiting the number of notifications per recipient and type
- Retry & Circuit Breaker: Automatically retries failed notifications and uses circuit breaker patterns for resilience (Resilience4j)
- Provider Integration: Works with Twilio (SMS), Slack, Firebase (Push - optional), and SMTP for message delivery
- Distributed Tracing & Monitoring: Integrated with Prometheus, Elastic APM, and Loki for monitoring and tracing
- Extensible Design: Easily add new notification providers and templates
- Tenant-Aware: Supports multi-tenant notifications via header-based tenant context
- Dynamic Configuration: Runtime-configurable notification settings with user-friendly dot-notation keys, labels, encryption, and category management
- Trading Platform Optimized: Specialized support for trading notifications including order executions, margin calls, and security alerts
- Type-Safe Priority System: Enum-based priority handling for push notifications with backward compatibility
- Wallet Service Integration: Leverages wallet service filtering for efficient balance-based targeting
- Performance Optimized: Pre-allocated data structures, non-blocking rate limiting, and memory-efficient processing
π οΈ Tech Stack
- Java 17
- Spring Boot 3
- PostgreSQL (Production Database) / H2 (Local Development)
- Redis (Caching)
- RabbitMQ (Message Queue)
- Flyway (Database Migrations)
- Thymeleaf (Email Templating)
- Twilio SDK (SMS)
- Slack API (Slack Notifications)
- Firebase Cloud Messaging (Push Notifications - Optional)
- Resilience4j (Rate Limiting, Circuit Breaker, Retry)
- Prometheus, Elastic APM, Loki (Monitoring & Logging)
ποΈ Architecture
Event-Driven Design
The Notification Service follows an event-driven architecture using RabbitMQ for asynchronous message processing:
- Event Consumer: Listens for
NOTIFICATION_SENTevents from other services - Notification Processing: Processes incoming notification requests and delivers to external providers
- Provider Integration: Supports multiple notification channels (Email, SMS, Slack, Push)
- Resilient Delivery: Implements retry mechanisms and circuit breakers for reliable delivery
Service Flow
Other Services β RabbitMQ β NotificationEventConsumer β NotificationService β External Providers
β
NotificationRequest
β
Email/SMS/Slack/Push
π¦ Installation
Prerequisites
- Java 17
- PostgreSQL (Production) or H2 (Local Development)
- Redis (Optional - for caching)
- RabbitMQ (Optional - for message queuing)
- Firebase Account (Optional - for push notifications)
- Twilio Account (Optional - for SMS)
- Slack App (Optional - for Slack notifications)
Clone the Repository
git clone https://github.com/olara-tech/notification-service-java.git
cd notification-service-java
Configure Environment Variables
Set the required environment variables in your application.yml or export them:
export SMTP_HOST=smtp.zoho.com
export SMTP_PORT=587
export SMTP_USER=devops@olaratech.com
export SMTP_PASSWORD=your_password
export TWILIO_ACCOUNT_SID=your_account_sid
export TWILIO_AUTH_TOKEN=your_auth_token
export TWILIO_PHONE_NUMBER=+1234567890
export SLACK_BOT_TOKEN=your_slack_bot_token
export FIREBASE_SERVICE_ACCOUNT_KEY_PATH=classpath:firebase-service-account.json
export FIREBASE_PROJECT_ID=your-firebase-project-id
export FIREBASE_DATABASE_URL=https://your-project.firebaseio.com/
export FIREBASE_ENABLED=true # Set to false for local development without Firebase
Note: Firebase, Twilio, and Slack configurations are optional. Set
FIREBASE_ENABLED=falsefor local development without Firebase credentials.### Build and Run ```bash ./gradlew clean build ./gradlew bootRun
Local Development Setup
For local development without external dependencies, create an application-local.yml:
spring:
profiles:
active: local
datasource:
url: jdbc:h2:mem:testdb
driver-class-name: org.h2.Driver
flyway:
enabled: true
data:
redis:
host: localhost
port: 6379
rabbitmq:
host: localhost
firebase:
enabled: false # Disable Firebase for local development
slack:
bot-token: token # Placeholder token for local development
Run with local profile:
./gradlew bootRun --args='--spring.profiles.active=local'
π¦ API Endpoints
Note:
X-Tenant-Idis a required header for all API requests. Header:X-Tenant-Id: <tenant-uuid>
1. Send a Notification
Endpoint: POST /api/v1/notifications
Headers:
X-Tenant-Id: <tenant-uuid>
Request Body: (see notification payload examples below)
Response:
{
"id": "123e4567-e89b-12d3-a456-426614174000",
"type": "EMAIL_REGISTRATION",
"recipient": "user@example.com",
"status": "SENT",
"created": "2025-04-24T12:00:00Z"
}
2. Get Notification by ID
Endpoint: GET /api/v1/notifications/{id}
Headers:
X-Tenant-Id: <tenant-uuid>
Response:
{
"id": "123e4567-e89b-12d3-a456-426614174000",
"type": "EMAIL_REGISTRATION",
"recipient": "user@example.com",
"status": "SENT",
"created": "2025-04-24T12:00:00Z",
...
}
π― Targeted Notifications API
The service provides a unified API for sending targeted notifications to specific users, groups, or company-wide audiences. This replaces the previous separate endpoints with a single, flexible interface.
Unified Notification Endpoint
Endpoint: POST /api/v1/notifications/targeted/{scope}/{notificationType}
Headers:
X-Tenant-Id: <tenant-uuid>
Authorization: Bearer <jwt-token>
Path Parameters:
- scope: Notification scope (TARGET, GROUP, or COMPANY)
- notificationType: Notification type enum value (e.g., EMAIL_ORDER_EXECUTED)
Supported Scopes
1. TARGET Scope - Individual Notifications
Send notification to a specific user or device.
Example:
POST /api/v1/notifications/targeted/TARGET/EMAIL_ORDER_EXECUTED
Request Body:
{
"recipient": "user@example.com",
"subject": "Order Executed Successfully",
"content": "Your order has been executed",
"clientReference": "order-123",
"templateVariables": {
"symbol": "AAPL",
"quantity": "100",
"price": "$150.25"
}
}
2. GROUP Scope - Group Notifications
Send notification to groups of users with complex targeting criteria including wallet-based filtering.
Example - Target users with low wallet balance:
POST /api/v1/notifications/targeted/GROUP/EMAIL_PORTFOLIO_LOW_BALANCE_ALERT
Request Body:
{
"subject": "Low Balance Alert",
"content": "Your account balance is getting low",
"clientReference": "balance-alert-456",
"targeting": {
"targetType": "CURRENT_BALANCE",
"currentBalance": {
"amount": 100.00,
"operator": "LESS_THAN"
}
},
"templateVariables": {
"currentBalance": "$50.00",
"recommendedAction": "Please add funds to continue trading"
}
}
Example - Target high-value users:
POST /api/v1/notifications/targeted/GROUP/EMAIL_PORTFOLIO_LOW_BALANCE_ALERT
Request Body:
{
"subject": "Exclusive Investment Opportunity",
"content": "New high-yield investment options available",
"clientReference": "premium-offer-789",
"targeting": {
"targetType": "AVAILABLE_TO_TRADE_BALANCE",
"availableToTrade": {
"amount": 10000.00,
"operator": "GREATER_THAN"
}
},
"templateVariables": {
"investmentOptions": "Premium Bonds, High-Yield ETFs",
"minimumInvestment": "$10,000"
}
}
3. COMPANY Scope - Company-wide Notifications
Send notification to all active users in the company.
Example:
POST /api/v1/notifications/targeted/COMPANY/EMAIL_PORTFOLIO_LOW_BALANCE_ALERT
Request Body:
{
"subject": "Account Balance Alert",
"content": "Your account balance is below the minimum threshold",
"clientReference": "balance-alert-789",
"templateVariables": {
"currentBalance": "$500.00",
"minimumBalance": "$1000.00",
"accountType": "Trading Account"
}
}
Response Format
All targeted notification endpoints return a consistent response:
{
"notificationIds": [
"550e8400-e29b-41d4-a716-446655440000",
"550e8400-e29b-41d4-a716-446655440001"
],
"totalSent": 2,
"scope": "TARGET",
"targetType": null
}
Advanced Targeting Options
The targeting object supports comprehensive filtering including wallet-based criteria:
{
"targeting": {
"targetType": "CURRENT_BALANCE",
"targetUserIds": ["user1", "user2"],
"targetRoles": ["ADMIN", "PREMIUM"],
"targetDepartments": ["IT", "SALES"],
"targetCountry": "US",
"targetCity": "New York",
"targetProductType": "CHECKING",
"targetCurrencyType": "USD",
// Wallet-based filtering
"availableToTrade": {
"amount": 1000.00,
"operator": "GREATER_THAN"
},
"availableBalance": {
"amount": 500.00,
"operator": "LESS_THAN"
},
"currentBalance": {
"amount": 0.00,
"operator": "GREATER_THAN"
},
"withdrawalBalance": {
"amount": 100.00,
"operator": "GREATER_THAN_OR_EQUAL_TO"
},
// Activity filters
"hasOpenOrders": true,
"hasPendingPayouts": false,
"kycStatus": "APPROVED",
"stockHoldingsSymbols": ["AAPL", "TSLA"],
// Portfolio filters - using BalanceFilter format
"portfolioValue": {
"amount": 75000.00,
"operator": "GREATER_THAN"
},
// Processing options
"priority": 1
}
}
Wallet-Based Targeting
The service supports advanced wallet-based targeting using the wallet service's filtering capabilities:
Supported Target Types
- AVAILABLE_TO_TRADE_BALANCE: Target users by available to trade balance
- CURRENT_BALANCE: Target users by current balance
- WITHDRAWAL_BALANCE: Target users by withdrawal balance
- PORTFOLIO_VALUE: Target users by portfolio value
- UNSETTLED_BALANCE: Target users by unsettled balance
- USER_ID: Target specific users by ID
- USER_ROLE: Target users in specific roles
- COUNTRY: Target users in a specific country
- CITY: Target users in a specific city
- PRODUCT_TYPE: Target users by product type
- CURRENCY_TYPE: Target users by currency
- KYC_STATUS: Target users by KYC status
- OPEN_ORDERS: Target users with open orders
- PENDING_PAYOUTS: Target users with pending payouts
- DYNAMIC_FILTER: Target users using custom filter criteria
- KYC_FILTER: Target users by KYC profile criteria
- ALL_USERS: Target all users (company-wide)
Balance Filter Operators
- GREATER_THAN (
>): Balance greater than specified amount - LESS_THAN (
<): Balance less than specified amount - EQUAL_TO (
=): Balance equal to specified amount - GREATER_THAN_OR_EQUAL_TO (
>=): Balance greater than or equal to specified amount - LESS_THAN_OR_EQUAL_TO (
<=): Balance less than or equal to specified amount
Wallet Balance Targeting Examples
Target users with low available balance:
{
"targeting": {
"targetType": "WALLET_BALANCE",
"availableBalance": {
"amount": 100.00,
"operator": "LESS_THAN"
}
}
}
Target users with high current balance:
{
"targeting": {
"targetType": "HIGH_WALLET_BALANCE"
}
}
Target users with zero balance:
{
"targeting": {
"targetType": "ZERO_WALLET_BALANCE"
}
}
Complex wallet filtering:
{
"targeting": {
"targetType": "WALLET_BALANCE",
"currentBalance": {
"amount": 1000.00,
"operator": "GREATER_THAN"
},
"availableToTrade": {
"amount": 500.00,
"operator": "LESS_THAN"
},
"kycIncomplete": false,
"hasOpenOrders": true
}
}
Intelligent Bulk Sending
The service automatically optimizes notification delivery based on recipient count:
Automatic Optimization
- Single Recipient: Uses individual notification sending for efficiency
- Multiple Recipients: Automatically switches to bulk sending for performance
- No Configuration Required: The system intelligently chooses the optimal method
Bulk Sending Features
- OS-Based Grouping: Recipients are grouped by operating system (iOS/Android) for Firebase efficiency
- Batch Processing: Large recipient lists are processed in optimized batches
- Rate Limiting: Non-blocking rate limiting prevents system overload
- Fallback Handling: Failed batches automatically retry with individual sends
- Memory Efficient: Pre-allocated data structures minimize garbage collection
Performance Benefits
- 5x Faster: Bulk sending dramatically improves throughput for large audiences
- Reduced API Calls: Fewer Firebase requests through recipient grouping
- Better Reliability: Circuit breaker patterns and retry mechanisms
- Scalable: Handles thousands of recipients efficiently
Error Responses
- 400 Bad Request: Invalid scope or notification type
- 422 Unprocessable Entity: Invalid targeting configuration
- 500 Internal Server Error: Service processing error
βοΈ Notification Settings API
The service provides a comprehensive API for managing notification settings dynamically. This allows for runtime configuration of notification behaviors, templates, and provider settings without code changes.
Design Pattern: Context-Based Parameter Extraction
All Notification Settings API endpoints use a context-based design where tenant and user information are automatically extracted from request headers via UserInformationContext:
X-Tenant-Idheader is automatically extracted and used for tenant isolationX-User-Idheader is automatically extracted for user-specific settings- No explicit query parameters required for tenant/user identification
- Cleaner API surface with fewer parameters
- Improved security through centralized context management
Example Header:
GET /api/v1/notification-settings/global.email.enabled
X-Tenant-Id: 550e8400-e29b-41d4-a716-446655440000
X-User-Id: 550e8400-e29b-41d4-a716-446655440001
Key Features
- Dot-Notation Keys: Settings use a hierarchical dot-notation (e.g.,
global.email.enabled,sms.provider.twilio.sid) for better organization. - Dynamic Settings: You can create new settings on the fly. If a key is not recognized as a standard system setting, it will be automatically assigned to the
GENERALcategory. - Type Safety: Standard settings have enforced data types (BOOLEAN, STRING, INTEGER, JSON), while dynamic settings default to STRING unless specified.
- Labels: Settings support user-friendly labels for UI display.
1. Create or Update Setting
Endpoint: POST /api/v1/notification-settings
Request Body (Minimal):
{
"settingKey": "global.email.enabled",
"settingValue": "true",
"description": "Master switch to enable or disable all email notifications"
}
Request Body (Full - For Custom Settings):
{
"settingKey": "olara.announcement.enabled",
"settingValue": "true",
"description": "Master switch to enable or disable all olara notifications",
"label": "Olara Announcement Notifications",
"category": "SYSTEM",
"dataType": "BOOLEAN",
"encrypted": false
}
Field Descriptions:
- settingKey (required): The unique key for the setting (e.g., global.email.enabled)
- settingValue (optional): The value of the setting. Validated based on the specified/inferred dataType
- description (optional): Human-readable description. For system settings, defaults to the label from the definition
- label (optional): Display label for UI. Ignored for system settings (uses definition label)
- category (optional): Setting category enum (SECURITY, TRANSACTIONAL, MARKETING, SYSTEM, ACCOUNT, REMINDERS, GENERAL). For system settings, uses the definition category; for custom settings, can be specified
- dataType (optional): Data type enum (STRING, INTEGER, LONG, DOUBLE, BOOLEAN, DATE, DATETIME, JSON, LIST). Uses definition for system settings; required for custom settings
- encrypted (optional): Whether the value should be encrypted at rest (true/false). Uses definition for system settings, defaults to false. When true, values are encrypted before storage and automatically decrypted on retrieval
System vs Custom Settings: - System Settings: Predefined keys (like
global.email.enabled) use metadata from the system definition. Optional metadata fields in the request are ignored - Custom Settings: Unknown keys are created as custom settings. Use metadata fields to define their properties
Data Type Validation & Formats
All notification settings values are validated based on their specified dataType before being stored. Invalid values will be rejected with descriptive error messages.
Supported Data Types
| Data Type | Format | Examples | Validation Rules | Error Example |
|---|---|---|---|---|
| BOOLEAN | true/false (case-insensitive) | "true", "false", "True", "FALSE" |
Only accepts "true" or "false" strings | Input value 'yes' is not a valid BOOLEAN. Accepted values: true, false |
| STRING | Any text | "user@example.com", "SMTP_KEY" |
No specific validation | N/A |
| INTEGER | Whole numbers | "42", "1000", "-50" |
Must be parseable as a 32-bit integer | Input value 'abc' is not a valid INTEGER |
| LONG | Large whole numbers | "9999999999", "1000000000000" |
Must be parseable as a 64-bit integer | Input value '99999999999999999999' exceeds LONG range |
| DOUBLE | Decimal numbers | "3.14", "99.99", "1.5e-10" |
Must be parseable as a double-precision floating-point | Input value '3.14.15' is not a valid DOUBLE |
| DATE | ISO 8601 date format | "2025-12-06", "2024-01-15" |
Must match YYYY-MM-DD pattern | Input value '12/06/2025' is not a valid DATE. Use format: YYYY-MM-DD |
| DATETIME | ISO 8601 datetime format | "2025-12-06T21:23:41Z", "2025-12-06T21:23:41+00:00" |
Must match ISO-8601 format with time and timezone | Input value '2025-12-06 21:23:41' is not a valid DATETIME. Use ISO-8601 format |
| JSON | Valid JSON object/array | '{"key":"value"}', '[1,2,3]' |
No specific validation (valid JSON structure expected) | N/A |
| LIST | Comma-separated values | "item1,item2,item3" |
No specific validation | N/A |
Validation Examples
BOOLEAN - Setting a toggle:
POST /api/v1/notification-settings
{
"settingKey": "global.email.enabled",
"settingValue": "true",
"dataType": "BOOLEAN"
}
β
Success: "true" is valid
β Error: "yes" β "Input value 'yes' is not a valid BOOLEAN. Accepted values: true, false"
INTEGER - Setting a numeric limit:
POST /api/v1/notification-settings
{
"settingKey": "custom.rate.limit.count",
"settingValue": "100",
"dataType": "INTEGER"
}
β
Success: "100" is valid
β Error: "abc" β "Input value 'abc' is not a valid INTEGER"
LONG - Setting a large counter:
POST /api/v1/notification-settings
{
"settingKey": "custom.notification.count",
"settingValue": "9999999999",
"dataType": "LONG"
}
β
Success: "9999999999" is valid
β Error: "99999999999999999999" β "Input value '99999999999999999999' exceeds LONG range"
DOUBLE - Setting a decimal threshold:
POST /api/v1/notification-settings
{
"settingKey": "custom.alert.threshold",
"settingValue": "99.99",
"dataType": "DOUBLE"
}
β
Success: "99.99" is valid
β Error: "3.14.15" β "Input value '3.14.15' is not a valid DOUBLE"
DATE - Setting an expiration date:
POST /api/v1/notification-settings
{
"settingKey": "custom.offer.expiry.date",
"settingValue": "2025-12-06",
"dataType": "DATE"
}
β
Success: "2025-12-06" is valid
β Error: "12/06/2025" β "Input value '12/06/2025' is not a valid DATE. Use format: YYYY-MM-DD"
DATETIME - Setting an exact timestamp:
POST /api/v1/notification-settings
{
"settingKey": "custom.notification.scheduled.time",
"settingValue": "2025-12-06T21:23:41Z",
"dataType": "DATETIME"
}
β
Success: "2025-12-06T21:23:41Z" is valid
β Error: "2025-12-06 21:23:41" β "Input value '2025-12-06 21:23:41' is not a valid DATETIME. Use ISO-8601 format"
JSON - Setting a configuration object:
POST /api/v1/notification-settings
{
"settingKey": "custom.smtp.config",
"settingValue": "{\"host\":\"smtp.example.com\",\"port\":587}",
"dataType": "JSON"
}
β Success: Valid JSON object is stored β Error: Invalid JSON syntax will be rejected
LIST - Setting multiple values:
POST /api/v1/notification-settings
{
"settingKey": "custom.notification.channels",
"settingValue": "email,sms,push",
"dataType": "LIST"
}
β
Success: "email,sms,push" is valid
Encryption Behavior
Settings can be optionally encrypted for sensitive data like API keys, passwords, and tokens. The encryption is transparent - values are automatically encrypted before storage and decrypted on retrieval.
How Encryption Works
- On Create/Update: If
encrypted: true, the value is encrypted using AES-GCM before being stored in the database - On Retrieval: If
encrypted: true, the value is automatically decrypted when fetched via GET endpoints - Storage: Encrypted values are stored as Base64-encoded ciphertext with an initialization vector (IV)
- Transparent: Consumers of the API see plaintext values; encryption/decryption is handled internally
Encrypted Settings Examples
Encrypting an API key:
POST /api/v1/notification-settings
{
"settingKey": "twilio.api.key",
"settingValue": "your-secret-api-key-12345",
"label": "Twilio API Key",
"category": "SECURITY",
"dataType": "STRING",
"encrypted": true,
"description": "Twilio API key for SMS provider"
}
Response (stored encrypted):
{
"id": "123e4567-e89b-12d3-a456-426614174000",
"settingKey": "twilio.api.key",
"settingValue": "7Hk9jL2mNp3...[encrypted ciphertext]...kQ5xR8vT1",
"encrypted": true,
"createdAt": "2025-12-06T10:30:00Z"
}
Retrieving encrypted settings:
GET /api/v1/notification-settings/twilio.api.key
X-Tenant-Id: 550e8400-e29b-41d4-a716-446655440000
Response (automatically decrypted):
{
"settingKey": "twilio.api.key",
"settingValue": "your-secret-api-key-12345",
"encrypted": true,
"label": "Twilio API Key",
"category": "SECURITY",
"dataType": "STRING"
}
Best Practices for Encryption
- Use encryption for: API keys, passwords, tokens, authentication credentials, PII (Personally Identifiable Information)
- Don't encrypt: Public configuration, feature flags, non-sensitive metadata, category/type information
- Validation: Encrypted values are validated based on their data type before encryption
- Consistency: All encrypted values are decrypted transparently in responses - no client-side handling required
- Security: Encryption keys are managed securely per tenant; values cannot be accessed without proper tenant context
Unencrypted Settings
For non-sensitive settings, encryption can be disabled or omitted:
POST /api/v1/notification-settings
{
"settingKey": "feature.new.dashboard.enabled",
"settingValue": "false",
"label": "New Dashboard Feature",
"category": "SYSTEM",
"dataType": "BOOLEAN",
"encrypted": false,
"description": "Feature flag for new dashboard"
}
2. Get Setting by Key
Endpoint: GET /api/v1/notification-settings/{key}
Headers:
- X-Tenant-Id: Tenant ID (UUID) - automatically extracted from request context
- X-User-Id: User ID (UUID) - automatically extracted from request context
Example:
GET /api/v1/notification-settings/global.email.enabled
Note: The tenant and user context are automatically extracted from request headers via
UserInformationContext. No query parameters are needed.
3. Get All Settings
Endpoint: GET /api/v1/notification-settings
Headers:
- X-Tenant-Id: Tenant ID (UUID) - automatically extracted from request context
Example:
GET /api/v1/notification-settings
Note: The tenant context is automatically extracted from request headers. No explicit parameters required.
4. Get Multiple Settings by Keys
Endpoint: GET /api/v1/notification-settings/bulk?keys=key1,key2,key3
Headers:
- X-Tenant-Id: Tenant ID (UUID) - automatically extracted from request context
Query Parameters:
- keys: Comma-separated list of setting keys to retrieve
Example:
GET /api/v1/notification-settings/bulk?keys=global.email.enabled,security.login.alert.email,transactional.order.executed
5. Batch Create or Update Settings
Endpoint: POST /api/v1/notification-settings/batch
Request Body (Minimal):
[
{
"settingKey": "sms.provider.twilio.sid",
"settingValue": "AC1234567890abcdef",
"description": "Twilio Account SID for SMS provider"
},
{
"settingKey": "sms.provider.twilio.token",
"settingValue": "auth_token_here",
"description": "Twilio Auth Token for SMS provider"
}
]
Request Body (With Custom Metadata):
[
{
"settingKey": "custom.api.key",
"settingValue": "secret_key_value",
"description": "Custom API key",
"category": "SECURITY",
"dataType": "STRING",
"encrypted": true
}
]
6. Admin Operations
Base Endpoint: /api/v1/admin/notification-settings
- Bulk Create:
POST /bulk - Delete Category:
DELETE /category/{category} - Export Settings:
POST /export/{tenantId}
Note: Admin operations automatically extract tenant context from request headers where applicable.
7. Get Available Settings Definitions
Endpoint: GET /api/v1/notification-settings/definitions
Returns a comprehensive list of all available notification settings keys with their metadata (category, data type, default value, label).
Response Example:
[
{
"key": "global.email.enabled",
"label": "Enable Email Notifications",
"category": "SYSTEM",
"dataType": "BOOLEAN",
"defaultValue": "true"
},
{
"key": "security.login.alert.email",
"label": "Login Alert (Email)",
"category": "SECURITY",
"dataType": "BOOLEAN",
"defaultValue": "true"
},
...
]
π Complete Notification Settings Keys Reference
The service supports dynamic management of notification settings through dot-notation keys. Settings are organized into logical categories with type-safe defaults.
System & Global Settings (4 keys)
Control global notification channels across the entire platform.
| Key | Label | Category | Type | Default | Description |
|---|---|---|---|---|---|
global.email.enabled |
Enable Email Notifications | SYSTEM | Boolean | true |
Master switch to enable/disable all email notifications |
global.sms.enabled |
Enable SMS Notifications | SYSTEM | Boolean | true |
Master switch to enable/disable all SMS notifications |
global.push.enabled |
Enable Push Notifications | SYSTEM | Boolean | true |
Master switch to enable/disable all push notifications |
global.in_app.enabled |
Enable In-App Notifications | SYSTEM | Boolean | true |
Master switch to enable/disable all in-app notifications |
Usage Example
# Disable all email notifications globally
POST /api/v1/notification-settings
{
"key": "global.email.enabled",
"value": "false",
"label": "Enable Email Notifications",
"category": "SYSTEM",
"dataType": "BOOLEAN",
"description": "Temporarily disable all email notifications for maintenance"
}
Security Settings (4 keys)
Manage security-related notification settings for alerts and authentication.
| Key | Label | Category | Type | Default | Description |
|---|---|---|---|---|---|
security.login.alert.email |
Login Alert (Email) | SECURITY | Boolean | true |
Alert users of new device logins via email |
security.login.alert.sms |
Login Alert (SMS) | SECURITY | Boolean | false |
Alert users of new device logins via SMS |
password.change.alert |
Password Change Alert | SECURITY | Boolean | true |
Notify users when their password is changed |
security.2fa.otp.enabled |
Two-Factor Authentication OTP | SECURITY | Boolean | true |
Enable/disable OTP delivery for 2FA |
Usage Examples
Enable SMS Login Alerts:
POST /api/v1/notification-settings
{
"key": "security.login.alert.sms",
"value": "true",
"label": "Login Alert (SMS)",
"category": "SECURITY",
"dataType": "BOOLEAN",
"description": "Send SMS alerts for new device logins"
}
Disable Password Change Alerts:
POST /api/v1/notification-settings
{
"key": "password.change.alert",
"value": "false",
"label": "Password Change Alert",
"category": "SECURITY",
"dataType": "BOOLEAN",
"description": "Disable password change notifications"
}
Transactional Settings (4 keys)
Control notifications for financial transactions and order executions.
| Key | Label | Category | Type | Default | Description |
|---|---|---|---|---|---|
transactional.deposit.success |
Deposit Successful | TRANSACTIONAL | Boolean | true |
Notify on successful fund deposits |
transactional.withdrawal.success |
Withdrawal Successful | TRANSACTIONAL | Boolean | true |
Notify on successful fund withdrawals |
transactional.payment.received |
Payment Received | TRANSACTIONAL | Boolean | true |
Notify when payments are received |
transactional.order.executed |
Order Executed | TRANSACTIONAL | Boolean | true |
Notify when trades/orders are executed |
Usage Example
Disable Deposit Success Notifications:
POST /api/v1/notification-settings
{
"key": "transactional.deposit.success",
"value": "false",
"label": "Deposit Successful",
"category": "TRANSACTIONAL",
"dataType": "BOOLEAN",
"description": "Disable notifications for successful deposits"
}
Marketing Settings (3 keys)
Manage opt-in/opt-out for marketing and promotional communications.
| Key | Label | Category | Type | Default | Description |
|---|---|---|---|---|---|
marketing.newsletter.subscription |
Newsletter Subscription | MARKETING | Boolean | false |
Enable/disable newsletter subscriptions |
marketing.promotional.offers |
Promotional Offers | MARKETING | Boolean | false |
Enable/disable promotional offer notifications |
marketing.partner.offers |
Partner Offers | MARKETING | Boolean | false |
Enable/disable partner promotional offers |
Usage Example
Enable Promotional Offers:
POST /api/v1/notification-settings
{
"key": "marketing.promotional.offers",
"value": "true",
"label": "Promotional Offers",
"category": "MARKETING",
"dataType": "BOOLEAN",
"description": "User opted in to receive promotional offers"
}
Account Settings (2 keys)
Manage account-related notifications including profile and KYC changes.
| Key | Label | Category | Type | Default | Description |
|---|---|---|---|---|---|
account.profile.update |
Profile Update | ACCOUNT | Boolean | true |
Notify on profile changes |
account.kyc.status.change |
KYC Status Change | ACCOUNT | Boolean | true |
Notify on KYC status updates (approved, rejected, etc.) |
Usage Example
Disable Profile Update Notifications:
POST /api/v1/notification-settings
{
"key": "account.profile.update",
"value": "false",
"label": "Profile Update",
"category": "ACCOUNT",
"dataType": "BOOLEAN",
"description": "Disable profile change notifications"
}
Reminder Settings (2 keys)
Control reminder notifications for important actions and upcoming events.
| Key | Label | Category | Type | Default | Description |
|---|---|---|---|---|---|
reminders.cart.abandonment |
Cart Abandonment | REMINDERS | Boolean | true |
Remind users about abandoned shopping carts |
reminders.upcoming.payment |
Upcoming Payment | REMINDERS | Boolean | true |
Remind users about upcoming payments due |
Usage Example
Disable Cart Abandonment Reminders:
POST /api/v1/notification-settings
{
"key": "reminders.cart.abandonment",
"value": "false",
"label": "Cart Abandonment",
"category": "REMINDERS",
"dataType": "BOOLEAN",
"description": "Disable cart abandonment reminder emails"
}
Categories Reference
Settings are organized into the following logical categories. Use these enum values in the category field when creating custom settings:
- SYSTEM: Global platform-wide notification settings (global toggles, master switches)
- SECURITY: Security and authentication related settings (login alerts, password changes, 2FA)
- TRANSACTIONAL: Financial transaction and order notifications (deposits, withdrawals, order execution)
- MARKETING: Marketing and promotional communications (newsletters, offers, promotional content)
- ACCOUNT: Account management and profile settings (profile updates, KYC status changes)
- REMINDERS: Reminders for important actions (cart abandonment, upcoming payments, event reminders)
- GENERAL: Custom user-defined settings (not part of system definitions, default for unknown keys)
Example: Creating a custom SECURITY setting
POST /api/v1/notification-settings
{
"settingKey": "custom.device.auth.required",
"settingValue": "true",
"label": "Require Device Authentication",
"category": "SECURITY",
"dataType": "BOOLEAN"
}
Data Types Reference
All notification settings support the following data types with comprehensive validation:
- BOOLEAN:
trueorfalsevalues (case-insensitive). Used for enable/disable toggles. Only accepts "true" or "false" strings. - STRING: Text values without specific format validation. Used for email addresses, URLs, API keys, text descriptions, etc.
- INTEGER: 32-bit whole numbers. Used for counts, limits, thresholds (e.g., rate limit: 100, retry count: 3)
- LONG: 64-bit whole numbers for large values. Used for large counters, timestamps in milliseconds, large numeric IDs (e.g., notification count: 9999999999)
- DOUBLE: Decimal/floating-point numbers. Used for percentages, thresholds with decimals, monetary amounts (e.g., alert threshold: 99.99, fee percentage: 2.5)
- DATE: ISO 8601 date format (YYYY-MM-DD). Used for expiration dates, schedule dates, date thresholds (e.g., offer expiry: 2025-12-06)
- DATETIME: ISO 8601 datetime format with timezone (e.g., 2025-12-06T21:23:41Z). Used for exact timestamps, scheduled times, audit timestamps
- JSON: Valid JSON objects or arrays. Used for complex configurations, nested settings, template definitions
- LIST: Comma-separated values. Used for enumerations, multiple choice settings, channel lists
User-Level vs Tenant-Level Settings
Settings can be configured at two levels:
Tenant-Level Settings
Apply to all users in a tenant (unless overridden by user-level settings).
POST /api/v1/notification-settings
{
"key": "global.email.enabled",
"value": "true",
"label": "Enable Email Notifications",
"category": "SYSTEM",
"dataType": "BOOLEAN",
"tenantId": "123e4567-e89b-12d3-a456-426614174000"
}
User-Level Settings
Override tenant settings for a specific user (provide userId header or in request).
POST /api/v1/notification-settings
{
"key": "marketing.promotional.offers",
"value": "false",
"label": "Promotional Offers",
"category": "MARKETING",
"dataType": "BOOLEAN",
"userId": "b1a2c3d4-e5f6-7890-1234-56789abcdef0"
}
Setting Resolution Order
The service resolves settings in the following priority order:
- User-Level Settings (if available and userId is provided)
- Tenant-Level Settings (if available)
- Default Values (built-in defaults from the enum)
Encryption
Sensitive settings can be optionally encrypted for storage. Use the encrypted flag in the request:
POST /api/v1/notification-settings
{
"key": "smtp.password",
"value": "secure_password_here",
"label": "SMTP Server Password",
"category": "GENERAL",
"dataType": "STRING",
"encrypted": true,
"description": "Encrypted SMTP server password for email provider"
}
Batch Operations
Create or update multiple settings in a single request:
POST /api/v1/notification-settings/batch
[
{
"settingKey": "global.email.enabled",
"settingValue": "true",
"category": "SYSTEM",
"dataType": "BOOLEAN"
},
{
"settingKey": "security.login.alert.email",
"settingValue": "true",
"category": "SECURITY",
"dataType": "BOOLEAN"
},
{
"settingKey": "marketing.promotional.offers",
"settingValue": "false",
"category": "MARKETING",
"dataType": "BOOLEAN"
}
]
Batch with Custom Settings and Encryption:
POST /api/v1/notification-settings/batch
[
{
"settingKey": "sms.provider.twilio.sid",
"settingValue": "ACxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"label": "Twilio Account SID",
"category": "SECURITY",
"dataType": "STRING",
"encrypted": true
},
{
"settingKey": "custom.notification.retry.count",
"settingValue": "3",
"label": "Notification Retry Count",
"category": "GENERAL",
"dataType": "INTEGER"
},
{
"settingKey": "custom.monthly.notification.limit",
"settingValue": "10000000",
"label": "Monthly Notification Limit",
"category": "GENERAL",
"dataType": "LONG"
}
]
Retrieve Settings by Category
Get all settings in a specific category:
GET /api/v1/notification-settings/category/SECURITY
X-Tenant-Id: 550e8400-e29b-41d4-a716-446655440000
Retrieve Bulk Settings
Get multiple specific settings by key (context-based extraction):
GET /api/v1/notification-settings/bulk?keys=global.email.enabled,security.login.alert.email,transactional.order.executed
X-Tenant-Id: 550e8400-e29b-41d4-a716-446655440000
π± Push Notification Support
The service now includes comprehensive push notification support with the following features:
Push Notification Configuration
Push notifications are configured using the pushNotification field in the main payload (moved from metadata for cleaner API design):
{
"type": "EMAIL_ORDER_EXECUTED",
"recipient": "user@example.com",
"pushNotification": {
"enabled": true,
"deviceToken": "firebase-device-token-here",
"priority": "HIGH",
"title": "Trade Executed",
"sound": "default",
"clickAction": "OPEN_APP"
},
"templateVariables": {
"symbol": "AAPL",
"quantity": "100",
"price": "150.25"
}
}
Priority Levels
Push notifications support three priority levels using the NotificationPriority enum:
- HIGH: Critical notifications (immediate delivery, bypasses battery optimization)
- NORMAL: Standard notifications (default priority)
- LOW: Low-priority notifications (may be delayed)
The system maintains backward compatibility - string values like "high", "normal", "low" are automatically converted to enum values.
Notification Styles
Push notifications support different display styles using the NotificationStyle enum to control how notifications appear on the device:
- BASIC: Standard notification with title and body only
- BIG_TEXT: Expandable notification that shows more content when expanded
- BIG_PICTURE: Notification with an image that displays prominently
- INBOX: Multi-line notification showing multiple lines of information
- MESSAGING: Chat-style notification for conversations
BASIC Style Example
{
"pushNotification": {
"enabled": true,
"deviceToken": "firebase-device-token-here",
"priority": "NORMAL",
"title": "Trade Executed",
"style": "BASIC"
}
}
BIG_TEXT Style Example
{
"pushNotification": {
"enabled": true,
"deviceToken": "firebase-device-token-here",
"priority": "HIGH",
"title": "Security Alert",
"style": "BIG_TEXT",
"bigText": "Your account has been accessed from a new device. If this wasn't you, please contact support immediately and change your password."
}
}
BIG_PICTURE Style Example
{
"pushNotification": {
"enabled": true,
"deviceToken": "firebase-device-token-here",
"priority": "NORMAL",
"title": "Portfolio Update",
"style": "BIG_PICTURE",
"imageUrl": "https://example.com/portfolio-chart.png"
}
}
INBOX Style Example
{
"pushNotification": {
"enabled": true,
"deviceToken": "firebase-device-token-here",
"priority": "NORMAL",
"title": "Recent Transactions",
"style": "INBOX",
"summaryText": "3 new transactions",
"inboxLines": [
"Bought 100 AAPL @ $150.25",
"Sold 50 TSLA @ $220.50",
"Dividend received: $25.00"
]
}
}
MESSAGING Style Example
{
"pushNotification": {
"enabled": true,
"deviceToken": "firebase-device-token-here",
"priority": "HIGH",
"title": "New Message",
"style": "MESSAGING"
}
}
π Real-World Use Cases & Payloads
This section provides comprehensive examples of how to use the notification service for common business scenarios. Each use case includes complete payloads, targeting strategies, and best practices.
π° Customer Acquisition & Onboarding
Welcome Series - Automated Email Sequence
Send a personalized welcome series to new users with progressive engagement.
Day 1: Welcome Email
POST /api/v1/notifications/targeted/TARGET/EMAIL_REGISTRATION
{
"recipient": "newuser@example.com",
"subject": "Welcome to OlaraTech - Your Trading Journey Begins!",
"clientReference": "welcome-series-day1-001",
"userId": "b1a2c3d4-e5f6-7890-1234-56789abcdef0",
"pushNotification": {
"enabled": true,
"deviceToken": "firebase-device-token-here",
"priority": "HIGH",
"title": "Welcome to OlaraTech!",
"style": "BIG_TEXT",
"bigText": "Your account is ready! Complete verification and start trading with $0 commissions for the first 30 days."
},
"templateVariables": {
"fullName": "Sarah Johnson",
"username": "SarahJ",
"verificationUrl": "https://app.olaratech.com/verify?token=welcome123",
"bonusAmount": "$10",
"bonusExpiry": "30 days",
"dashboardUrl": "https://app.olaratech.com/dashboard",
"supportEmail": "support@olaratech.com",
"appDownloadUrl": "https://app.olaratech.com/download"
}
}
Day 3: Educational Content
POST /api/v1/notifications/targeted/TARGET/EMAIL_MISC_FEATURE_ANNOUNCEMENT
{
"recipient": "newuser@example.com",
"subject": "π Your Trading Education Starts Here",
"clientReference": "welcome-series-day3-002",
"userId": "b1a2c3d4-e5f6-7890-1234-56789abcdef0",
"templateVariables": {
"fullName": "Sarah Johnson",
"educationalResources": [
"How to Place Your First Trade",
"Understanding Market Orders vs Limit Orders",
"Risk Management Basics"
],
"videoTutorialUrl": "https://learn.olaratech.com/first-trade",
"practiceAccountUrl": "https://app.olaratech.com/demo",
"nextSteps": "Fund your account and place your first trade"
}
}
Referral Program Onboarding
Target users who haven't made their first referral yet.
POST /api/v1/notifications/targeted/GROUP/EMAIL_MISC_REFERRAL_BONUS
{
"subject": "Earn $50 for Each Friend You Invite!",
"content": "Share your referral link and get rewarded",
"clientReference": "referral-onboarding-003",
"targeting": {
"targetType": "DYNAMIC_FILTER",
"filterCriteria": {
"accountAgeDays": {"gte": 7},
"hasReferrals": false,
"kycStatus": "APPROVED",
"hasDeposited": true
}
},
"pushNotification": {
"enabled": true,
"priority": "NORMAL",
"title": "Earn $50 Per Referral",
"style": "INBOX",
"summaryText": "Referral program benefits",
"inboxLines": [
"$50 bonus per successful referral",
"Unlimited referral earnings",
"Easy sharing tools available"
]
},
"templateVariables": {
"referralBonus": "$50",
"referralUrl": "https://app.olaratech.com/refer?code=SARAHJ50",
"leaderboardUrl": "https://app.olaratech.com/referrals/leaderboard",
"termsUrl": "https://app.olaratech.com/referrals/terms"
}
}
π Risk Management & Compliance
AML/KYC Compliance Monitoring
Automated alerts for suspicious account activity patterns.
Large Deposit Alert
POST /api/v1/notifications/targeted/GROUP/EMAIL_SECURITY_NEW_DEVICE_LOGIN
{
"subject": "Security Alert: Large Deposit Detected",
"content": "A significant deposit has been made to your account",
"clientReference": "aml-large-deposit-001",
"targeting": {
"targetType": "DYNAMIC_FILTER",
"filterCriteria": {
"lastDepositAmount": {"gte": 10000},
"depositFrequency": "unusual",
"kycStatus": "PENDING",
"accountAgeDays": {"lte": 30}
}
},
"pushNotification": {
"enabled": true,
"priority": "HIGH",
"title": "Security Alert",
"sound": "alert",
"style": "BIG_TEXT",
"bigText": "A large deposit of $10,000+ has been detected on your account. Please verify this activity and update your KYC if required."
},
"templateVariables": {
"depositAmount": "{{lastDepositAmount}}",
"depositDate": "{{lastDepositDate}}",
"verificationRequired": "KYC update required for deposits over $10,000",
"kycUpdateUrl": "https://app.olaratech.com/kyc/update",
"supportContact": "compliance@olaratech.com"
}
}
KYC Expiry Prevention Campaign
Proactive reminders before KYC documents expire.
POST /api/v1/notifications/targeted/GROUP/EMAIL_KYC_EXPIRY_REMINDER
{
"subject": "Action Required: Update Your KYC Documents",
"content": "Your KYC verification expires soon",
"clientReference": "kyc-expiry-prevention-002",
"targeting": {
"targetType": "KYC_STATUS",
"kycStatus": "APPROVED",
"filterCriteria": {
"kycExpiryDays": {"lte": 30},
"hasOpenOrders": true,
"currentBalance": {"gte": 1000}
}
},
"pushNotification": {
"enabled": true,
"priority": "HIGH",
"title": "KYC Update Required",
"sound": "alert",
"clickAction": "OPEN_KYC_UPDATE"
},
"templateVariables": {
"fullName": "{{fullName}}",
"kycExpiryDate": "{{kycExpiryDate}}",
"daysUntilExpiry": "{{daysUntilExpiry}}",
"tradingLimits": "Trading suspended after expiry",
"kycUpdateUrl": "https://app.olaratech.com/kyc/update",
"requiredDocuments": "Government ID, Proof of Address, Selfie"
}
}
πΈ Customer Retention & Engagement
Churn Prevention - Inactive User Reactivation
Target users who haven't traded in 30+ days with personalized incentives.
POST /api/v1/notifications/targeted/GROUP/EMAIL_PORTFOLIO_LOW_BALANCE_ALERT
{
"subject": "We Miss You! Special Welcome Back Offer",
"content": "Come back and claim your trading bonus",
"clientReference": "churn-prevention-inactive-003",
"targeting": {
"targetType": "DYNAMIC_FILTER",
"filterCriteria": {
"lastTradeDays": {"gte": 30},
"currentBalance": {"gte": 100},
"kycStatus": "APPROVED",
"hasDeposited": true,
"accountStatus": "ACTIVE"
}
},
"pushNotification": {
"enabled": true,
"priority": "NORMAL",
"title": "Welcome Back Offer!",
"style": "BIG_PICTURE",
"imageUrl": "https://cdn.olaratech.com/welcome-back-banner.png",
"bigText": "Get 50% bonus on your next deposit! Limited time offer for returning traders."
},
"templateVariables": {
"fullName": "{{fullName}}",
"welcomeBackBonus": "50%",
"bonusMaxAmount": "$500",
"offerExpiry": "7 days",
"depositUrl": "https://app.olaratech.com/deposit",
"tradingIdeasUrl": "https://learn.olaratech.com/market-analysis",
"personalizedMessage": "We noticed you haven't traded recently. Markets are active - come back and take advantage of current opportunities!"
}
}
VIP Customer Appreciation
Monthly rewards for high-value customers.
POST /api/v1/notifications/targeted/GROUP/EMAIL_MISC_FEATURE_ANNOUNCEMENT
{
"subject": "π Exclusive VIP Benefits - Thank You for Trading with Us!",
"content": "Your loyalty is appreciated with exclusive benefits",
"clientReference": "vip-appreciation-monthly-004",
"targeting": {
"targetType": "PORTFOLIO_VALUE",
"portfolioValue": {
"amount": 50000.00,
"operator": "GREATER_THAN"
},
"filterCriteria": {
"monthlyVolume": {"gte": 100000},
"accountAgeDays": {"gte": 90},
"kycStatus": "APPROVED"
}
},
"pushNotification": {
"enabled": true,
"priority": "HIGH",
"title": "VIP Exclusive Offer",
"style": "INBOX",
"summaryText": "Your VIP benefits this month",
"inboxLines": [
"0.5% fee reduction on all trades",
"Priority customer support",
"Exclusive market insights",
"VIP event invitations"
]
},
"templateVariables": {
"fullName": "{{fullName}}",
"portfolioValue": "{{portfolioValue}}",
"monthlyVolume": "{{monthlyVolume}}",
"vipTier": "Platinum",
"feeDiscount": "0.5%",
"nextBenefits": "Private webinar access, Dedicated relationship manager",
"vipPortalUrl": "https://vip.olaratech.com",
"personalizedMessage": "Your trading activity this month has been exceptional. As a token of appreciation, we've upgraded your VIP status."
}
}
π Trading & Market Events
Market Volatility Alerts
Real-time alerts during high volatility periods.
POST /api/v1/notifications/targeted/GROUP/EMAIL_ORDER_EXECUTED
{
"subject": "β οΈ High Market Volatility - Trade with Caution",
"content": "Current market conditions require extra attention",
"clientReference": "volatility-alert-005",
"targeting": {
"targetType": "DYNAMIC_FILTER",
"filterCriteria": {
"hasOpenPositions": true,
"portfolioValue": {"gte": 1000},
"riskTolerance": "medium",
"lastLoginDays": {"lte": 7}
}
},
"pushNotification": {
"enabled": true,
"priority": "HIGH",
"title": "Market Volatility Alert",
"sound": "alert",
"style": "BIG_TEXT",
"bigText": "VIX has spiked 25% in the last hour. Consider adjusting stop-loss orders and reducing position sizes during volatile market conditions."
},
"templateVariables": {
"volatilityIndex": "32.5",
"changePercent": "+25%",
"affectedMarkets": "US Tech stocks, Crypto, Commodities",
"riskManagementTips": [
"Tighten stop-loss orders",
"Reduce position sizes",
"Consider hedging strategies",
"Monitor news closely"
],
"riskManagementUrl": "https://learn.olaratech.com/volatility-trading",
"portfolioReviewUrl": "https://app.olaratech.com/portfolio/review"
}
}
Earnings Season Preparation
Pre-earnings guidance for relevant positions.
POST /api/v1/notifications/targeted/GROUP/EMAIL_PORTFOLIO_DIVIDEND_PAYMENT
{
"subject": "π
Earnings Season: Review Your Positions",
"content": "Upcoming earnings reports may impact your holdings",
"clientReference": "earnings-season-prep-006",
"targeting": {
"targetType": "DYNAMIC_FILTER",
"filterCriteria": {
"holdings": {"contains": ["AAPL", "MSFT", "GOOGL", "AMZN", "TSLA"]},
"portfolioValue": {"gte": 5000},
"hasOpenOrders": false
}
},
"pushNotification": {
"enabled": true,
"priority": "NORMAL",
"title": "Earnings Season Alert",
"style": "INBOX",
"summaryText": "Upcoming earnings reports",
"inboxLines": [
"AAPL reports tomorrow after market close",
"MSFT earnings next week",
"Consider position adjustments",
"Review analyst expectations"
]
},
"templateVariables": {
"upcomingEarnings": [
{"symbol": "AAPL", "date": "2025-01-30", "time": "After Market", "expectedMove": "+/- 5%"},
{"symbol": "MSFT", "date": "2025-01-31", "time": "Before Market", "expectedMove": "+/- 3%"},
{"symbol": "GOOGL", "date": "2025-02-03", "time": "After Market", "expectedMove": "+/- 4%"}
],
"portfolioImpact": "15% of your portfolio affected",
"riskManagementUrl": "https://learn.olaratech.com/earnings-trading",
"earningsCalendarUrl": "https://app.olaratech.com/earnings-calendar"
}
}
π¦ Banking & Financial Operations
Margin Call Prevention
Proactive alerts before margin calls occur.
POST /api/v1/notifications/targeted/GROUP/EMAIL_PORTFOLIO_MARGIN_CALL_ALERT
{
"subject": "β οΈ Margin Warning - Action Required",
"content": "Your account is approaching margin maintenance requirements",
"clientReference": "margin-prevention-007",
"targeting": {
"targetType": "DYNAMIC_FILTER",
"filterCriteria": {
"marginLevel": {"lte": 35},
"hasOpenPositions": true,
"portfolioValue": {"gte": 10000},
"accountType": "margin"
}
},
"pushNotification": {
"enabled": true,
"priority": "HIGH",
"title": "Margin Warning",
"sound": "alert",
"clickAction": "OPEN_MARGIN_DETAILS",
"style": "BIG_TEXT",
"bigText": "Your margin level is at 32%. Add funds or reduce positions to avoid a margin call. Current requirement: $5,000 additional margin needed."
},
"templateVariables": {
"fullName": "{{fullName}}",
"currentMarginLevel": "{{marginLevel}}%",
"requiredMarginLevel": "30%",
"additionalMarginNeeded": "{{additionalMarginNeeded}}",
"deadlineHours": "24",
"depositUrl": "https://app.olaratech.com/deposit",
"marginManagementUrl": "https://learn.olaratech.com/margin-management",
"supportContact": "margin@olaratech.com"
}
}
Corporate Action Notifications
Dividend payments, stock splits, mergers, etc.
POST /api/v1/notifications/targeted/GROUP/EMAIL_PORTFOLIO_DIVIDEND_PAYMENT
{
"subject": "π° Dividend Payment Notification - {{symbol}}",
"content": "Dividend payment processed to your account",
"clientReference": "corporate-action-dividend-008",
"targeting": {
"targetType": "DYNAMIC_FILTER",
"filterCriteria": {
"holdings": {"contains": ["AAPL"]},
"dividendEligible": true,
"accountType": {"in": ["individual", "retirement"]}
}
},
"pushNotification": {
"enabled": true,
"priority": "NORMAL",
"title": "Dividend Paid",
"style": "INBOX",
"summaryText": "Dividend payments received",
"inboxLines": [
"AAPL: $0.96 per share",
"Total dividend: $96.00",
"Payment date: Jan 15, 2025",
"Tax implications apply"
]
},
"templateVariables": {
"symbol": "AAPL",
"dividendPerShare": "$0.96",
"sharesOwned": "100",
"totalDividend": "$96.00",
"paymentDate": "2025-01-15",
"exDividendDate": "2025-01-10",
"taxWithholding": "$9.60 (10%)",
"netPayment": "$86.40",
"reinvestmentUrl": "https://app.olaratech.com/dividend-reinvestment",
"taxDocumentsUrl": "https://app.olaratech.com/tax-documents"
}
}
π§ Operational & Technical Scenarios
System Maintenance Notifications
Scheduled maintenance with advance notice.
POST /api/v1/notifications/targeted/COMPANY/EMAIL_MISC_FEATURE_ANNOUNCEMENT
{
"subject": "π οΈ Scheduled System Maintenance - Sunday 2-4 AM EST",
"content": "Platform maintenance window and expected impact",
"clientReference": "maintenance-scheduled-009",
"pushNotification": {
"enabled": true,
"priority": "NORMAL",
"title": "System Maintenance",
"style": "BIG_TEXT",
"bigText": "Scheduled maintenance this Sunday 2-4 AM EST. Trading will be unavailable during this window. All orders will resume normal processing after maintenance completion."
},
"templateVariables": {
"maintenanceDate": "Sunday, January 26, 2025",
"maintenanceTime": "2:00 AM - 4:00 AM EST",
"expectedDuration": "2 hours",
"servicesAffected": "Trading platform, Mobile apps, API access",
"backupServices": "View-only access to account information",
"contactSupport": "For urgent issues during maintenance: emergency@olaratech.com",
"statusPageUrl": "https://status.olaratech.com"
}
}
API Rate Limit Warnings
Notify developers approaching API limits.
POST /api/v1/notifications/targeted/GROUP/EMAIL_SECURITY_NEW_DEVICE_LOGIN
{
"subject": "API Rate Limit Warning - 80% Usage Reached",
"content": "Your API usage is approaching rate limits",
"clientReference": "api-rate-limit-warning-010",
"targeting": {
"targetType": "DYNAMIC_FILTER",
"filterCriteria": {
"apiUsagePercent": {"gte": 80},
"apiPlan": {"in": ["developer", "enterprise"]},
"lastNotificationDays": {"gte": 1}
}
},
"pushNotification": {
"enabled": true,
"priority": "NORMAL",
"title": "API Usage Alert",
"style": "INBOX",
"summaryText": "Rate limit approaching",
"inboxLines": [
"Current usage: 85%",
"Limit: 10,000 requests/hour",
"Reset in: 2 hours",
"Upgrade available"
]
},
"templateVariables": {
"apiKeyMasked": "sk-****-****-****-abc123",
"currentUsagePercent": "{{apiUsagePercent}}%",
"requestsUsed": "{{requestsUsed}}",
"requestsLimit": "{{requestsLimit}}",
"resetTime": "{{resetTime}}",
"upgradeUrl": "https://app.olaratech.com/api/upgrade",
"documentationUrl": "https://docs.olaratech.com/api/rate-limits",
"contactSupport": "api-support@olaratech.com"
}
}
π― Advanced Targeting Patterns
Multi-Criteria Segmentation
Complex targeting combining multiple filters.
POST /api/v1/notifications/targeted/GROUP/EMAIL_PORTFOLIO_LOW_BALANCE_ALERT
{
"subject": "Personalized Investment Opportunity",
"content": "Based on your trading history and preferences",
"clientReference": "advanced-targeting-multi-criteria-011",
"targeting": {
"targetType": "DYNAMIC_FILTER",
"filterCriteria": {
"portfolioValue": {"gte": 25000, "lte": 100000},
"monthlyVolume": {"gte": 50000},
"preferredAssets": {"contains": ["stocks", "etf"]},
"riskTolerance": "moderate",
"accountAgeDays": {"gte": 180},
"kycStatus": "APPROVED",
"hasOpenOrders": false,
"lastDepositDays": {"lte": 30},
"geographicRegion": "US",
"accountType": "individual"
},
"availableToTrade": {
"amount": 5000.00,
"operator": "GREATER_THAN"
}
},
"pushNotification": {
"enabled": true,
"priority": "NORMAL",
"title": "Exclusive Opportunity",
"style": "BIG_TEXT",
"bigText": "Based on your $75K portfolio and moderate risk tolerance, you may be interested in our new ESG ETF fund with 8% projected annual returns."
},
"templateVariables": {
"fullName": "{{fullName}}",
"portfolioValue": "{{portfolioValue}}",
"riskProfile": "{{riskTolerance}}",
"recommendedProduct": "OlaraTech ESG Growth ETF",
"projectedReturn": "8% annually",
"minimumInvestment": "$5,000",
"timeHorizon": "5+ years",
"researchUrl": "https://research.olaratech.com/esg-etf",
"investmentUrl": "https://app.olaratech.com/invest/esg-etf"
}
}
Geographic & Demographic Targeting
Location-based campaigns with demographic filters.
POST /api/v1/notifications/targeted/GROUP/EMAIL_MISC_FEATURE_ANNOUNCEMENT
{
"subject": "π New Feature Available in Your Region",
"content": "Fractional share trading now available",
"clientReference": "geographic-targeting-012",
"targeting": {
"targetType": "COUNTRY",
"targetCountry": "US",
"filterCriteria": {
"accountAgeDays": {"gte": 30},
"hasDeposited": true,
"portfolioValue": {"lt": 1000},
"kycStatus": "APPROVED",
"state": {"in": ["CA", "NY", "TX", "FL"]},
"ageRange": {"gte": 25, "lte": 45},
"incomeBracket": "medium"
}
},
"pushNotification": {
"enabled": true,
"priority": "NORMAL",
"title": "New Feature Unlocked",
"style": "BIG_PICTURE",
"imageUrl": "https://cdn.olaratech.com/fractional-shares-banner.png"
},
"templateVariables": {
"fullName": "{{fullName}}",
"newFeature": "Fractional Share Trading",
"featureBenefit": "Invest in expensive stocks with as little as $5",
"exampleInvestment": "$5 in Apple stock = 0.03 shares",
"availableStocks": "Apple, Amazon, Tesla, Google, Microsoft",
"tutorialUrl": "https://learn.olaratech.com/fractional-trading",
"startTradingUrl": "https://app.olaratech.com/trade/fractional"
}
}
π¨ Error Handling & Troubleshooting
Failed Notification Retry Scenarios
Handle and retry failed notifications with exponential backoff.
POST /api/v1/notifications/targeted/GROUP/EMAIL_FUNDING_DEPOSIT_FAILED
{
"subject": "Deposit Processing Issue - Action Required",
"content": "We encountered an issue processing your deposit",
"clientReference": "error-handling-retry-013",
"targeting": {
"targetType": "DYNAMIC_FILTER",
"filterCriteria": {
"lastDepositStatus": "failed",
"depositFailureReason": {"in": ["insufficient_funds", "card_declined", "bank_error"]},
"retryAttempts": {"lt": 3},
"accountStatus": "ACTIVE"
}
},
"pushNotification": {
"enabled": true,
"priority": "HIGH",
"title": "Deposit Issue",
"sound": "alert",
"style": "BIG_TEXT",
"bigText": "Your $500 deposit failed due to insufficient funds. Please update your payment method or add funds to complete the transaction."
},
"templateVariables": {
"fullName": "{{fullName}}",
"depositAmount": "{{depositAmount}}",
"failureReason": "{{depositFailureReason}}",
"failureDescription": {
"insufficient_funds": "Your account has insufficient funds",
"card_declined": "Your card was declined by the issuer",
"bank_error": "Temporary bank processing error"
}["{{depositFailureReason}}"],
"retryUrl": "https://app.olaratech.com/deposit/retry",
"updatePaymentUrl": "https://app.olaratech.com/payment-methods",
"supportTicketUrl": "https://support.olaratech.com/new-ticket?category=deposits"
}
}
Bulk Operation Examples
Efficient handling of large-scale notifications.
Company-wide Security Update
POST /api/v1/notifications/targeted/COMPANY/EMAIL_SECURITY_NEW_DEVICE_LOGIN
{
"subject": "π Security Update: New Two-Factor Authentication Required",
"content": "Enhanced security measures now active",
"clientReference": "bulk-security-update-014",
"pushNotification": {
"enabled": true,
"priority": "HIGH",
"title": "Security Update Required",
"sound": "alert",
"style": "BIG_TEXT",
"bigText": "New security measures are now active. Please enable two-factor authentication within 7 days to maintain access to your account."
},
"templateVariables": {
"fullName": "{{fullName}}",
"securityUpdate": "Two-Factor Authentication (2FA)",
"deadline": "7 days",
"setupUrl": "https://app.olaratech.com/security/2fa-setup",
"securityBenefits": [
"Enhanced account protection",
"Prevention of unauthorized access",
"Compliance with industry standards"
],
"supportUrl": "https://support.olaratech.com/2fa-help",
"emergencyContact": "security@olaratech.com"
}
}
π Integration Patterns & Best Practices
Event-Driven Notification Workflows
Automated notifications triggered by system events.
Order Execution Workflow
// Example: Backend service integration
const notificationService = require('./notificationService');
async function handleOrderExecution(orderId, userId, executionDetails) {
try {
// 1. Send immediate execution confirmation
await notificationService.sendTargetedNotification({
scope: 'TARGET',
notificationType: 'EMAIL_ORDER_EXECUTED',
recipient: userId,
subject: `Order Executed - ${executionDetails.symbol}`,
templateVariables: {
orderNumber: orderId,
symbol: executionDetails.symbol,
quantity: executionDetails.quantity,
price: executionDetails.price,
totalValue: executionDetails.totalValue
},
pushNotification: {
enabled: true,
priority: 'HIGH',
title: 'Order Executed',
style: 'INBOX'
}
});
// 2. Check for portfolio impact notifications
if (executionDetails.portfolioImpact > 0.1) { // 10% portfolio change
await notificationService.sendTargetedNotification({
scope: 'TARGET',
notificationType: 'EMAIL_PORTFOLIO_POSITION_LIQUIDATION',
recipient: userId,
subject: 'Portfolio Update: Significant Position Change',
templateVariables: {
symbol: executionDetails.symbol,
positionChange: `${executionDetails.portfolioImpact}%`,
newPortfolioValue: executionDetails.newPortfolioValue
}
});
}
// 3. Trigger related workflows (tax documents, etc.)
if (executionDetails.isTaxableEvent) {
await notificationService.sendTargetedNotification({
scope: 'TARGET',
notificationType: 'EMAIL_PORTFOLIO_DIVIDEND_PAYMENT',
recipient: userId,
subject: 'Tax Document Available',
templateVariables: {
taxYear: new Date().getFullYear(),
documentType: '1099-B',
downloadUrl: `/tax-documents/${orderId}`
}
});
}
} catch (error) {
console.error('Notification workflow failed:', error);
// Implement retry logic or fallback notifications
}
}
Scheduled Campaign Management
Time-based notification campaigns with A/B testing.
// Example: Campaign scheduler service
const campaignScheduler = {
async scheduleWelcomeCampaign(userId, userProfile) {
const delays = [0, 3, 7, 14, 30]; // days after registration
for (let i = 0; i < delays.length; i++) {
await this.scheduleNotification({
userId,
notificationType: `EMAIL_WELCOME_SERIES_DAY_${i + 1}`,
delayDays: delays[i],
templateVariables: {
...userProfile,
campaignStage: i + 1,
nextMilestone: i < delays.length - 1 ? `${delays[i + 1] - delays[i]} days` : 'Complete'
}
});
}
},
async scheduleReengagementCampaign(inactiveUsers) {
// Segment users by inactivity duration
const segments = {
'30_days': inactiveUsers.filter(u => u.daysInactive >= 30 && u.daysInactive < 60),
'60_days': inactiveUsers.filter(u => u.daysInactive >= 60 && u.daysInactive < 90),
'90_days': inactiveUsers.filter(u => u.daysInactive >= 90)
};
// Different messaging for different segments
for (const [segment, users] of Object.entries(segments)) {
const offer = this.getReengagementOffer(segment);
await notificationService.sendTargetedNotification({
scope: 'GROUP',
notificationType: 'EMAIL_REENGAGEMENT_OFFER',
targeting: {
targetType: 'USER_ID',
targetUserIds: users.map(u => u.id)
},
subject: offer.subject,
templateVariables: {
...offer,
segment,
personalizedMessage: this.getPersonalizedMessage(segment, users.length)
}
});
}
}
};
Monitoring & Analytics Integration
Track notification performance and user engagement.
// Example: Notification analytics service
const notificationAnalytics = {
async trackNotificationMetrics(notificationId, userId, event) {
const metrics = {
sent: { status: 'sent', timestamp: new Date() },
delivered: { status: 'delivered', timestamp: new Date() },
opened: { status: 'opened', timestamp: new Date() },
clicked: { status: 'clicked', url: event.url, timestamp: new Date() },
converted: { status: 'converted', action: event.action, timestamp: new Date() }
};
await this.storeMetric(notificationId, userId, metrics[event.type]);
// Trigger follow-up actions based on engagement
if (event.type === 'opened' && !user.hasCompletedOnboarding) {
await this.triggerOnboardingReminder(userId);
}
if (event.type === 'converted' && event.action === 'deposit') {
await this.triggerWelcomeBonus(userId);
}
},
async generateCampaignReport(campaignId) {
const metrics = await this.getCampaignMetrics(campaignId);
return {
campaignId,
totalSent: metrics.sent,
deliveryRate: (metrics.delivered / metrics.sent) * 100,
openRate: (metrics.opened / metrics.delivered) * 100,
clickRate: (metrics.clicked / metrics.opened) * 100,
conversionRate: (metrics.converted / metrics.clicked) * 100,
revenueGenerated: metrics.revenue,
costPerAcquisition: metrics.cost / metrics.converted,
bestPerformingSegment: this.findBestSegment(metrics),
recommendations: this.generateRecommendations(metrics)
};
}
};
οΏ½ Wallet-Based Targeting
The notification service integrates with the wallet service to provide advanced targeting based on user wallet balances and financial criteria.
Wallet Service Integration
The service uses the wallet service's /api/v1/wallets/filter endpoint for efficient bulk filtering of users based on balance criteria, eliminating the need for individual wallet lookups.
Supported Balance Types
- Available to Trade: Balance available for trading activities
- Available Balance: General available balance
- Current Balance: Total current balance
- Withdrawal Balance: Balance available for withdrawal
Balance Operators
GREATER_THAN: Balance > amountLESS_THAN: Balance < amountEQUAL_TO: Balance = amountGREATER_THAN_OR_EQUAL_TO: Balance >= amountLESS_THAN_OR_EQUAL_TO: Balance <= amount
Wallet Targeting Examples
Low Balance Alert Campaign
POST /api/v1/notifications/targeted/GROUP/EMAIL_PORTFOLIO_LOW_BALANCE_ALERT
{
"subject": "Account Balance Alert",
"content": "Your trading balance is below the recommended threshold",
"clientReference": "low-balance-campaign-001",
"targeting": {
"targetType": "WALLET_BALANCE",
"availableToTrade": {
"amount": 100.00,
"operator": "LESS_THAN"
},
"currentBalance": {
"amount": 0.00,
"operator": "GREATER_THAN"
}
},
"pushNotification": {
"enabled": true,
"priority": "HIGH",
"title": "Low Balance Alert",
"style": "BIG_TEXT",
"bigText": "Your trading balance is getting low. Add funds now to continue trading without interruption."
},
"templateVariables": {
"currentBalance": "{{currentBalance}}",
"minimumRecommended": "$100.00",
"actionUrl": "https://app.olaratech.com/funding"
}
}
High-Value User Notifications
POST /api/v1/notifications/targeted/GROUP/EMAIL_PORTFOLIO_LOW_BALANCE_ALERT
{
"subject": "Exclusive Premium Investment Opportunity",
"content": "New high-yield investment options for premium clients",
"clientReference": "premium-investment-002",
"targeting": {
"targetType": "HIGH_WALLET_BALANCE",
"currentBalance": {
"amount": 50000.00,
"operator": "GREATER_THAN"
}
},
"pushNotification": {
"enabled": true,
"priority": "NORMAL",
"title": "Premium Investment Opportunity",
"style": "INBOX",
"summaryText": "Exclusive offers available",
"inboxLines": [
"High-yield bonds available",
"Premium ETF portfolios",
"Private equity opportunities"
]
},
"templateVariables": {
"portfolioValue": "{{portfolioValue}}",
"newOpportunities": "High-yield bonds, Premium ETFs, Private equity",
"contactAdvisor": "https://app.olaratech.com/advisor"
}
}
Zero Balance Users
POST /api/v1/notifications/targeted/GROUP/EMAIL_PORTFOLIO_LOW_BALANCE_ALERT
{
"subject": "Welcome Back - Ready to Start Trading?",
"content": "Your account is ready for funding",
"clientReference": "zero-balance-reactivation-003",
"targeting": {
"targetType": "ZERO_WALLET_BALANCE",
"kycIncomplete": false
},
"pushNotification": {
"enabled": true,
"priority": "NORMAL",
"title": "Ready to Trade?",
"style": "BASIC",
"clickAction": "OPEN_FUNDING"
},
"templateVariables": {
"welcomeMessage": "Welcome back! Your account is ready for funding.",
"fundingOptions": "Bank transfer, Card payment, Crypto deposit",
"startTradingUrl": "https://app.olaratech.com/funding"
}
}
Performance Benefits
- Single API Call: Uses wallet service bulk filtering instead of individual lookups
- Scalable: Handles large user bases efficiently
- Real-time: Leverages wallet service's current balance data
- Flexible: Supports complex balance criteria combinations
π― Advanced Targeting Patterns
This section demonstrates sophisticated targeting strategies that combine multiple criteria for precise audience segmentation.
Multi-Dimensional User Segmentation
High-Value Customer Lifecycle Targeting
Target users based on portfolio value, trading activity, and account age for personalized lifecycle marketing.
POST /api/v1/notifications/targeted/GROUP/EMAIL_PORTFOLIO_LOW_BALANCE_ALERT
{
"subject": "Exclusive: Your Portfolio Review & Optimization Session",
"content": "Personalized portfolio analysis with our senior investment advisors",
"clientReference": "lifecycle-portfolio-review-015",
"targeting": {
"targetType": "DYNAMIC_FILTER",
"filterCriteria": {
"portfolioValue": {"gte": 100000, "lte": 500000},
"monthlyVolume": {"gte": 25000},
"accountAgeDays": {"gte": 365},
"kycStatus": "APPROVED",
"hasActiveInvestments": true,
"lastAdvisorContactDays": {"gte": 90},
"riskTolerance": {"in": ["moderate", "conservative"]},
"preferredAssetClasses": {"contains": ["stocks", "bonds"]},
"geographicRegion": {"in": ["US-WEST", "US-EAST"]},
"accountType": "individual"
},
"availableToTrade": {
"amount": 10000.00,
"operator": "GREATER_THAN"
}
},
"pushNotification": {
"enabled": true,
"priority": "NORMAL",
"title": "Portfolio Review Available",
"style": "BIG_TEXT",
"bigText": "Your $250K portfolio qualifies for a free comprehensive review with our senior advisors. Includes tax optimization and rebalancing recommendations."
},
"templateVariables": {
"fullName": "{{fullName}}",
"portfolioValue": "{{portfolioValue}}",
"accountAgeYears": "{{accountAgeYears}}",
"monthlyVolume": "{{monthlyVolume}}",
"advisorName": "Sarah Mitchell",
"advisorCredentials": "CFA, 15+ years experience",
"sessionDuration": "60 minutes",
"sessionValue": "$500",
"availableSlots": [
"Tomorrow 2:00 PM EST",
"Friday 10:00 AM EST",
"Next Monday 3:00 PM EST"
],
"preparationMaterials": [
"Portfolio Performance Summary",
"Tax Loss Harvesting Opportunities",
"Asset Allocation Analysis",
"Risk Assessment Report"
],
"bookingUrl": "https://app.olaratech.com/advisor/book?portfolio={{portfolioValue}}",
"portfolioUrl": "https://app.olaratech.com/portfolio/analysis",
"researchUrl": "https://research.olaratech.com/market-outlook"
}
}
Behavioral Pattern Targeting
Target users based on their trading behavior patterns and market conditions.
POST /api/v1/notifications/targeted/GROUP/EMAIL_ORDER_EXECUTED
{
"subject": "π Market Opportunity: Your Trading Pattern Shows Potential",
"content": "Based on your successful trading history, here's a market opportunity",
"clientReference": "behavioral-pattern-opportunity-016",
"targeting": {
"targetType": "DYNAMIC_FILTER",
"filterCriteria": {
"winRate": {"gte": 0.65},
"avgTradeSize": {"gte": 5000, "lte": 25000},
"tradingFrequency": {"gte": 10, "lte": 50}, // trades per month
"preferredSectors": {"contains": ["technology", "healthcare"]},
"riskTolerance": "moderate",
"accountAgeDays": {"gte": 180},
"lastTradeDays": {"lte": 7},
"portfolioDiversification": {"gte": 0.7},
"hasUsedOptions": false,
"educationLevel": {"in": ["intermediate", "advanced"]}
},
"currentBalance": {
"amount": 15000.00,
"operator": "GREATER_THAN"
}
},
"pushNotification": {
"enabled": true,
"priority": "NORMAL",
"title": "Trading Opportunity Alert",
"style": "INBOX",
"summaryText": "Based on your trading style",
"inboxLines": [
"Healthcare sector showing strength",
"Your win rate suggests good timing",
"Consider UNH position",
"Risk-adjusted opportunity"
]
},
"templateVariables": {
"fullName": "{{fullName}}",
"winRate": "{{winRate}}%",
"tradingStyle": "Momentum-based with good exits",
"opportunitySymbol": "UNH",
"opportunityRationale": "Strong earnings, sector momentum, your historical success patterns",
"suggestedPosition": "$10,000 - $15,000",
"riskRewardRatio": "1:2.5",
"timeHorizon": "2-4 weeks",
"entryPoint": "$485 - $490",
"stopLoss": "$460",
"takeProfit": "$520",
"marketContext": "Healthcare sector outperforming, positive earnings momentum",
"yourEdge": "Your pattern shows 68% win rate in similar setups",
"researchUrl": "https://research.olaratech.com/UNH-analysis",
"tradingUrl": "https://app.olaratech.com/trade/UNH",
"backtestUrl": "https://app.olaratech.com/backtest?strategy=your-pattern"
}
}
Geographic & Demographic Precision Targeting
Regional Market Event Notifications
Target users in specific regions for localized market events and opportunities.
POST /api/v1/notifications/targeted/GROUP/EMAIL_MISC_FEATURE_ANNOUNCEMENT
{
"subject": "π San Francisco Tech Meetup - Network with 200+ Investors",
"content": "Exclusive in-person event for our premium Bay Area clients",
"clientReference": "regional-event-sf-tech-017",
"targeting": {
"targetType": "DYNAMIC_FILTER",
"filterCriteria": {
"geographicRegion": "US-WEST",
"city": {"in": ["San Francisco", "Palo Alto", "Mountain View", "San Jose"]},
"portfolioValue": {"gte": 250000},
"accountType": "individual",
"kycStatus": "APPROVED",
"investorType": {"in": ["accredited", "qualified"]},
"industryInterests": {"contains": ["technology", "venture capital"]},
"networkingPreference": "high",
"eventAttendanceHistory": {"gte": 2}
},
"availableToTrade": {
"amount": 50000.00,
"operator": "GREATER_THAN"
}
},
"pushNotification": {
"enabled": true,
"priority": "HIGH",
"title": "Exclusive SF Tech Meetup",
"style": "BIG_PICTURE",
"imageUrl": "https://cdn.olaratech.com/sf-tech-meetup-banner.png",
"bigText": "Join 200+ tech investors and founders at our exclusive Bay Area networking event. Limited to premium clients only."
},
"templateVariables": {
"fullName": "{{fullName}}",
"eventName": "Silicon Valley Tech Investment Summit",
"eventDate": "February 15, 2025",
"eventTime": "6:00 PM - 9:00 PM PST",
"venueName": "The Battery",
"venueAddress": "1 Battery St, San Francisco, CA 94111",
"attendeeCount": "200+ premium investors",
"speakerLineup": [
"Sarah Chen - Sequoia Capital Partner",
"Marcus Johnson - Andreessen Horowitz",
"Dr. Lisa Wong - Stanford GSB Professor"
],
"networkingFocus": "AI, Biotech, FinTech, Climate Tech",
"rsvpDeadline": "February 8, 2025",
"ticketPrice": "Complimentary for premium clients",
"parkingInfo": "Valet parking available",
"dressCode": "Business casual",
"rsvpUrl": "https://events.olaratech.com/sf-tech-summit/rsvp",
"eventDetailsUrl": "https://events.olaratech.com/sf-tech-summit",
"guestPolicy": "Plus one allowed for spouses/partners"
}
}
Time-Based & Seasonal Targeting
Tax Season Optimization Campaign
Target users before tax deadlines with tax-loss harvesting opportunities.
POST /api/v1/notifications/targeted/GROUP/EMAIL_PORTFOLIO_DIVIDEND_PAYMENT
{
"subject": "π¨ Tax Season Alert: Optimize Your Portfolio Before April 15",
"content": "Tax-loss harvesting opportunities identified in your portfolio",
"clientReference": "tax-season-optimization-018",
"targeting": {
"targetType": "DYNAMIC_FILTER",
"filterCriteria": {
"taxSituation": "potential_losses_available",
"portfolioValue": {"gte": 50000},
"unrealizedLosses": {"gte": 5000},
"accountType": "taxable",
"lastTaxOptimizationDays": {"gte": 365},
"kycStatus": "APPROVED",
"investorType": "active_trader",
"state": {"nin": ["FL", "TX", "NV"]}, // states without income tax
"notificationPreference": "tax_optimization"
},
"currentBalance": {
"amount": 10000.00,
"operator": "GREATER_THAN"
}
},
"pushNotification": {
"enabled": true,
"priority": "HIGH",
"title": "Tax Optimization Available",
"sound": "alert",
"style": "INBOX",
"summaryText": "Tax-loss harvesting opportunity",
"inboxLines": [
"$12,500 in potential tax savings",
"Deadline: April 15",
"Optimize before wash sale rules",
"Free consultation available"
],
"clickAction": "OPEN_TAX_OPTIMIZATION"
},
"templateVariables": {
"fullName": "{{fullName}}",
"taxDeadline": "April 15, 2025",
"daysUntilDeadline": "{{daysUntilDeadline}}",
"potentialSavings": "{{potentialTaxSavings}}",
"taxableLosses": "{{unrealizedLosses}}",
"washSaleRisk": "Medium - 3 positions at risk",
"optimizationStrategy": "Tax-loss harvesting with similar securities",
"recommendedActions": [
"Harvest losses in underperforming positions",
"Offset gains with losses",
"Reinvest in similar but not identical securities",
"Maintain market exposure while optimizing taxes"
],
"affectedPositions": [
{"symbol": "XYZ", "loss": "$3,200", "replacement": "XYZ-like ETF"},
{"symbol": "ABC", "loss": "$2,800", "replacement": "ABC competitor"},
{"symbol": "DEF", "loss": "$1,500", "replacement": "DEF sector fund"}
],
"estimatedTaxSavings": "$4,200 (assuming 25% tax bracket)",
"consultationUrl": "https://app.olaratech.com/tax-consultation",
"optimizationUrl": "https://app.olaratech.com/tax-optimization",
"taxResourcesUrl": "https://learn.olaratech.com/tax-strategies",
"deadlineReminder": "Set calendar reminder for April 10 to complete optimization"
}
}
Risk-Based Dynamic Targeting
Market Volatility Protection
Automatically target users during high volatility periods based on their risk profile.
POST /api/v1/notifications/targeted/GROUP/EMAIL_ORDER_STOP_LOSS_TRIGGERED
{
"subject": "β οΈ High Market Volatility - Risk Management Recommendations",
"content": "VIX over 35 - consider adjusting your risk management strategy",
"clientReference": "volatility-risk-management-019",
"targeting": {
"targetType": "DYNAMIC_FILTER",
"filterCriteria": {
"riskTolerance": {"in": ["conservative", "moderate"]},
"hasOpenPositions": true,
"portfolioBeta": {"gte": 1.2},
"stopLossCoverage": {"lt": 0.8}, // less than 80% of positions have stops
"volatilityExperience": "intermediate",
"lastRiskReviewDays": {"gte": 30},
"accountType": "individual",
"kycStatus": "APPROVED"
},
"portfolioValue": {
"amount": 25000.00,
"operator": "GREATER_THAN"
}
},
"pushNotification": {
"enabled": true,
"priority": "HIGH",
"title": "Volatility Risk Alert",
"sound": "alert",
"style": "BIG_TEXT",
"bigText": "VIX at 38. High volatility detected. 40% of your portfolio lacks stop loss protection. Review and adjust risk management now.",
"clickAction": "OPEN_RISK_MANAGEMENT"
},
"templateVariables": {
"fullName": "{{fullName}}",
"vixLevel": "38.5",
"volatilityLevel": "High",
"marketCondition": "Extreme Fear",
"portfolioAtRisk": "{{positionsWithoutStops}}",
"riskExposure": "{{uncoveredValue}}",
"recommendedActions": [
"Implement stop losses on all positions",
"Reduce position sizes by 20-30%",
"Consider hedging strategies",
"Move to cash if uncomfortable",
"Review risk tolerance"
],
"stopLossRecommendations": [
{"symbol": "SPY", "currentPrice": "$425", "suggestedStop": "$395", "protection": "7%"},
{"symbol": "QQQ", "currentPrice": "$380", "suggestedStop": "$350", "protection": "8%"},
{"symbol": "TSLA", "currentPrice": "$245", "suggestedStop": "$200", "protection": "18%"}
],
"riskManagementTools": {
"autoStopLoss": "https://app.olaratech.com/trading/auto-stop-loss",
"portfolioHedging": "https://app.olaratech.com/trading/hedging-tools",
"volatilityProtection": "https://app.olaratech.com/trading/volatility-protection",
"cashPositioning": "https://app.olaratech.com/trading/cash-management"
},
"educationalResources": {
"volatilityTrading": "https://learn.olaratech.com/volatility-trading",
"riskManagement": "https://learn.olaratech.com/risk-management-masterclass",
"stopLossStrategies": "https://learn.olaratech.com/stop-loss-guide"
},
"consultationAvailable": "Free 15-minute risk review available now",
"consultationUrl": "https://app.olaratech.com/consultation/risk-review"
}
}
A/B Testing & Personalization Targeting
Personalized Content Testing
Target users for A/B testing of different content strategies based on their profile.
POST /api/v1/notifications/targeted/GROUP/EMAIL_MISC_FEATURE_ANNOUNCEMENT
{
"subject": "{{subjectVariant}}",
"content": "{{contentVariant}}",
"clientReference": "ab-test-personalization-020",
"targeting": {
"targetType": "DYNAMIC_FILTER",
"filterCriteria": {
"segment": "ab_test_group_a",
"accountAgeDays": {"gte": 90, "lte": 365},
"portfolioValue": {"gte": 10000, "lte": 100000},
"monthlyActivity": "medium",
"notificationEngagement": {"gte": 0.6},
"preferredContentType": "educational",
"lastFeatureAnnouncementDays": {"gte": 14}
}
},
"pushNotification": {
"enabled": true,
"priority": "NORMAL",
"title": "{{pushTitleVariant}}",
"style": "{{pushStyleVariant}}",
"bigText": "{{pushBigTextVariant}}"
},
"templateVariables": {
"fullName": "{{fullName}}",
"firstName": "{{firstName}}",
"subjectVariant": {
"variant_a": "π New Educational Series: Master Technical Analysis",
"variant_b": "π Free Webinar: Technical Analysis for Better Trading",
"variant_c": "π οΈ Skill Up: Advanced Chart Patterns Training"
}["{{assignedVariant}}"],
"contentVariant": {
"variant_a": "Master the art of technical analysis with our comprehensive 5-week course covering chart patterns, indicators, and trading strategies.",
"variant_b": "Join our live webinar this Thursday where our expert analysts break down technical analysis from basics to advanced strategies.",
"variant_c": "Learn to identify and trade chart patterns like flags, pennants, and head & shoulders with real market examples and practice exercises."
}["{{assignedVariant}}"],
"pushTitleVariant": {
"variant_a": "Technical Analysis Course",
"variant_b": "Free Trading Webinar",
"variant_c": "Chart Patterns Training"
}["{{assignedVariant}}"],
"courseDetails": {
"title": "Technical Analysis Mastery",
"duration": "5 weeks",
"format": "Self-paced with live Q&A",
"modules": 12,
"certificate": "Upon completion",
"price": "Free for premium members"
},
"webinarDetails": {
"title": "Technical Analysis Deep Dive",
"date": "Thursday, January 25",
"time": "7:00 PM EST",
"duration": "90 minutes",
"instructor": "Maria Rodriguez, CFA",
"price": "Free"
},
"trainingDetails": {
"title": "Chart Patterns Workshop",
"format": "Interactive online course",
"duration": "3 hours",
"difficulty": "Intermediate",
"includes": "Practice charts, templates, checklists"
},
"enrollmentUrl": "https://learn.olaratech.com/enroll/technical-analysis?variant={{assignedVariant}}",
"previewUrl": "https://learn.olaratech.com/preview/technical-analysis",
"calendarUrl": "https://learn.olaratech.com/calendar",
"assignedVariant": "{{abTestVariant}}"
}
}
The service supports 60+ notification types across multiple categories. Below are comprehensive examples for each category:
π Authentication & Registration
Email Registration (with Push Notification)
{
"type": "EMAIL_REGISTRATION",
"recipient": "newuser@example.com",
"subject": "π Welcome to OlaraTech - Your Trading Journey Begins!",
"clientReference": "registration-welcome-001",
"userId": "b1a2c3d4-e5f6-7890-1234-56789abcdef0",
"pushNotification": {
"enabled": true,
"deviceToken": "firebase-device-token-here",
"priority": "HIGH",
"title": "Welcome to OlaraTech!",
"style": "BIG_TEXT",
"bigText": "Your account is ready! Complete verification and get $10 bonus for your first trade. Start building your portfolio today.",
"clickAction": "OPEN_VERIFICATION"
},
"templateVariables": {
"fullName": "Sarah Johnson",
"username": "SarahJ",
"firstName": "Sarah",
"verificationUrl": "https://app.olaratech.com/verify?token=welcome123&user=SarahJ",
"verificationCode": "WJ9X2P",
"bonusAmount": "$10",
"bonusExpiryDays": "30",
"dashboardUrl": "https://app.olaratech.com/dashboard",
"mobileAppUrl": "https://app.olaratech.com/download",
"supportEmail": "welcome@olaratech.com",
"appName": "OlaraTech",
"currentYear": "2025",
"welcomeVideoUrl": "https://learn.olaratech.com/welcome-video",
"nextSteps": [
"Verify your email",
"Complete KYC verification",
"Add payment method",
"Make your first deposit",
"Place your first trade"
]
}
}
Password Reset (with Security Alert)
{
"type": "EMAIL_PASSWORD_RESET",
"recipient": "user@example.com",
"subject": "π Password Reset Request - Action Required",
"clientReference": "password-reset-security-002",
"userId": "b1a2c3d4-e5f6-7890-1234-56789abcdef0",
"pushNotification": {
"enabled": true,
"deviceToken": "firebase-device-token-here",
"priority": "HIGH",
"title": "Password Reset Requested",
"sound": "alert",
"style": "BIG_TEXT",
"bigText": "A password reset was requested for your account. If this wasn't you, secure your account immediately. Reset link expires in 1 hour.",
"clickAction": "OPEN_SECURITY_SETTINGS"
},
"templateVariables": {
"fullName": "John Doe",
"username": "JohnDoe",
"firstName": "John",
"resetUrl": "https://app.olaratech.com/reset-password?token=xyz456&user=JohnDoe",
"resetCode": "RP8K3M",
"ipAddress": "192.168.1.100",
"location": "New York, USA",
"deviceInfo": "Chrome on Windows",
"requestTime": "2025-01-15 14:30:00 UTC",
"expiryHours": "1",
"securityTips": [
"Never share your password",
"Enable two-factor authentication",
"Monitor account activity regularly",
"Contact support if suspicious"
],
"securitySettingsUrl": "https://app.olaratech.com/security",
"supportUrl": "https://support.olaratech.com/password-help",
"appName": "OlaraTech"
}
}
Email Verification (Multi-Channel)
{
"type": "EMAIL_ONBOARDING_EMAIL_VERIFICATION",
"recipient": "newuser@example.com",
"subject": "π§ Verify Your Email - Complete Your Registration",
"clientReference": "email-verification-onboarding-003",
"userId": "b1a2c3d4-e5f6-7890-1234-56789abcdef0",
"pushNotification": {
"enabled": true,
"deviceToken": "firebase-device-token-here",
"priority": "HIGH",
"title": "Verify Your Email",
"style": "INBOX",
"summaryText": "Complete registration",
"inboxLines": [
"Click verification link",
"Confirm within 24 hours",
"Unlock full platform access"
],
"clickAction": "OPEN_VERIFICATION"
},
"templateVariables": {
"fullName": "Sarah Johnson",
"username": "SarahJ",
"firstName": "Sarah",
"verificationUrl": "https://app.olaratech.com/verify?token=abc123&user=SarahJ",
"verificationCode": "EV7R4N",
"expiryHours": "24",
"benefitsAfterVerification": [
"Full trading access",
"Deposit and withdrawal capabilities",
"Advanced analytics and reporting",
"Priority customer support",
"Exclusive promotions and bonuses"
],
"resendUrl": "https://app.olaratech.com/resend-verification?user=SarahJ",
"changeEmailUrl": "https://app.olaratech.com/change-email",
"helpUrl": "https://support.olaratech.com/email-verification",
"appName": "OlaraTech",
"supportEmail": "verification@olaratech.com"
}
}
Account Activation Success
{
"type": "EMAIL_ONBOARDING_ACCOUNT_ACTIVATED",
"recipient": "user@example.com",
"subject": "π Your Account is Now Active - Start Trading!",
"clientReference": "account-activation-success-004",
"userId": "b1a2c3d4-e5f6-7890-1234-56789abcdef0",
"pushNotification": {
"enabled": true,
"deviceToken": "firebase-device-token-here",
"priority": "HIGH",
"title": "Account Activated!",
"style": "BIG_PICTURE",
"imageUrl": "https://cdn.olaratech.com/account-activated-banner.png",
"bigText": "Congratulations! Your account is fully activated. Deposit funds and start trading with zero commission for the first month."
},
"templateVariables": {
"fullName": "John Doe",
"username": "JohnDoe",
"firstName": "John",
"activationDate": "2025-01-15",
"welcomeBonus": "$25",
"tradingFeeDiscount": "0% commission for first month",
"accountLimits": "$10,000 daily trading limit",
"nextSteps": [
"Complete account funding",
"Set up two-factor authentication",
"Explore trading platform",
"Join our educational webinars"
],
"depositUrl": "https://app.olaratech.com/deposit",
"tradingUrl": "https://app.olaratech.com/trade",
"educationUrl": "https://learn.olaratech.com",
"supportUrl": "https://support.olaratech.com/getting-started",
"appName": "OlaraTech"
}
}
π° Funding & Payments
Deposit Successful (Multi-Channel Celebration)
{
"type": "EMAIL_FUNDING_DEPOSIT_SUCCESSFUL",
"recipient": "trader@example.com",
"subject": "π° Deposit Successful - $2,500 Added to Your Account!",
"clientReference": "deposit-success-celebration-005",
"userId": "b1a2c3d4-e5f6-7890-1234-56789abcdef0",
"pushNotification": {
"enabled": true,
"deviceToken": "firebase-device-token-here",
"priority": "HIGH",
"title": "Deposit Successful! π",
"sound": "success",
"style": "BIG_TEXT",
"bigText": "$2,500.00 USD deposit confirmed! Your account balance is now $8,750. Start trading immediately with zero commissions.",
"clickAction": "OPEN_TRADING"
},
"templateVariables": {
"fullName": "Mike Chen",
"firstName": "Mike",
"amount": "$2,500.00",
"currency": "USD",
"referenceNumber": "DEP-2025-001-789",
"processingMethod": "Instant Bank Transfer",
"dateProcessed": "2025-01-15 14:30:00 UTC",
"previousBalance": "$6,250.00",
"newBalance": "$8,750.00",
"availableForTrading": "$8,750.00",
"depositBonus": "$25.00",
"bonusReason": "First deposit bonus",
"tradingFeeDiscount": "0% commission for 30 days",
"nextSteps": [
"Start trading immediately",
"Set up price alerts",
"Explore new investment opportunities",
"Join our trading community"
],
"tradingUrl": "https://app.olaratech.com/trade",
"dashboardUrl": "https://app.olaratech.com/dashboard",
"transactionHistoryUrl": "https://app.olaratech.com/transactions",
"supportUrl": "https://support.olaratech.com/deposits",
"appName": "OlaraTech",
"currentYear": "2025"
}
}
Deposit Pending Review (AML Check)
{
"type": "EMAIL_FUNDING_DEPOSIT_PENDING",
"recipient": "user@example.com",
"subject": "Deposit Pending Review - Processing Update",
"clientReference": "deposit-pending-aml-006",
"userId": "b1a2c3d4-e5f6-7890-1234-56789abcdef0",
"pushNotification": {
"enabled": true,
"deviceToken": "firebase-device-token-here",
"priority": "NORMAL",
"title": "Deposit Under Review",
"style": "BIG_TEXT",
"bigText": "Your $5,000 deposit is being reviewed for security. This usually takes 1-2 hours. You'll receive another notification when funds are available."
},
"templateVariables": {
"fullName": "John Doe",
"amount": "$5,000.00",
"currency": "USD",
"referenceNumber": "DEP-2025-002-456",
"estimatedProcessingTime": "1-2 hours",
"reviewReason": "Enhanced security verification for large deposits",
"whatHappensNext": [
"Automated security review",
"Manual verification if needed",
"Email confirmation when complete",
"Funds credited to trading account"
],
"securityMeasures": [
"AML compliance checks",
"Fraud prevention algorithms",
"Transaction pattern analysis",
"Identity verification"
],
"statusTrackingUrl": "https://app.olaratech.com/deposit-status?ref=DEP-2025-002-456",
"contactSupport": "For urgent questions: deposits@olaratech.com",
"appName": "OlaraTech"
}
}
Deposit Failed (with Recovery Options)
{
"type": "EMAIL_FUNDING_DEPOSIT_FAILED",
"recipient": "user@example.com",
"subject": "Deposit Failed - Let's Fix This Together",
"clientReference": "deposit-failed-recovery-007",
"userId": "b1a2c3d4-e5f6-7890-1234-56789abcdef0",
"pushNotification": {
"enabled": true,
"deviceToken": "firebase-device-token-here",
"priority": "HIGH",
"title": "Deposit Failed",
"sound": "alert",
"style": "BIG_TEXT",
"bigText": "Your deposit of $1,000 failed due to insufficient funds. Try a different payment method or update your card details.",
"clickAction": "OPEN_DEPOSIT_RETRY"
},
"templateVariables": {
"fullName": "John Doe",
"amount": "$1,000.00",
"currency": "USD",
"referenceNumber": "DEP-2025-003-123",
"failureReason": "Card issuer declined transaction - insufficient funds",
"failureCode": "DECLINE-INSUFFICIENT_FUNDS",
"troubleshootingSteps": [
"Check available balance on your card",
"Try a different payment method",
"Update card details if expired",
"Contact your bank for limits",
"Use bank transfer for large amounts"
],
"alternativeMethods": [
"Bank Transfer (ACH) - Instant, no fees",
"Wire Transfer - For large amounts",
"Different Debit/Credit Card",
"PayPal or digital wallets"
],
"retryUrl": "https://app.olaratech.com/deposit/retry?ref=DEP-2025-003-123",
"updatePaymentUrl": "https://app.olaratech.com/payment-methods",
"supportTicketUrl": "https://support.olaratech.com/new-ticket?category=deposits",
"liveChatUrl": "https://app.olaratech.com/chat?department=deposits",
"appName": "OlaraTech"
}
}
Withdrawal Request (with Security Verification)
{
"type": "EMAIL_FUNDING_WITHDRAWAL_REQUEST",
"recipient": "user@example.com",
"subject": "Withdrawal Request Submitted - Security Verification Required",
"clientReference": "withdrawal-security-verification-008",
"userId": "b1a2c3d4-e5f6-7890-1234-56789abcdef0",
"pushNotification": {
"enabled": true,
"deviceToken": "firebase-device-token-here",
"priority": "HIGH",
"title": "Withdrawal Verification Needed",
"sound": "alert",
"style": "INBOX",
"summaryText": "Complete withdrawal verification",
"inboxLines": [
"2FA code required",
"Processing starts after verification",
"Funds available in 1-3 days"
],
"clickAction": "OPEN_WITHDRAWAL_VERIFICATION"
},
"templateVariables": {
"fullName": "John Doe",
"amount": "$2,500.00",
"currency": "USD",
"referenceNumber": "WD-2025-004-789",
"withdrawalMethod": "Bank Transfer",
"destinationAccount": "****1234 (Chase Bank)",
"securityRequirements": [
"Two-factor authentication code",
"Email confirmation",
"Possibly additional verification for large amounts"
],
"estimatedProcessingTime": "1-3 business days",
"processingFees": "$0.00 (covered by OlaraTech)",
"verificationSteps": [
"Check email for verification code",
"Enter 2FA code from authenticator app",
"Confirm withdrawal details",
"Processing begins immediately"
],
"verificationUrl": "https://app.olaratech.com/withdrawal/verify?ref=WD-2025-004-789",
"cancelUrl": "https://app.olaratech.com/withdrawal/cancel?ref=WD-2025-004-789",
"statusUrl": "https://app.olaratech.com/withdrawal/status?ref=WD-2025-004-789",
"securityHelpUrl": "https://support.olaratech.com/withdrawal-security",
"appName": "OlaraTech"
}
}
Withdrawal Completed (with Receipt)
{
"type": "EMAIL_FUNDING_WITHDRAWAL_COMPLETED",
"recipient": "user@example.com",
"subject": "Withdrawal Completed - Funds Sent Successfully",
"clientReference": "withdrawal-completed-receipt-009",
"userId": "b1a2c3d4-e5f6-7890-1234-56789abcdef0",
"pushNotification": {
"enabled": true,
"deviceToken": "firebase-device-token-here",
"priority": "NORMAL",
"title": "Withdrawal Completed",
"style": "INBOX",
"summaryText": "Funds sent to your account",
"inboxLines": [
"$2,500.00 sent to ****1234",
"Processing time: 2 days",
"Reference: WD-2025-004-789",
"Tax document available"
]
},
"templateVariables": {
"fullName": "John Doe",
"amount": "$2,500.00",
"currency": "USD",
"referenceNumber": "WD-2025-004-789",
"processingTime": "2 business days",
"completionDate": "2025-01-17",
"destinationAccount": "****1234 (Chase Bank)",
"netAmount": "$2,500.00",
"fees": "$0.00",
"remainingBalance": "$3,250.00",
"transactionDetails": {
"requestDate": "2025-01-15 10:30:00 UTC",
"verificationDate": "2025-01-15 10:35:00 UTC",
"processingStartDate": "2025-01-15 14:00:00 UTC",
"completionDate": "2025-01-17 16:45:00 UTC"
},
"receiptUrl": "https://app.olaratech.com/receipts/WD-2025-004-789",
"taxDocumentUrl": "https://app.olaratech.com/tax-documents/2025",
"supportUrl": "https://support.olaratech.com/withdrawals",
"appName": "OlaraTech",
"currentYear": "2025"
}
}
Card Added (with Security Features)
{
"type": "EMAIL_FUNDING_CARD_ADDED",
"recipient": "user@example.com",
"subject": "π³ New Payment Method Added Successfully",
"clientReference": "card-added-security-010",
"userId": "b1a2c3d4-e5f6-7890-1234-56789abcdef0",
"pushNotification": {
"enabled": true,
"deviceToken": "firebase-device-token-here",
"priority": "NORMAL",
"title": "Card Added Successfully",
"style": "INBOX",
"summaryText": "New payment method ready",
"inboxLines": [
"Visa ****4242 added",
"Security verification complete",
"Ready for deposits and withdrawals"
]
},
"templateVariables": {
"fullName": "John Doe",
"cardType": "Visa",
"cardLastFour": "****4242",
"cardholderName": "JOHN DOE",
"expiryDate": "**/27",
"billingAddress": "123 Main St, New York, NY 10001",
"securityFeatures": [
"Tokenization for enhanced security",
"Fraud monitoring active",
"Instant transaction notifications",
"3D Secure verification when required"
],
"verificationStatus": "Verified and Active",
"depositLimit": "$10,000 per transaction",
"withdrawalLimit": "$5,000 per day",
"nextSteps": [
"Make your first deposit",
"Set up auto-investment if desired",
"Review security settings",
"Test small transaction first"
],
"testTransactionUrl": "https://app.olaratech.com/deposit?amount=1.00&card=4242",
"manageCardsUrl": "https://app.olaratech.com/payment-methods",
"securitySettingsUrl": "https://app.olaratech.com/security",
"supportUrl": "https://support.olaratech.com/payment-methods",
"appName": "OlaraTech"
}
}
π Trading & Orders
Order Executed (High Priority Push with Rich Details)
{
"type": "EMAIL_ORDER_EXECUTED",
"recipient": "trader@example.com",
"subject": "π Order Executed Successfully - AAPL x 100 shares",
"clientReference": "order-execution-success-011",
"userId": "b1a2c3d4-e5f6-7890-1234-56789abcdef0",
"pushNotification": {
"enabled": true,
"deviceToken": "firebase-device-token-here",
"priority": "HIGH",
"title": "Order Executed! π",
"sound": "success",
"style": "INBOX",
"summaryText": "AAPL order filled",
"inboxLines": [
"100 shares @ $150.25",
"Total: $15,025.00",
"Commission: $0.00 (free)",
"View in portfolio"
],
"clickAction": "OPEN_TRADE_DETAILS"
},
"templateVariables": {
"fullName": "Mike Chen",
"firstName": "Mike",
"username": "MikeC",
"orderNumber": "ORD-2025-001-789",
"executionId": "EXEC-2025-001-789-001",
"orderType": "Market Buy",
"symbol": "AAPL",
"companyName": "Apple Inc.",
"quantity": "100",
"price": "$150.25",
"totalValue": "$15,025.00",
"commission": "$0.00",
"netAmount": "$15,025.00",
"executionTime": "2025-01-15 14:30:15 UTC",
"marketCondition": "Regular Hours",
"orderSource": "Mobile App",
"accountType": "Individual",
"portfolioImpact": {
"previousValue": "$45,250.00",
"newValue": "$60,275.00",
"changeAmount": "+$15,025.00",
"changePercent": "+33.2%"
},
"positionDetails": {
"currentPosition": "100 shares",
"averageCost": "$150.25",
"marketValue": "$15,025.00",
"unrealizedPnL": "$0.00",
"dayChange": "+$125.00 (+0.8%)"
},
"nextSteps": [
"Monitor your position",
"Set up price alerts",
"Consider diversification",
"Review tax implications"
],
"relatedActions": {
"setStopLoss": "https://app.olaratech.com/trade/set-stop-loss?symbol=AAPL",
"setPriceAlert": "https://app.olaratech.com/alerts/new?symbol=AAPL",
"viewAnalysis": "https://app.olaratech.com/research/AAPL",
"taxOptimizer": "https://app.olaratech.com/tax-harvesting"
},
"performanceMetrics": {
"executionSpeed": "< 100ms",
"priceImprovement": "$0.02 better than market",
"feeSavings": "$4.99 (using free trades)"
},
"receiptUrl": "https://app.olaratech.com/receipts/ORD-2025-001-789",
"portfolioUrl": "https://app.olaratech.com/portfolio",
"tradingUrl": "https://app.olaratech.com/trade",
"supportUrl": "https://support.olaratech.com/trading",
"appName": "OlaraTech",
"currentYear": "2025"
}
}
Order Confirmation (Pre-Execution Review)
{
"type": "EMAIL_ORDER_CONFIRMATION",
"recipient": "trader@example.com",
"subject": "π Order Confirmation - Review Before Execution",
"clientReference": "order-confirmation-review-012",
"userId": "b1a2c3d4-e5f6-7890-1234-56789abcdef0",
"pushNotification": {
"enabled": true,
"deviceToken": "firebase-device-token-here",
"priority": "NORMAL",
"title": "Order Ready for Review",
"style": "INBOX",
"summaryText": "TSLA order pending",
"inboxLines": [
"50 shares @ market price",
"Estimated value: $9,250.00",
"Review and confirm",
"Auto-executes in 5 minutes"
],
"clickAction": "OPEN_ORDER_REVIEW"
},
"templateVariables": {
"fullName": "Mike Chen",
"orderNumber": "ORD-2025-002-456",
"orderType": "Market Buy",
"timeInForce": "Day",
"symbol": "TSLA",
"companyName": "Tesla, Inc.",
"quantity": "50",
"orderPrice": "Market",
"estimatedValue": "$9,250.00",
"estimatedCommission": "$0.00",
"estimatedTotal": "$9,250.00",
"currentMarketPrice": "$185.00",
"lastTradedPrice": "$184.75",
"bidAskSpread": "$184.50 - $185.25",
"marketCap": "$585B",
"volumeToday": "45.2M shares",
"riskAssessment": {
"portfolioAllocation": "8.5% of portfolio",
"diversificationImpact": "Medium - Tech sector",
"volatilityRating": "High",
"liquidityRating": "Excellent"
},
"accountStatus": {
"availableCash": "$12,500.00",
"buyingPower": "$25,000.00",
"maintenanceMargin": "$18,750.00",
"dayTradingBuyingPower": "$50,000.00"
},
"confirmationDetails": {
"autoExecutionTime": "5 minutes",
"cancelUrl": "https://app.olaratech.com/orders/cancel/ORD-2025-002-456",
"modifyUrl": "https://app.olaratech.com/orders/modify/ORD-2025-002-456",
"confirmUrl": "https://app.olaratech.com/orders/confirm/ORD-2025-002-456"
},
"educationalContent": {
"marketAnalysis": "https://learn.olaratech.com/TSLA-analysis",
"tradingStrategies": "https://learn.olaratech.com/market-orders",
"riskManagement": "https://learn.olaratech.com/stop-loss-guide"
},
"supportContact": "trading@olaratech.com",
"appName": "OlaraTech"
}
}
Stop Loss Triggered (Risk Management Alert)
{
"type": "EMAIL_ORDER_STOP_LOSS_TRIGGERED",
"recipient": "trader@example.com",
"subject": "π‘οΈ Stop Loss Executed - Risk Management Activated",
"clientReference": "stop-loss-protection-013",
"userId": "b1a2c3d4-e5f6-7890-1234-56789abcdef0",
"pushNotification": {
"enabled": true,
"deviceToken": "firebase-device-token-here",
"priority": "HIGH",
"title": "Stop Loss Triggered",
"sound": "alert",
"style": "BIG_TEXT",
"bigText": "TSLA stop loss executed at $180.00. Sold 50 shares, limiting losses. Your risk management strategy worked!",
"clickAction": "OPEN_PORTFOLIO_REVIEW"
},
"templateVariables": {
"fullName": "Mike Chen",
"executionId": "STOP-2025-003-123",
"symbol": "TSLA",
"companyName": "Tesla, Inc.",
"quantity": "50",
"stopPrice": "$180.00",
"executionPrice": "$179.75",
"totalValue": "$8,987.50",
"commission": "$0.00",
"netProceeds": "$8,987.50",
"lossAmount": "$637.50",
"lossPercent": "-6.6%",
"executionTime": "2025-01-15 11:45:22 UTC",
"triggerReason": "Price dropped below stop loss level",
"marketCondition": "High volatility - earnings reaction",
"portfolioImpact": {
"previousValue": "$68,250.00",
"newValue": "$59,262.50",
"changeAmount": "-$8,987.50",
"changePercent": "-13.2%"
},
"riskManagement": {
"strategy": "Trailing stop loss",
"originalStop": "$190.00",
"adjustedStop": "$180.00",
"protectionLevel": "10% from peak",
"savedCapital": "$2,125.00 (additional loss prevented)"
},
"lessonsLearned": [
"Stop losses protect capital",
"Consider position sizing",
"Review market conditions",
"Adjust strategy as needed"
],
"recoveryActions": {
"rebalancePortfolio": "https://app.olaratech.com/portfolio/rebalance",
"reviewStrategy": "https://learn.olaratech.com/risk-management",
"marketAnalysis": "https://app.olaratech.com/research/market-overview",
"consultAdvisor": "https://app.olaratech.com/advisor/chat"
},
"receiptUrl": "https://app.olaratech.com/receipts/STOP-2025-003-123",
"portfolioUrl": "https://app.olaratech.com/portfolio",
"tradingUrl": "https://app.olaratech.com/trade",
"supportUrl": "https://support.olaratech.com/risk-management",
"appName": "OlaraTech"
}
}
π Portfolio & Margin
Margin Call Alert (Critical Priority)
{
"type": "EMAIL_PORTFOLIO_MARGIN_CALL_ALERT",
"recipient": "user@example.com",
"subject": "Margin Call Alert",
"clientReference": "client-123",
"userId": "b1a2c3d4-e5f6-7890-1234-56789abcdef0",
"pushNotification": {
"enabled": true,
"deviceToken": "firebase-device-token-here",
"priority": "HIGH",
"title": "Margin Call Alert",
"sound": "alert",
"clickAction": "OPEN_MARGIN_DETAILS"
},
"templateVariables": {
"fullName": "John Doe",
"marginLevel": "25.5%",
"portfolioValue": "$50,000.00",
"requiredMargin": "$15,000.00",
"deadline": "2025-01-20",
"dashboardUrl": "https://app.olaratech.com/margin",
"supportUrl": "https://support.olaratech.com/margin-help",
"appName": "OlaraTech"
}
}
Low Balance Alert
{
"type": "EMAIL_PORTFOLIO_LOW_BALANCE_ALERT",
"recipient": "user@example.com",
"subject": "Low Balance Alert",
"clientReference": "client-123",
"userId": "b1a2c3d4-e5f6-7890-1234-56789abcdef0",
"pushNotification": {
"enabled": true,
"deviceToken": "firebase-device-token-here",
"priority": "NORMAL",
"title": "Low Balance Alert",
"sound": "default"
},
"templateVariables": {
"fullName": "John Doe",
"currentBalance": "$250.00",
"minimumBalance": "$500.00",
"depositUrl": "https://app.olaratech.com/deposit",
"dashboardUrl": "https://app.olaratech.com/dashboard",
"appName": "OlaraTech"
}
}
Dividend Payment
{
"type": "EMAIL_PORTFOLIO_DIVIDEND_PAYMENT",
"recipient": "user@example.com",
"subject": "Dividend Payment Notification",
"clientReference": "client-123",
"userId": "b1a2c3d4-e5f6-7890-1234-56789abcdef0",
"templateVariables": {
"fullName": "John Doe",
"symbol": "AAPL",
"dividendAmount": "$25.50",
"sharesOwned": "100",
"paymentDate": "2025-01-15",
"dashboardUrl": "https://app.olaratech.com/dividends",
"appName": "OlaraTech"
}
}
π Security & KYC
New Device Login Alert
{
"type": "EMAIL_SECURITY_NEW_DEVICE_LOGIN",
"recipient": "user@example.com",
"subject": "New Device Login Detected",
"clientReference": "client-123",
"userId": "b1a2c3d4-e5f6-7890-1234-56789abcdef0",
"pushNotification": {
"enabled": true,
"deviceToken": "firebase-device-token-here",
"priority": "HIGH",
"title": "New Device Login",
"sound": "alert"
},
"templateVariables": {
"fullName": "John Doe",
"deviceInfo": "iPhone 13, Safari",
"location": "New York, USA",
"ipAddress": "192.168.1.100",
"loginTime": "2025-01-15 14:30:00 UTC",
"securityUrl": "https://app.olaratech.com/security",
"appName": "OlaraTech"
}
}
KYC Approved
{
"type": "EMAIL_KYC_APPROVED",
"recipient": "user@example.com",
"subject": "KYC Approved",
"clientReference": "client-123",
"userId": "b1a2c3d4-e5f6-7890-1234-56789abcdef0",
"templateVariables": {
"fullName": "John Doe",
"appName": "OlaraTech",
"dashboardUrl": "https://app.olaratech.com/dashboard",
"tradingLimits": "Increased to $100,000 daily",
"approvedDate": "2025-01-15"
}
}
KYC Expiry Reminder
{
"type": "EMAIL_KYC_EXPIRY_REMINDER",
"recipient": "user@example.com",
"subject": "KYC Expiry Reminder",
"clientReference": "client-123",
"userId": "b1a2c3d4-e5f6-7890-1234-56789abcdef0",
"templateVariables": {
"fullName": "John Doe",
"username": "JohnDoe",
"appName": "OlaraTech",
"kycUpdateUrl": "https://app.olaratech.com/kyc/update",
"expiryDate": "2025-02-15",
"daysUntilExpiry": "30"
}
}
π’ Corporate & Business
Corporate Account Application
{
"type": "EMAIL_CORPORATE_ACCOUNT_APPLICATION",
"recipient": "user@example.com",
"subject": "Corporate Account Application Received",
"clientReference": "client-123",
"userId": "b1a2c3d4-e5f6-7890-1234-56789abcdef0",
"templateVariables": {
"fullName": "Jane Smith",
"companyName": "ABC Corporation",
"applicationId": "APP-789012",
"reviewTime": "5-7 business days",
"dashboardUrl": "https://app.olaratech.com/corporate",
"appName": "OlaraTech"
}
}
Fee Schedule Change
{
"type": "EMAIL_CORPORATE_FEE_SCHEDULE_CHANGE",
"recipient": "user@example.com",
"subject": "Fee Schedule Change Notification",
"clientReference": "client-123",
"userId": "b1a2c3d4-e5f6-7890-1234-56789abcdef0",
"templateVariables": {
"fullName": "Jane Smith",
"username": "JaneSmith",
"appName": "OlaraTech",
"feeScheduleUrl": "https://app.olaratech.com/fees",
"effectiveDate": "2025-02-01",
"supportUrl": "https://support.olaratech.com/fees"
}
}
π Miscellaneous & Marketing
Birthday Greeting
{
"type": "EMAIL_MISC_BIRTHDAY_GREETING",
"recipient": "user@example.com",
"subject": "Happy Birthday from OlaraTech!",
"clientReference": "client-123",
"userId": "b1a2c3d4-e5f6-7890-1234-56789abcdef0",
"templateVariables": {
"fullName": "John Doe",
"appName": "OlaraTech",
"birthdayBonus": "$10 trading credit",
"dashboardUrl": "https://app.olaratech.com/dashboard"
}
}
Referral Bonus
{
"type": "EMAIL_MISC_REFERRAL_BONUS",
"recipient": "user@example.com",
"subject": "You've Earned a Referral Bonus!",
"clientReference": "client-123",
"userId": "b1a2c3d4-e5f6-7890-1234-56789abcdef0",
"templateVariables": {
"fullName": "John Doe",
"amount": "$50.00",
"referralName": "Jane Smith",
"appName": "OlaraTech",
"dashboardUrl": "https://app.olaratech.com/referrals"
}
}
Feature Announcement
{
"type": "EMAIL_MISC_FEATURE_ANNOUNCEMENT",
"recipient": "user@example.com",
"subject": "New Feature: Advanced Analytics Dashboard",
"clientReference": "client-123",
"userId": "b1a2c3d4-e5f6-7890-1234-56789abcdef0",
"templateVariables": {
"fullName": "John Doe",
"featureName": "Advanced Analytics Dashboard",
"featureUrl": "https://app.olaratech.com/analytics",
"appName": "OlaraTech",
"releaseDate": "2025-01-20"
}
}
π± SMS Notifications
OTP SMS
{
"type": "SMS_OTP",
"recipient": "+1234567890",
"clientReference": "client-123",
"templateVariables": {
"code": "123456",
"expiryMinutes": 10
}
}
Order Confirmation SMS
{
"type": "SMS_ORDER_CONFIRMATION",
"recipient": "+1234567890",
"clientReference": "client-123",
"templateVariables": {
"orderNumber": "ORD-12345",
"amount": "$1,500.00",
"status": "Confirmed"
}
}
π¬ Slack Notifications
Admin Alert
{
"type": "SLACK_MESSAGE",
"recipient": "#alerts",
"clientReference": "client-123",
"userId": "b1a2c3d4-e5f6-7890-1234-56789abcdef0",
"templateVariables": {
"alertType": "High CPU Usage",
"message": "CPU usage exceeded 90% on server-1",
"priority": "HIGH",
"timestamp": "2025-01-15 14:30:00 UTC"
}
}
π Complete Notification Types Reference
Authentication & Onboarding (12 types)
EMAIL_REGISTRATION- User registration welcomeEMAIL_PASSWORD_RESET- Password reset instructionsEMAIL_ONBOARDING_WELCOME- Welcome emailEMAIL_ONBOARDING_EMAIL_VERIFICATION- Email verificationEMAIL_ONBOARDING_REFERRAL_INVITATION- Referral invitationEMAIL_ONBOARDING_COMPLETE_PROFILE_REMINDER- Profile completion reminderEMAIL_ONBOARDING_ACCOUNT_CREATED- Account creation confirmationEMAIL_SECURITY_PASSWORD_RESET- Security password resetEMAIL_SECURITY_PASSWORD_CHANGED- Password change confirmationEMAIL_SECURITY_NEW_DEVICE_LOGIN- New device login alertEMAIL_SECURITY_ACCOUNT_LOCKED- Account locked notificationEMAIL_SECURITY_ACCOUNT_REACTIVATED- Account reactivation
Funding & Payments (8 types)
EMAIL_FUNDING_DEPOSIT_SUCCESSFUL- Deposit success confirmationEMAIL_FUNDING_DEPOSIT_FAILED- Deposit failure notificationEMAIL_FUNDING_DEPOSIT_INITIATED- Deposit initiationEMAIL_FUNDING_WITHDRAWAL_SUCCESSFUL- Withdrawal successEMAIL_FUNDING_WITHDRAWAL_FAILED- Withdrawal failureEMAIL_FUNDING_WITHDRAWAL_REQUEST- Withdrawal request receivedEMAIL_FUNDING_CARD_ADDED- Card addition confirmationEMAIL_FUNDING_CARD_REMOVED- Card removal confirmation
Trading & Orders (10 types)
EMAIL_ORDER_CONFIRMATION- Order confirmationEMAIL_ORDER_EXECUTED- Order execution notificationEMAIL_ORDER_CANCELLED- Order cancellationEMAIL_ORDER_PLACED- Order placement confirmationEMAIL_ORDER_EXPIRED- Order expirationEMAIL_ORDER_STOP_LOSS_TRIGGERED- Stop loss executionEMAIL_ORDER_CORPORATE_ACTION- Corporate action notificationEMAIL_PAYMENT_CONFIRMATION- Payment confirmationEMAIL_ORDER_CONFIRMATION_TEMPLATE- Order confirmation (legacy)EMAIL_DEVICE_REGISTRATION- Device registration
Portfolio & Risk Management (6 types)
EMAIL_PORTFOLIO_STATEMENT- Portfolio statementEMAIL_PORTFOLIO_TRADE_SUMMARY- Trade summaryEMAIL_PORTFOLIO_DIVIDEND_PAYMENT- Dividend paymentEMAIL_PORTFOLIO_MARGIN_CALL_ALERT- Margin call alertEMAIL_PORTFOLIO_LOW_BALANCE_ALERT- Low balance alertEMAIL_PORTFOLIO_POSITION_LIQUIDATION- Position liquidation
KYC & Compliance (5 types)
EMAIL_KYC_APPROVED- KYC approvalEMAIL_KYC_REJECTED- KYC rejectionEMAIL_KYC_EDD- Enhanced due diligence requiredEMAIL_KYC_EXPIRY_REMINDER- KYC expiry reminderEMAIL_KYC_SUBMISSION_RECEIVED- KYC submission received
Corporate & Business (4 types)
EMAIL_CORPORATE_ACCOUNT_APPLICATION- Corporate account applicationEMAIL_CORPORATE_ACCOUNT_APPROVED- Corporate account approvalEMAIL_CORPORATE_ACCOUNT_REJECTED- Corporate account rejectionEMAIL_CORPORATE_FEE_SCHEDULE_CHANGE- Fee schedule changeEMAIL_CORPORATE_REPORTS- Corporate reports
Security & Alerts (6 types)
EMAIL_SECURITY_2FA_CHANGED- 2FA settings changedEMAIL_SECURITY_SUSPICIOUS_ACTIVITY- Suspicious activity detectedEMAIL_SECURITY_ACCOUNT_LOCKED- Account lockedEMAIL_SECURITY_ACCOUNT_REACTIVATED- Account reactivatedEMAIL_SECURITY_NEW_DEVICE_LOGIN- New device loginEMAIL_SECURITY_PASSWORD_CHANGED- Password changed
Support & Communication (5 types)
EMAIL_SUPPORT_TICKET_CREATED- Support ticket createdEMAIL_SUPPORT_TICKET_UPDATED- Support ticket updatedEMAIL_SUPPORT_TICKET_RESOLVED- Support ticket resolvedEMAIL_SUPPORT_POLICY_UPDATE- Policy updateEMAIL_SUPPORT_FEEDBACK_REQUEST- Feedback request
Miscellaneous (4 types)
EMAIL_MISC_REFERRAL_BONUS- Referral bonus earnedEMAIL_MISC_FEATURE_ANNOUNCEMENT- Feature announcementEMAIL_MISC_BIRTHDAY_GREETING- Birthday greetingEMAIL_MISC_ACCOUNT_CLOSURE- Account closureEMAIL_MISC_TAX_DOCUMENT_READY- Tax document ready
SMS Types (2 types)
SMS_OTP- One-time passwordSMS_ORDER_CONFIRMATION- Order confirmation SMS
Slack Types (4 types)
SLACK_MESSAGE- Regular Slack messagesSLACK_ATTACHMENT- Messages with file attachmentsSLACK_EPHEMERAL- Ephemeral messages (visible only to recipient)SLACK_MODAL- Interactive modal dialogs
π οΈ Configuration
application.yml
spring:
datasource:
url: jdbc:postgresql://localhost:5432/notification-service-db # Use jdbc:h2:mem:testdb for local development
username: admin
password: admin
mail:
host: smtp.zoho.com
port: 587
username: devops@olaratech.com
password: your_password
flyway:
enabled: true
locations: classpath:db/migration
data:
redis:
host: localhost
port: 6379
rabbitmq:
host: localhost
firebase:
service-account-key-path: ${FIREBASE_SERVICE_ACCOUNT_KEY_PATH:classpath:firebase-service-account.json}
project-id: ${FIREBASE_PROJECT_ID:olara-trading-platform}
database-url: ${FIREBASE_DATABASE_URL:https://olara-trading-platform-default-rtdb.firebaseio.com/}
enabled: ${FIREBASE_ENABLED:true}
slack:
bot-token: ${SLACK_BOT_TOKEN:token}
notification:
rate-limit:
limits:
EMAIL: 100
SMS: 10
SLACK: 50
windows:
EMAIL: 1h
SMS: 1h
SLACK: 1h
π§ͺ Testing
Run Unit Tests
./gradlew test
Run Integration Tests
./gradlew integrationTest
π Examples
Sending a Notification Programmatically
NotificationRequest request = NotificationRequest.builder()
.type(NotificationType.EMAIL_REGISTRATION)
.recipient("user@example.com")
.subject("Welcome to Our Service!")
.clientReference("client-123")
.tenantId(UUID.randomUUID())
.userId(UUID.randomUUID())
.templateVariables(Map.of(
"verificationUrl", "https://example.com/verify?token=abc123",
"username", "JohnDoe"
))
.build();
NotificationResponse response = notificationService.sendNotification(request);
System.out.println("Notification sent with ID: " + response.getId());
Sending a Push Notification
NotificationRequest request = NotificationRequest.builder()
.type(NotificationType.EMAIL_ORDER_EXECUTED)
.recipient("user@example.com")
.pushNotification(PushNotificationConfig.builder()
.enabled(true)
.deviceToken("firebase-device-token")
.priority(NotificationPriority.HIGH)
.title("Trade Executed")
.sound("default")
.build())
.templateVariables(Map.of(
"symbol", "AAPL",
"quantity", "100",
"price", "150.25"
))
.build();
π Monitoring
- Prometheus: Metrics are exposed at
/actuator/prometheus. - Elastic APM: Distributed tracing is enabled for debugging and performance monitoring.
- Loki: Centralized logging support via Loki Logback appender.
π‘οΈ Security
- Ensure sensitive environment variables (e.g., SMTP credentials) are stored securely.
- Use HTTPS for all API communications.
π€ Contributing
We welcome contributions! Please follow these steps:
1. Fork the repository.
2. Create a new branch (feature/my-feature).
3. Commit your changes.
4. Push to your branch and create a pull request.
π License
This project is licensed under the MIT License. See the LICENSE file for details.
οΏ½ Error Handling & Troubleshooting
This section covers error scenarios, retry mechanisms, and troubleshooting strategies for production deployments.
Retry Logic & Circuit Breaker Configuration
The service implements sophisticated retry logic with exponential backoff and circuit breaker patterns:
# application.yml - Retry Configuration
resilience4j:
retry:
instances:
notification-retry:
max-attempts: 3
wait-duration: 1s
enable-exponential-backoff: true
exponential-backoff-multiplier: 2
retry-on-result-predicate: com.olara.resilience.NotificationRetryPredicate
retry-on-exception-predicate: com.olara.resilience.NotificationExceptionPredicate
circuitbreaker:
instances:
notification-circuit:
failure-rate-threshold: 50
wait-duration-in-open-state: 30s
permitted-number-of-calls-in-half-open-state: 3
sliding-window-size: 10
minimum-number-of-calls: 5
Error Response Examples
Provider Failure Scenarios
Firebase Push Notification Failure
{
"timestamp": "2024-01-15T10:30:45.123Z",
"status": 500,
"error": "Internal Server Error",
"message": "Push notification delivery failed",
"path": "/api/v1/notifications/targeted/INDIVIDUAL/EMAIL_ORDER_EXECUTED",
"details": {
"errorCode": "PUSH_DELIVERY_FAILED",
"provider": "FIREBASE",
"recipientId": "user_12345",
"notificationId": "notif_67890",
"failureReason": "Invalid registration token",
"retryCount": 2,
"nextRetryAt": "2024-01-15T10:31:45.123Z",
"circuitBreakerState": "CLOSED"
}
}
SMTP Email Bounce
{
"timestamp": "2024-01-15T11:15:20.456Z",
"status": 400,
"error": "Bad Request",
"message": "Email delivery failed - permanent bounce",
"path": "/api/v1/notifications/targeted/GROUP/EMAIL_PORTFOLIO_LOW_BALANCE_ALERT",
"details": {
"errorCode": "EMAIL_BOUNCE",
"provider": "SMTP",
"recipientEmail": "invalid@nonexistent.com",
"bounceType": "PERMANENT",
"bounceReason": "Mailbox does not exist",
"notificationId": "notif_54321",
"suppressed": true,
"suppressionReason": "Invalid email address"
}
}
Twilio SMS Failure
{
"timestamp": "2024-01-15T12:00:30.789Z",
"status": 500,
"error": "Internal Server Error",
"message": "SMS delivery failed",
"path": "/api/v1/notifications/targeted/INDIVIDUAL/SMS_AUTH_2FA_CODE",
"details": {
"errorCode": "SMS_DELIVERY_FAILED",
"provider": "TWILIO",
"recipientPhone": "+1234567890",
"notificationId": "notif_98765",
"twilioErrorCode": 21211,
"failureReason": "Invalid phone number",
"retryCount": 1,
"nextRetryAt": "2024-01-15T12:01:30.789Z"
}
}
Circuit Breaker Activation
Circuit Breaker Open State
{
"timestamp": "2024-01-15T13:45:15.234Z",
"status": 503,
"error": "Service Unavailable",
"message": "Notification service temporarily unavailable",
"path": "/api/v1/notifications/targeted/GROUP/SLACK_TRADING_ALERT",
"details": {
"errorCode": "CIRCUIT_BREAKER_OPEN",
"provider": "SLACK",
"circuitBreakerState": "OPEN",
"failureRate": 75.5,
"waitDurationRemaining": "25s",
"nextAttemptAt": "2024-01-15T13:46:15.234Z",
"queuedNotifications": 15,
"estimatedRecoveryTime": "30s"
}
}
Rate Limiting Errors
Rate Limit Exceeded
{
"timestamp": "2024-01-15T14:20:10.567Z",
"status": 429,
"error": "Too Many Requests",
"message": "Rate limit exceeded for notification type",
"path": "/api/v1/notifications/targeted/INDIVIDUAL/PUSH_ORDER_EXECUTED",
"details": {
"errorCode": "RATE_LIMIT_EXCEEDED",
"notificationType": "PUSH_ORDER_EXECUTED",
"recipientId": "user_11111",
"currentRequests": 25,
"limit": 20,
"windowSeconds": 60,
"resetAt": "2024-01-15T14:21:10.567Z",
"retryAfter": 50,
"queued": true,
"queuePosition": 3
}
}
Template Processing Errors
Missing Template Variables
{
"timestamp": "2024-01-15T15:05:25.890Z",
"status": 400,
"error": "Bad Request",
"message": "Template processing failed",
"path": "/api/v1/notifications/targeted/GROUP/EMAIL_PORTFOLIO_DIVIDEND_PAYMENT",
"details": {
"errorCode": "TEMPLATE_PROCESSING_ERROR",
"templateType": "EMAIL",
"notificationType": "EMAIL_PORTFOLIO_DIVIDEND_PAYMENT",
"missingVariables": ["dividendAmount", "paymentDate"],
"providedVariables": ["fullName", "accountId"],
"templatePath": "templates/dividend-payment.html",
"validationErrors": [
"Variable 'dividendAmount' is required but not provided",
"Variable 'paymentDate' is required but not provided"
]
}
}
Targeting Filter Errors
Invalid Filter Criteria
{
"timestamp": "2024-01-15T16:30:40.123Z",
"status": 400,
"error": "Bad Request",
"message": "Invalid targeting filter criteria",
"path": "/api/v1/notifications/targeted/DYNAMIC_FILTER/EMAIL_MISC_FEATURE_ANNOUNCEMENT",
"details": {
"errorCode": "INVALID_FILTER_CRITERIA",
"targetType": "DYNAMIC_FILTER",
"invalidFields": ["portfolioValue.operator", "accountAgeDays.value"],
"validationErrors": [
"portfolioValue.operator must be one of: GREATER_THAN, LESS_THAN, EQUAL, BETWEEN",
"accountAgeDays.value must be a positive integer"
],
"providedCriteria": {
"portfolioValue": {"operator": "INVALID_OP", "value": 100000},
"accountAgeDays": {"operator": "GREATER_THAN", "value": -30}
}
}
}
Troubleshooting Payloads
Health Check Response
{
"status": "UP",
"components": {
"db": {
"status": "UP",
"details": {
"database": "PostgreSQL",
"validationQuery": "SELECT 1"
}
},
"redis": {
"status": "UP",
"details": {
"version": "7.0.5"
}
},
"rabbitmq": {
"status": "UP",
"details": {
"version": "3.12.0"
}
},
"firebase": {
"status": "UP",
"details": {
"projectId": "olara-tech-prod"
}
},
"circuitBreaker": {
"status": "UP",
"details": {
"notification-circuit": "CLOSED",
"failureRate": 0.0
}
}
},
"metrics": {
"notifications.sent.last24h": 15420,
"notifications.failed.last24h": 23,
"notifications.queued.current": 5,
"rateLimit.hits.last1h": 45
}
}
Diagnostic Notification Payload
{
"subject": "π§ Notification Service Diagnostic Report",
"content": "System health and performance metrics for notification service",
"clientReference": "diagnostic-report-021",
"targeting": {
"targetType": "INDIVIDUAL",
"recipientId": "admin_user_001"
},
"pushNotification": {
"enabled": true,
"priority": "NORMAL",
"title": "System Diagnostic Available",
"style": "INBOX",
"summaryText": "Notification service health report",
"inboxLines": [
"Service Status: HEALTHY",
"Uptime: 15 days",
"Success Rate: 99.85%",
"View detailed metrics"
]
},
"templateVariables": {
"reportDate": "2024-01-15",
"serviceUptime": "15 days, 4 hours",
"totalNotifications": "2,450,123",
"successRate": "99.85%",
"failureRate": "0.15%",
"topFailureReasons": [
{"reason": "Invalid email address", "count": 1250},
{"reason": "Phone number unreachable", "count": 890},
{"reason": "Firebase token expired", "count": 567}
],
"performanceMetrics": {
"averageResponseTime": "245ms",
"p95ResponseTime": "890ms",
"p99ResponseTime": "1.2s",
"throughputPerMinute": "1,250 notifications"
},
"circuitBreakerStatus": {
"notification-circuit": "CLOSED",
"failureRate": "2.1%",
"lastFailure": "2024-01-15T08:30:00Z"
},
"queueStatus": {
"activeQueues": 3,
"queuedMessages": 12,
"processingRate": "45 msg/sec"
},
"providerHealth": {
"smtp": "HEALTHY",
"twilio": "HEALTHY",
"slack": "HEALTHY",
"firebase": "HEALTHY"
},
"alerts": [
"Rate limit threshold approaching for SMS (85% of limit)",
"Circuit breaker failure rate elevated (2.1% > 1% threshold)"
],
"recommendations": [
"Monitor SMS rate limits",
"Review recent Firebase token failures",
"Consider scaling if throughput continues to grow"
],
"dashboardUrl": "https://monitoring.olaratech.com/notification-service",
"logsUrl": "https://logs.olaratech.com/notification-service",
"configUrl": "https://config.olaratech.com/notification-service"
}
}
Recovery Strategies
Manual Retry for Failed Notifications
# Retry specific failed notification
curl -X POST https://api.olaratech.com/api/v1/notifications/retry/notif_67890 \
-H "Authorization: Bearer <admin_token>" \
-H "Content-Type: application/json" \
-d '{
"forceRetry": true,
"bypassCircuitBreaker": false,
"updateContactInfo": true
}'
Bulk Failure Recovery
# Retry all failed notifications from last hour
curl -X POST https://api.olaratech.com/api/v1/notifications/bulk-retry \
-H "Authorization: Bearer <admin_token>" \
-H "Content-Type: application/json" \
-d '{
"timeRange": {
"start": "2024-01-15T00:00:00Z",
"end": "2024-01-15T01:00:00Z"
},
"failureTypes": ["PUSH_DELIVERY_FAILED", "EMAIL_BOUNCE"],
"maxRetries": 1000,
"batchSize": 50
}'
Circuit Breaker Manual Reset
# Manually reset circuit breaker (admin only)
curl -X POST https://api.olaratech.com/api/v1/admin/circuit-breaker/reset \
-H "Authorization: Bearer <admin_token>" \
-H "Content-Type: application/json" \
-d '{
"circuitBreakerName": "notification-circuit",
"reason": "Manual intervention after provider recovery"
}'
π Bulk Operations & Performance Optimization
This section covers strategies for handling large-scale notifications, performance optimization, and scaling patterns.
Bulk Notification Strategies
Mass Marketing Campaigns
Send personalized notifications to thousands of users with intelligent batching and rate limiting.
POST /api/v1/notifications/bulk
{
"campaignId": "q4-portfolio-review-campaign-022",
"campaignName": "Q4 Portfolio Review Campaign",
"notificationType": "EMAIL_PORTFOLIO_LOW_BALANCE_ALERT",
"totalRecipients": 50000,
"batchSize": 1000,
"delayBetweenBatches": 5000,
"rateLimitPerMinute": 5000,
"targeting": {
"targetType": "DYNAMIC_FILTER",
"filterCriteria": {
"portfolioValue": {"gte": 10000, "lte": 500000},
"lastLoginDays": {"lte": 30},
"accountType": "individual",
"kycStatus": "APPROVED",
"hasActiveInvestments": true,
"notificationPreference": {"nin": ["none", "minimal"]}
}
},
"content": {
"subject": "Your Q4 Portfolio Performance Review is Ready",
"templateVariables": {
"fullName": "{{fullName}}",
"portfolioValue": "{{portfolioValue}}",
"quarterlyReturn": "{{quarterlyReturn}}",
"topPerformer": "{{topPerformer}}",
"reviewUrl": "https://app.olaratech.com/portfolio/review/q4-2024",
"advisorContact": "advisor@olaratech.com"
}
},
"pushNotification": {
"enabled": true,
"priority": "NORMAL",
"title": "Portfolio Review Available",
"style": "BIG_TEXT",
"bigText": "Your Q4 portfolio review is ready. See how your investments performed this quarter."
},
"schedule": {
"startTime": "2024-12-15T09:00:00Z",
"endTime": "2024-12-15T17:00:00Z",
"timezone": "America/New_York",
"businessHoursOnly": true
},
"monitoring": {
"progressCallbackUrl": "https://campaign.olaratech.com/webhook/progress",
"completionCallbackUrl": "https://campaign.olaratech.com/webhook/complete",
"failureCallbackUrl": "https://campaign.olaratech.com/webhook/failure"
}
}
Regulatory Compliance Notifications
Send time-sensitive regulatory notifications to all affected users with delivery tracking.
POST /api/v1/notifications/bulk/compliance
{
"campaignId": "sec-rule-605-compliance-023",
"campaignName": "SEC Rule 605 Disclosure Update",
"notificationType": "EMAIL_MISC_FEATURE_ANNOUNCEMENT",
"priority": "HIGH",
"totalRecipients": 250000,
"batchSize": 500,
"delayBetweenBatches": 2000,
"maxConcurrentBatches": 10,
"targeting": {
"targetType": "ALL_USERS",
"filterCriteria": {
"accountType": "individual",
"kycStatus": "APPROVED",
"country": "US",
"lastActivityDays": {"lte": 365},
"notificationPreference": {"nin": ["none"]}
}
},
"content": {
"subject": "π Important: Updated Order Execution Quality Disclosure",
"templateVariables": {
"fullName": "{{fullName}}",
"effectiveDate": "January 1, 2025",
"disclosureUrl": "https://www.olaratech.com/disclosures/sec-rule-605",
"contactSupport": "compliance@olaratech.com",
"optOutUrl": "https://app.olaratech.com/notifications/unsubscribe?type=regulatory"
}
},
"channels": ["EMAIL", "PUSH"],
"pushNotification": {
"enabled": true,
"priority": "HIGH",
"title": "Regulatory Disclosure Update",
"style": "BIG_TEXT",
"bigText": "Important regulatory update regarding order execution quality disclosures. Please review the updated information.",
"clickAction": "OPEN_DISCLOSURE"
},
"compliance": {
"regulation": "SEC_RULE_605",
"deliveryDeadline": "2024-12-31T23:59:59Z",
"proofOfDelivery": true,
"auditTrail": true,
"retentionPeriodDays": 2555
},
"monitoring": {
"realTimeMetrics": true,
"deliveryReceipts": true,
"bounceTracking": true,
"unsubscribeTracking": true
}
}
Performance Optimization Patterns
Async Processing with Callbacks
Handle large notification batches asynchronously with progress callbacks.
POST /api/v1/notifications/async-batch
{
"batchId": "market-volatility-alert-024",
"operation": "VOLATILITY_RISK_NOTIFICATION",
"totalRecipients": 100000,
"processingMode": "ASYNC_PARALLEL",
"maxConcurrency": 20,
"targeting": {
"targetType": "DYNAMIC_FILTER",
"filterCriteria": {
"riskTolerance": {"in": ["conservative", "moderate"]},
"hasOpenPositions": true,
"portfolioValue": {"gte": 25000},
"volatilityPreference": "low",
"notificationEnabled": true
}
},
"content": {
"subject": "β οΈ Market Volatility Alert - Risk Management Recommendations",
"templateVariables": {
"fullName": "{{fullName}}",
"vixLevel": "{{currentVixLevel}}",
"volatilityLevel": "{{volatilityLevel}}",
"portfolioImpact": "{{portfolioImpact}}",
"recommendationsUrl": "https://app.olaratech.com/risk/volatility-alert",
"consultationUrl": "https://app.olaratech.com/consultation/volatility"
}
},
"callbacks": {
"progress": {
"url": "https://api.olaratech.com/webhooks/notification-progress",
"headers": {"Authorization": "Bearer webhook_token"},
"frequency": "EVERY_1000"
},
"completion": {
"url": "https://api.olaratech.com/webhooks/notification-complete",
"method": "POST",
"retries": 3
},
"failure": {
"url": "https://api.olaratech.com/webhooks/notification-failure",
"method": "POST",
"includeFailedRecipients": true
}
},
"performance": {
"targetCompletionTime": "2h",
"acceptableFailureRate": 0.01,
"throttleOnHighFailureRate": true,
"adaptiveBatching": true
}
}
Database-Optimized Bulk Targeting
Use pre-computed segments for ultra-fast bulk targeting.
POST /api/v1/notifications/segmented-bulk
{
"segmentId": "premium-investor-segment-025",
"segmentName": "Premium Investors Q4 2024",
"notificationType": "EMAIL_PORTFOLIO_DIVIDEND_PAYMENT",
"segmentCriteria": {
"portfolioValue": {"gte": 100000},
"accountAgeDays": {"gte": 365},
"monthlyVolume": {"gte": 50000},
"kycStatus": "APPROVED",
"accountType": "individual"
},
"segmentSize": 15000,
"precomputed": true,
"lastUpdated": "2024-12-01T00:00:00Z",
"content": {
"subject": "π Exclusive: Premium Investor Dividend Report & Tax Optimization",
"templateVariables": {
"fullName": "{{fullName}}",
"dividendIncome": "{{dividendIncome}}",
"taxSavings": "{{taxSavings}}",
"optimizationUrl": "https://app.olaratech.com/tax/dividend-optimization",
"premiumBenefitsUrl": "https://app.olaratech.com/premium/benefits"
}
},
"channels": ["EMAIL", "SMS", "PUSH"],
"pushNotification": {
"enabled": true,
"priority": "NORMAL",
"title": "Premium Dividend Report",
"style": "INBOX",
"summaryText": "Your premium investor dividend report",
"inboxLines": [
"Dividend income: ${{dividendIncome}}",
"Tax optimization available",
"Exclusive premium benefits"
]
},
"smsContent": "Premium Investor Alert: Your dividend report is ready with tax optimization recommendations. View: {{shortUrl}}",
"performance": {
"estimatedProcessingTime": "15m",
"memoryUsage": "512MB",
"databaseQueries": 3,
"cacheHitRate": 0.95
}
}
Scaling & Infrastructure Patterns
Horizontal Scaling Configuration
# application-prod.yml - Production Scaling
spring:
rabbitmq:
listener:
simple:
concurrency: 20
max-concurrency: 50
prefetch: 10
resilience4j:
bulkhead:
instances:
notification-bulkhead:
max-concurrent-calls: 100
max-wait-duration: 5s
management:
metrics:
export:
prometheus:
enabled: true
endpoint:
metrics:
enabled: true
health:
show-details: always
Load Balancing Strategy
# Kubernetes deployment with HPA
apiVersion: apps/v1
kind: Deployment
metadata:
name: notification-service
spec:
replicas: 3
template:
spec:
containers:
- name: notification-service
resources:
requests:
memory: "2Gi"
cpu: "1000m"
limits:
memory: "4Gi"
cpu: "2000m"
env:
- name: SPRING_RABBITMQ_LISTENER_SIMPLE_CONCURRENCY
value: "15"
- name: JAVA_OPTS
value: "-Xmx3g -Xms1g -XX:+UseG1GC"
---
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: notification-service-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: notification-service
minReplicas: 3
maxReplicas: 20
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80
Performance Monitoring Queries
-- Real-time performance metrics
SELECT
date_trunc('minute', created_at) as minute,
count(*) as notifications_sent,
count(*) filter (where status = 'FAILED') as failures,
avg(extract(epoch from (processed_at - created_at))) as avg_processing_time
FROM notifications
WHERE created_at >= now() - interval '1 hour'
GROUP BY date_trunc('minute', created_at)
ORDER BY minute DESC;
-- Queue depth monitoring
SELECT
queue_name,
messages,
consumers,
messages / greatest(consumers, 1) as messages_per_consumer
FROM rabbitmq_queue
WHERE queue_name LIKE 'notification%';
-- Provider rate limit tracking
SELECT
provider,
notification_type,
count(*) as sent_last_hour,
max(rate_limit) as rate_limit,
count(*)::float / max(rate_limit) as utilization
FROM notifications
WHERE created_at >= now() - interval '1 hour'
AND status = 'SENT'
GROUP BY provider, notification_type;
Caching Strategies
Multi-Level Caching Configuration
# Redis caching configuration
spring:
cache:
type: redis
redis:
time-to-live: 3600000
cache:
user-profiles:
ttl: 1800 # 30 minutes
max-size: 10000
notification-templates:
ttl: 3600 # 1 hour
max-size: 500
targeting-segments:
ttl: 300 # 5 minutes
max-size: 1000
Cache-Aside Pattern Implementation
@Service
public class CachedNotificationService {
@Cacheable(value = "user-profiles", key = "#userId")
public UserProfile getUserProfile(String userId) {
return userRepository.findById(userId)
.orElseThrow(() -> new UserNotFoundException(userId));
}
@Cacheable(value = "notification-templates", key = "#type")
public NotificationTemplate getTemplate(NotificationType type) {
return templateRepository.findByType(type);
}
@CacheEvict(value = "user-profiles", key = "#userId")
public void invalidateUserCache(String userId) {
// Cache will be invalidated after profile updates
}
}
π Integration Patterns & Best Practices
This section covers integration strategies, event-driven workflows, and monitoring best practices.
Event-Driven Integration
RabbitMQ Consumer Configuration
@Configuration
public class NotificationEventConsumer {
@Bean
public MessageListenerContainer notificationContainer(
ConnectionFactory connectionFactory,
NotificationEventHandler handler) {
SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
container.setConnectionFactory(connectionFactory);
container.setQueueNames("notification.events");
container.setMessageListener(handler);
container.setConcurrency("10-20");
container.setPrefetchCount(5);
return container;
}
}
Event Publishing Patterns
@Service
public class NotificationEventPublisher {
private final RabbitTemplate rabbitTemplate;
public void publishOrderExecutedEvent(OrderExecutedEvent event) {
NotificationEvent notificationEvent = NotificationEvent.builder()
.eventType("ORDER_EXECUTED")
.userId(event.getUserId())
.notificationType(NotificationType.EMAIL_ORDER_EXECUTED)
.templateVariables(Map.of(
"symbol", event.getSymbol(),
"quantity", event.getQuantity(),
"price", event.getPrice(),
"orderId", event.getOrderId()
))
.pushNotification(PushNotification.builder()
.enabled(true)
.priority(Priority.HIGH)
.title("Order Executed")
.build())
.build();
rabbitTemplate.convertAndSend("notification.events", notificationEvent);
}
}
Monitoring & Observability
Prometheus Metrics Configuration
management:
endpoints:
web:
exposure:
include: health,info,metrics,prometheus
metrics:
export:
prometheus:
enabled: true
tags:
application: notification-service
environment: production
# Custom metrics
notification:
metrics:
enabled: true
batch:
size: 1000
queue:
monitoring: true
Key Metrics to Monitor
# Notification success rate
rate(notification_requests_total{status="success"}[5m])
/
rate(notification_requests_total[5m])
# Queue depth
rabbitmq_queue_messages{queue="notification.events"}
# Processing latency
histogram_quantile(0.95, rate(notification_processing_duration_bucket[5m]))
# Provider health
up{job="notification-service", provider="firebase"}
up{job="notification-service", provider="twilio"}
up{job="notification-service", provider="smtp"}
Alerting Rules
# Alert on high failure rate
- alert: NotificationHighFailureRate
expr: rate(notification_failures_total[5m]) / rate(notification_requests_total[5m]) > 0.05
for: 5m
labels:
severity: warning
annotations:
summary: "High notification failure rate detected"
# Alert on queue backlog
- alert: NotificationQueueBacklog
expr: rabbitmq_queue_messages{queue="notification.events"} > 10000
for: 2m
labels:
severity: warning
annotations:
summary: "Notification queue has high backlog"
# Alert on circuit breaker open
- alert: NotificationCircuitBreakerOpen
expr: resilience4j_circuitbreaker_state{circuitbreaker="notification-circuit", state="OPEN"} == 1
for: 1m
labels:
severity: critical
annotations:
summary: "Notification circuit breaker is open"
API Integration Patterns
REST Client Configuration
@Configuration
public class NotificationClientConfig {
@Bean
public WebClient notificationWebClient() {
return WebClient.builder()
.baseUrl("https://api.olaratech.com")
.defaultHeader("Authorization", "Bearer ${notification.api.key}")
.defaultHeader("X-Tenant-Id", "${tenant.id}")
.codecs(configurer -> configurer.defaultCodecs().maxInMemorySize(10 * 1024 * 1024))
.filter(ExchangeFilterFunction.ofRequestProcessor(request -> {
log.info("Sending notification request: {}", request.url());
return Mono.just(request);
}))
.build();
}
}
Retry & Timeout Configuration
@Service
public class ResilientNotificationClient {
private final WebClient webClient;
@Retry(name = "notification-api")
@CircuitBreaker(name = "notification-api")
public Mono<NotificationResponse> sendNotification(NotificationRequest request) {
return webClient.post()
.uri("/api/v1/notifications/targeted")
.bodyValue(request)
.retrieve()
.onStatus(HttpStatus::isError, response ->
response.bodyToMono(ErrorResponse.class)
.flatMap(error -> Mono.error(new NotificationException(error)))
)
.bodyToMono(NotificationResponse.class)
.timeout(Duration.ofSeconds(30));
}
}
Testing Strategies
Integration Test Example
@SpringBootTest
@Testcontainers
public class NotificationIntegrationTest {
@Container
static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:15");
@Container
static RabbitMQContainer rabbitMQ = new RabbitMQContainer("rabbitmq:3.12");
@Autowired
private NotificationService notificationService;
@Autowired
private RabbitTemplate rabbitTemplate;
@Test
void shouldSendNotificationViaQueue() {
// Given
NotificationRequest request = createTestNotification();
// When
notificationService.sendNotification(request);
// Then
await().atMost(10, SECONDS).untilAsserted(() -> {
Message message = rabbitTemplate.receive("notification.events", 1000);
assertThat(message).isNotNull();
NotificationEvent event = objectMapper.readValue(
message.getBody(), NotificationEvent.class);
assertThat(event.getNotificationType()).isEqualTo(request.getType());
});
}
}
Load Testing Configuration
@Configuration
public class LoadTestConfig {
@Bean
public CommandLineRunner loadTestRunner(NotificationService service) {
return args -> {
if (Arrays.asList(args).contains("--load-test")) {
IntStream.range(0, 10000).parallel().forEach(i -> {
NotificationRequest request = createBulkTestNotification(i);
try {
service.sendNotification(request);
Thread.sleep(10); // Rate limiting
} catch (Exception e) {
log.error("Load test error: {}", e.getMessage());
}
});
}
};
}
}
π Configuration Encryption
The service uses Jasypt for encrypting sensitive configuration properties (e.g., database passwords, API keys).
- Encryption Algorithm: PBEWithMD5AndDES
- Configuration:
JasyptConfigbean handles the decryption. - Usage: Encrypted values in
application.ymlare enclosed inENC(...).
Example:
spring:
datasource:
password: ENC(encrypted_password_here)
To generate encrypted values, you can use the Jasypt CLI or a similar tool with the configured encryption password.
π¦ Rate Limiting
The service implements robust rate limiting to prevent abuse and ensure stability.
- Implementation: Uses Resilience4j and a custom
RateLimitService. - Algorithm: Sliding Window.
- Configuration: Limits are configurable via
NotificationRateLimitConfigand can be adjusted per notification type or globally. - Storage: Rate limit counters are stored in Redis (distributed) or local cache (standalone).
Key Features: - Per-User Limits: Limits the number of notifications a single user can receive within a time window. - Per-Tenant Limits: Limits the total notifications for a tenant. - Dynamic Configuration: Limits can be adjusted at runtime without restarting the service.
π§ Contact
For support or inquiries, please contact devops@olaratech.com.