Creating and Sending Notifications
This guide explains how to create and send notifications to users using the Agglestone Messaging Service.
Creating a Notification
Notifications are messages stored in a user’s personal inbox. They can be retrieved later, marked as read, and optionally delivered via email.
Creating a New Notification
To create a new notification, send a POST request to the notifications endpoint:
Endpoint: POST /tenant/{tenantId}/v1/Notifications
⚠️ Authorization Required: This endpoint requires Admin privileges or API Key authentication.
- Admin users: Users with the Admin group in their JWT token can create notifications
- API Key: Backend services can use API Key authentication for backend-to-backend communication
- ⚠️ Security Note: API Keys should NEVER be exposed in frontend code. They should only be used in secure backend services that cannot be accessed by end users.
Request Body:
{
"userId": "user-id-123",
"type": "SystemAnnouncement",
"subject": "System Maintenance Scheduled",
"message": "We will be performing scheduled maintenance on Saturday at 2 AM.",
"htmlContent": "<p>We will be performing <strong>scheduled maintenance</strong> on Saturday at 2 AM.</p>",
"summary": "Maintenance scheduled for Saturday",
"priority": "High",
"email": "user@example.com",
"metadata": {
"actionUrl": "/maintenance",
"maintenanceDate": "2024-01-20T02:00:00Z"
}
}
Request Fields:
userId(required): The user ID to send the notification to. This field is required and must be specified in the request.type(optional): The notification type (e.g.,UserInvite,RegistrationWelcome,SystemAnnouncement,PasswordReset,AccountVerification)subject(required): The notification subject/titlemessage(required): The notification message content (plain text)htmlContent(optional): HTML formatted content for rich notificationssummary(optional): A brief summary of the notificationpriority(optional): Priority level (Low,Normal,High,Urgent). Defaults toNormal.scheduledFor(optional): ISO 8601 date/time to schedule the notification for future deliveryemail(optional): Email address to send the notification to. If provided, the notification will also be delivered via email.metadata(optional): Custom key-value pairs for additional data your application can use
Response:
{
"id": "notification-id-456",
"tenantId": "tenant-id-123",
"userId": "user-id-123",
"type": "SystemAnnouncement",
"subject": "System Maintenance Scheduled",
"message": "We will be performing scheduled maintenance on Saturday at 2 AM.",
"htmlContent": "<p>We will be performing <strong>scheduled maintenance</strong> on Saturday at 2 AM.</p>",
"summary": "Maintenance scheduled for Saturday",
"priority": "High",
"status": "Pending",
"createdAt": "2024-01-15T10:30:00Z",
"scheduledFor": null,
"sentAt": null,
"readAt": null,
"metadata": {
"actionUrl": "/maintenance",
"maintenanceDate": "2024-01-20T02:00:00Z"
}
}
The response includes:
id: The unique notification IDstatus: The notification status (Pending,Scheduled,Sent,Read,Failed,Cancelled,Grouped)createdAt: When the notification was createdscheduledFor: When the notification is scheduled for (if scheduled)sentAt: When the notification was sent (if sent)readAt: When the notification was read (if read)
Example: Creating a Notification
Note: The examples below show API Key authentication for backend services. ⚠️ Never expose API Keys in frontend code – they should only be used in secure backend services. Alternatively, Admin users with the Admin group in their JWT token can use JWT authentication by replacing the X-API-Key header with Authorization: Bearer {jwt-token}.
// Backend service example - API Key authentication for server-to-server communication
// This code, using API Key, should run on your backend server, never in frontend/browser code
async function createNotification(
userId: string,
subject: string,
message: string,
options?: {
type?: string;
priority?: 'Low' | 'Normal' | 'High' | 'Urgent';
htmlContent?: string;
email?: string;
metadata?: Record<string, any>;
}
) {
// API Key should be stored securely in backend environment variables
// Never expose API Keys in frontend code or client-side JavaScript
const apiKey = process.env.MESSAGING_SERVICE_API_KEY;
const response = await fetch(
`${apiBaseUrl}/tenant/${tenantId}/v1/Notifications`,
{
method: 'POST',
headers: {
'X-API-Key': apiKey, // API Key for backend-to-backend communication
// Alternative for Admin users: 'Authorization': `Bearer ${jwtToken}`
'Content-Type': 'application/json'
},
body: JSON.stringify({
userId: userId,
subject: subject,
message: message,
type: options?.type,
priority: options?.priority || 'Normal',
htmlContent: options?.htmlContent,
email: options?.email,
metadata: options?.metadata
})
}
);
if (!response.ok) {
throw new Error(`Failed to create notification: ${response.statusText}`);
}
return await response.json();
}
// Create a system announcement
const notification = await createNotification(
'user-id-123',
'System Maintenance Scheduled',
'We will be performing scheduled maintenance on Saturday at 2 AM.',
{
type: 'SystemAnnouncement',
priority: 'High',
email: 'user@example.com',
metadata: {
actionUrl: '/maintenance',
maintenanceDate: '2024-01-20T02:00:00Z'
}
}
);
using System.Net.Http;
using System.Text;
using System.Text.Json;
async Task<Notification> CreateNotificationAsync(
string userId,
string subject,
string message,
NotificationOptions? options = null)
{
var client = new HttpClient();
client.DefaultRequestHeaders.Add("X-API-Key", apiKey); // API Key for backend-to-backend communication
var requestBody = new
{
userId = userId,
subject = subject,
message = message,
type = options?.Type,
priority = options?.Priority ?? "Normal",
htmlContent = options?.HtmlContent,
email = options?.Email,
metadata = options?.Metadata
};
var json = JsonSerializer.Serialize(requestBody);
var content = new StringContent(json, Encoding.UTF8, "application/json");
var response = await client.PostAsync(
$"{apiBaseUrl}/tenant/{tenantId}/v1/Notifications",
content);
response.EnsureSuccessStatusCode();
var responseJson = await response.Content.ReadAsStringAsync();
return JsonSerializer.Deserialize<Notification>(responseJson);
}
// Create a system announcement
var notification = await CreateNotificationAsync(
"user-id-123",
"System Maintenance Scheduled",
"We will be performing scheduled maintenance on Saturday at 2 AM.",
new NotificationOptions
{
Type = "SystemAnnouncement",
Priority = "High",
Email = "user@example.com",
Metadata = new Dictionary<string, object>
{
{ "actionUrl", "/maintenance" },
{ "maintenanceDate", "2024-01-20T02:00:00Z" }
}
});
import requests
import json
def create_notification(user_id, subject, message, options=None):
url = f"{api_base_url}/tenant/{tenant_id}/v1/Notifications"
headers = {
"X-API-Key": api_key, # API Key for backend-to-backend communication
"Content-Type": "application/json"
}
payload = {
"userId": user_id,
"subject": subject,
"message": message,
"type": options.get("type") if options else None,
"priority": options.get("priority", "Normal") if options else "Normal",
"htmlContent": options.get("htmlContent") if options else None,
"email": options.get("email") if options else None,
"metadata": options.get("metadata") if options else None
}
response = requests.post(url, headers=headers, json=payload)
response.raise_for_status()
return response.json()
# Create a system announcement
notification = create_notification(
"user-id-123",
"System Maintenance Scheduled",
"We will be performing scheduled maintenance on Saturday at 2 AM.",
{
"type": "SystemAnnouncement",
"priority": "High",
"email": "user@example.com",
"metadata": {
"actionUrl": "/maintenance",
"maintenanceDate": "2024-01-20T02:00:00Z"
}
}
)
Notification Types
Notifications support different types to help categorize and handle them appropriately:
UserInvite: Invitation for a user to join or access somethingRegistrationWelcome: Welcome message for new user registrationsInactivityReminder: Reminder for inactive usersSystemAnnouncement: General system announcementsPasswordReset: Password reset notificationsAccountVerification: Account verification messages
Choose the type that best matches your notification’s purpose. This helps users understand the nature of each notification and allows your application to handle different notification types appropriately.
Priority Levels
Set priority levels to indicate the importance of notifications:
Low: Low priority notificationsNormal: Normal priority (default)High: High priority notificationsUrgent: Urgent notifications requiring immediate attention
Priority levels help users prioritize which notifications to read first and help your application surface the most important messages.
Email Delivery
Notifications can optionally be delivered via email in addition to being stored in the inbox. To send a notification via email, include the email field in your request:
// Create a notification with email delivery
const notification = await createNotification(
'user-id-123',
'Password Reset Requested',
'You requested a password reset. Click the link to reset your password.',
{
type: 'PasswordReset',
priority: 'High',
email: 'user@example.com' // This will also send an email
}
);
// Create a notification with email delivery
var notification = await CreateNotificationAsync(
"user-id-123",
"Password Reset Requested",
"You requested a password reset. Click the link to reset your password.",
new NotificationOptions
{
Type = "PasswordReset",
Priority = "High",
Email = "user@example.com" // This will also send an email
});
# Create a notification with email delivery
notification = create_notification(
"user-id-123",
"Password Reset Requested",
"You requested a password reset. Click the link to reset your password.",
{
"type": "PasswordReset",
"priority": "High",
"email": "user@example.com" # This will also send an email
}
)
When the email field is provided, the notification will be:
- Stored in the user’s inbox (as always)
- Sent via email to the specified address
This ensures users never miss important notifications even when they’re not actively using your application.
Scheduled Notifications
You can schedule notifications to be sent at a future time by providing the scheduledFor field:
// Schedule a notification for future delivery
const scheduledDate = new Date('2024-01-20T02:00:00Z');
const notification = await createNotification(
'user-id-123',
'Reminder: Meeting Tomorrow',
'Don't forget about the team meeting tomorrow at 10 AM.',
{
scheduledFor: scheduledDate.toISOString()
}
);
// Schedule a notification for future delivery
var scheduledDate = DateTime.Parse("2024-01-20T02:00:00Z");
var notification = await CreateNotificationAsync(
"user-id-123",
"Reminder: Meeting Tomorrow",
"Don't forget about the team meeting tomorrow at 10 AM.",
new NotificationOptions
{
ScheduledFor = scheduledDate.ToString("O")
});
# Schedule a notification for future delivery
from datetime import datetime
scheduled_date = datetime.fromisoformat("2024-01-20T02:00:00Z")
notification = create_notification(
"user-id-123",
"Reminder: Meeting Tomorrow",
"Don't forget about the team meeting tomorrow at 10 AM.",
{
"scheduledFor": scheduled_date.isoformat()
}
)
The notification will be created immediately but will remain in a Scheduled status until the specified time arrives, at which point it will be processed and delivered.
Rich Content
Notifications support both plain text and HTML content:
// Create a notification with HTML content
const notification = await createNotification(
'user-id-123',
'Welcome to Our Platform',
'Welcome! We're excited to have you here.',
{
htmlContent: '<h2>Welcome!</h2><p>We're <strong>excited</strong> to have you here.</p><a href="/dashboard">Go to Dashboard</a>',
type: 'RegistrationWelcome'
}
);
// Create a notification with HTML content
var notification = await CreateNotificationAsync(
"user-id-123",
"Welcome to Our Platform",
"Welcome! We're excited to have you here.",
new NotificationOptions
{
HtmlContent = "<h2>Welcome!</h2><p>We're <strong>excited</strong> to have you here.</p><a href="/dashboard">Go to Dashboard</a>",
Type = "RegistrationWelcome"
});
# Create a notification with HTML content
notification = create_notification(
"user-id-123",
"Welcome to Our Platform",
"Welcome! We're excited to have you here.",
{
"htmlContent": "<h2>Welcome!</h2><p>We're <strong>excited</strong> to have you here.</p><a href="/dashboard">Go to Dashboard</a>",
"type": "RegistrationWelcome"
}
)
Use message for plain text content and htmlContent for rich, formatted content with links, formatting, and structured elements.
Metadata
Attach custom metadata to notifications for additional context:
// Create a notification with metadata
const notification = await createNotification(
'user-id-123',
'New Comment on Your Post',
'Someone commented on your post.',
{
metadata: {
actionUrl: '/posts/123',
postId: 'post-123',
commentId: 'comment-456',
commenterName: 'John Doe'
}
}
);
// Create a notification with metadata
var notification = await CreateNotificationAsync(
"user-id-123",
"New Comment on Your Post",
"Someone commented on your post.",
new NotificationOptions
{
Metadata = new Dictionary<string, object>
{
{ "actionUrl", "/posts/123" },
{ "postId", "post-123" },
{ "commentId", "comment-456" },
{ "commenterName", "John Doe" }
}
});
# Create a notification with metadata
notification = create_notification(
"user-id-123",
"New Comment on Your Post",
"Someone commented on your post.",
{
"metadata": {
"actionUrl": "/posts/123",
"postId": "post-123",
"commentId": "comment-456",
"commenterName": "John Doe"
}
}
)
Your application can use this metadata to handle notifications appropriately, such as navigating to specific pages or displaying additional context.
Error Handling
Common errors you may encounter:
- 401 Unauthorized:
- Your access token is missing, invalid, or expired. Refresh your token and retry.
- You don’t have Admin privileges (for JWT authentication) or your API Key is invalid (for API Key authentication).
- This endpoint requires Admin privileges or API Key authentication.
- 403 Forbidden: The tenant ID doesn’t match your authentication.
- 400 Bad Request: The request body is invalid (e.g., missing required fields like
userId,subject, ormessage).
Always check the response status and handle errors appropriately in your application.
—
Ready to retrieve notifications? Check out Retrieving Notifications.