Skip to content

πŸš€ 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_SENT events 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=false for 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-Id is 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-Id header is automatically extracted and used for tenant isolation
  • X-User-Id header 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 GENERAL category.
  • 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

  1. On Create/Update: If encrypted: true, the value is encrypted using AES-GCM before being stored in the database
  2. On Retrieval: If encrypted: true, the value is automatically decrypted when fetched via GET endpoints
  3. Storage: Encrypted values are stored as Base64-encoded ciphertext with an initialization vector (IV)
  4. 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: true or false values (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:

  1. User-Level Settings (if available and userId is provided)
  2. Tenant-Level Settings (if available)
  3. 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 > amount
  • LESS_THAN: Balance < amount
  • EQUAL_TO: Balance = amount
  • GREATER_THAN_OR_EQUAL_TO: Balance >= amount
  • LESS_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 welcome
  • EMAIL_PASSWORD_RESET - Password reset instructions
  • EMAIL_ONBOARDING_WELCOME - Welcome email
  • EMAIL_ONBOARDING_EMAIL_VERIFICATION - Email verification
  • EMAIL_ONBOARDING_REFERRAL_INVITATION - Referral invitation
  • EMAIL_ONBOARDING_COMPLETE_PROFILE_REMINDER - Profile completion reminder
  • EMAIL_ONBOARDING_ACCOUNT_CREATED - Account creation confirmation
  • EMAIL_SECURITY_PASSWORD_RESET - Security password reset
  • EMAIL_SECURITY_PASSWORD_CHANGED - Password change confirmation
  • EMAIL_SECURITY_NEW_DEVICE_LOGIN - New device login alert
  • EMAIL_SECURITY_ACCOUNT_LOCKED - Account locked notification
  • EMAIL_SECURITY_ACCOUNT_REACTIVATED - Account reactivation

Funding & Payments (8 types)

  • EMAIL_FUNDING_DEPOSIT_SUCCESSFUL - Deposit success confirmation
  • EMAIL_FUNDING_DEPOSIT_FAILED - Deposit failure notification
  • EMAIL_FUNDING_DEPOSIT_INITIATED - Deposit initiation
  • EMAIL_FUNDING_WITHDRAWAL_SUCCESSFUL - Withdrawal success
  • EMAIL_FUNDING_WITHDRAWAL_FAILED - Withdrawal failure
  • EMAIL_FUNDING_WITHDRAWAL_REQUEST - Withdrawal request received
  • EMAIL_FUNDING_CARD_ADDED - Card addition confirmation
  • EMAIL_FUNDING_CARD_REMOVED - Card removal confirmation

Trading & Orders (10 types)

  • EMAIL_ORDER_CONFIRMATION - Order confirmation
  • EMAIL_ORDER_EXECUTED - Order execution notification
  • EMAIL_ORDER_CANCELLED - Order cancellation
  • EMAIL_ORDER_PLACED - Order placement confirmation
  • EMAIL_ORDER_EXPIRED - Order expiration
  • EMAIL_ORDER_STOP_LOSS_TRIGGERED - Stop loss execution
  • EMAIL_ORDER_CORPORATE_ACTION - Corporate action notification
  • EMAIL_PAYMENT_CONFIRMATION - Payment confirmation
  • EMAIL_ORDER_CONFIRMATION_TEMPLATE - Order confirmation (legacy)
  • EMAIL_DEVICE_REGISTRATION - Device registration

Portfolio & Risk Management (6 types)

  • EMAIL_PORTFOLIO_STATEMENT - Portfolio statement
  • EMAIL_PORTFOLIO_TRADE_SUMMARY - Trade summary
  • EMAIL_PORTFOLIO_DIVIDEND_PAYMENT - Dividend payment
  • EMAIL_PORTFOLIO_MARGIN_CALL_ALERT - Margin call alert
  • EMAIL_PORTFOLIO_LOW_BALANCE_ALERT - Low balance alert
  • EMAIL_PORTFOLIO_POSITION_LIQUIDATION - Position liquidation

KYC & Compliance (5 types)

  • EMAIL_KYC_APPROVED - KYC approval
  • EMAIL_KYC_REJECTED - KYC rejection
  • EMAIL_KYC_EDD - Enhanced due diligence required
  • EMAIL_KYC_EXPIRY_REMINDER - KYC expiry reminder
  • EMAIL_KYC_SUBMISSION_RECEIVED - KYC submission received

Corporate & Business (4 types)

  • EMAIL_CORPORATE_ACCOUNT_APPLICATION - Corporate account application
  • EMAIL_CORPORATE_ACCOUNT_APPROVED - Corporate account approval
  • EMAIL_CORPORATE_ACCOUNT_REJECTED - Corporate account rejection
  • EMAIL_CORPORATE_FEE_SCHEDULE_CHANGE - Fee schedule change
  • EMAIL_CORPORATE_REPORTS - Corporate reports

Security & Alerts (6 types)

  • EMAIL_SECURITY_2FA_CHANGED - 2FA settings changed
  • EMAIL_SECURITY_SUSPICIOUS_ACTIVITY - Suspicious activity detected
  • EMAIL_SECURITY_ACCOUNT_LOCKED - Account locked
  • EMAIL_SECURITY_ACCOUNT_REACTIVATED - Account reactivated
  • EMAIL_SECURITY_NEW_DEVICE_LOGIN - New device login
  • EMAIL_SECURITY_PASSWORD_CHANGED - Password changed

Support & Communication (5 types)

  • EMAIL_SUPPORT_TICKET_CREATED - Support ticket created
  • EMAIL_SUPPORT_TICKET_UPDATED - Support ticket updated
  • EMAIL_SUPPORT_TICKET_RESOLVED - Support ticket resolved
  • EMAIL_SUPPORT_POLICY_UPDATE - Policy update
  • EMAIL_SUPPORT_FEEDBACK_REQUEST - Feedback request

Miscellaneous (4 types)

  • EMAIL_MISC_REFERRAL_BONUS - Referral bonus earned
  • EMAIL_MISC_FEATURE_ANNOUNCEMENT - Feature announcement
  • EMAIL_MISC_BIRTHDAY_GREETING - Birthday greeting
  • EMAIL_MISC_ACCOUNT_CLOSURE - Account closure
  • EMAIL_MISC_TAX_DOCUMENT_READY - Tax document ready

SMS Types (2 types)

  • SMS_OTP - One-time password
  • SMS_ORDER_CONFIRMATION - Order confirmation SMS

Slack Types (4 types)

  • SLACK_MESSAGE - Regular Slack messages
  • SLACK_ATTACHMENT - Messages with file attachments
  • SLACK_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: JasyptConfig bean handles the decryption.
  • Usage: Encrypted values in application.yml are enclosed in ENC(...).

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 NotificationRateLimitConfig and 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.