Skip to main content

Notification API for External Systems

The OmniCRM Notification API allows external systems and 3rd party integrations to send in-app notifications to users. This enables automated alerts, status updates, and important information to be delivered directly to users within the OmniCRM interface.

See also: Using the API <concepts_api> for authentication methods, Support Ticket System <support_tickets> for ticket-related notifications, Monitoring & Metrics <monitoring_metrics> for system monitoring.

Overview

The Notification API provides a flexible way for any system to send notifications to OmniCRM users. Notifications appear in the user's notification dropdown in the OmniCRM interface and can optionally link to specific pages or resources.

Key Features

  1. Flexible Integration — Any system can send notifications via API
  2. Multiple Notification Types — Support for various event types (provisioning, billing, tickets, custom)
  3. Rich Metadata — Include structured data with notifications
  4. Link Navigation — Notifications can link to specific pages
  5. API Key Authentication — Secure server-to-server integration
  6. Real-time Delivery — Notifications appear immediately in user interface
  7. Persistent Storage — Notifications are stored and retrievable

Common Use Cases

Provisioning Systems:

  • Notify users when service activation completes
  • Alert on provisioning failures
  • Update users on long-running provisioning tasks

Billing & Payment Systems:

  • Alert users when new invoices are generated
  • Confirm payment processing
  • Warn about upcoming service expirations

Monitoring & Alerting:

  • Send system health alerts to administrators
  • Notify on threshold breaches
  • Alert on critical events

Custom Integrations:

  • External workflow systems
  • Third-party service integrations
  • Automated reporting systems

Authentication

The Notification API supports two authentication methods:

API keys provide secure, long-lived authentication for server-to-server integrations. This is the recommended method for external systems.

Configure API Key:

Add your API key to crm_config.yaml:

api_keys:
your-secure-api-key-minimum-32-characters:
roles:
- admin
description: "Provisioning notification system"

Use API Key:

Include the API key in the X-API-KEY header:

curl -X POST "https://yourcrm.com/crm/notification/send" \
-H "X-API-KEY: your-secure-api-key-minimum-32-characters" \
-H "Content-Type: application/json" \
-d '{
"user_id": 123,
"type": "provision_complete",
"title": "Service Activated",
"message": "Your mobile service has been successfully activated",
"link": "/services/167"
}'

Bearer Token Authentication

For interactive systems or user-initiated notifications, use Bearer token authentication.

See Using the API <concepts_api> for details on obtaining Bearer tokens.

API Endpoint

Send Notification

Endpoint: POST /crm/notification/send

Authentication: API Key (X-API-KEY) or Bearer Token

Description: Send a notification to a specific user

Request Body

{
"user_id": 123,
"type": "provision_complete",
"title": "Service Activated",
"message": "Your mobile service has been successfully activated",
"link": "/services/167",
"metadata": {
"service_id": 167,
"provision_job_id": "prov-2026-00042",
"duration_seconds": 45
},
"related_ticket_id": 42,
"related_user_id": 5
}

Request Parameters

FieldTypeRequiredDescription
user_idintegerYesID of the user to notify
typestringYesNotification type (see types below)
titlestringYesNotification title (max 255 chars)
messagestringNoDetailed notification message
linkstringNoURL/path to navigate when clicked
metadataobjectNoAdditional structured data (JSON)
related_ticket_idintegerNoAssociated ticket ID
related_user_idintegerNoRelated user ID (e.g., who caused event)

Notification Types

TypeDescriptionCommon Use Case
provision_completeProvisioning completed successfullyAnsible playbook finished
provision_failedProvisioning failedService activation error
ticket_mentionUser @mentioned in ticketCollaboration alert
ticket_assignedTicket assigned to userSupport workflow
ticket_updatedTicket was updatedTicket subscriber notification
customer_replyCustomer replied to ticketSupport alert
system_alertSystem-wide alertCritical system event
billing_invoiceNew invoice generatedBilling system integration
billing_paymentPayment processedPayment gateway webhook
service_expiringService expiring soonAutomated monitoring
customCustom notification typeAny other purpose

Success Response

Status: 201 Created

{
"result": "Success",
"message": "Notification sent successfully",
"notification": {
"notification_id": 1234,
"user_id": 123,
"type": "provision_complete",
"title": "Service Activated",
"message": "Your mobile service has been successfully activated",
"link": "/services/167",
"metadata": {
"service_id": 167,
"provision_job_id": "prov-2026-00042",
"duration_seconds": 45
},
"is_read": false,
"created_at": "2026-01-11T14:30:00Z"
}
}

Error Responses

Missing Required Field (400 Bad Request):

{
"result": "Failed",
"reason": "user_id is required"
}

User Not Found (404 Not Found):

{
"result": "Failed",
"reason": "User 999 not found"
}

Authentication Failed (401 Unauthorized):

{
"message": "Invalid API key"
}

Code Examples

Python Example

import requests

# Configuration
CRM_URL = 'https://yourcrm.com'
API_KEY = 'your-secure-api-key-minimum-32-characters'

def send_notification(user_id, notification_type, title, message=None, link=None, metadata=None):
"""Send a notification to a user via OmniCRM API"""

headers = {
"Content-Type": "application/json",
"X-API-KEY": API_KEY
}

payload = {
"user_id": user_id,
"type": notification_type,
"title": title
}

# Add optional fields
if message:
payload["message"] = message
if link:
payload["link"] = link
if metadata:
payload["metadata"] = metadata

response = requests.post(
f"{CRM_URL}/crm/notification/send",
headers=headers,
json=payload
)

if response.status_code == 201:
print(f"✓ Notification sent successfully: {response.json()}")
return response.json()
else:
print(f"✗ Failed to send notification: {response.text}")
response.raise_for_status()

# Example usage
if __name__ == "__main__":
# Notify user of provisioning completion
send_notification(
user_id=123,
notification_type="provision_complete",
title="Mobile Service Activated",
message="Service ID 167 has been successfully provisioned and activated",
link="/services/167",
metadata={
"service_id": 167,
"provision_job_id": "prov-2026-00042",
"duration_seconds": 45,
"playbook": "mobile_service_activation"
}
)

Bash/cURL Example

#!/bin/bash

# Configuration
CRM_URL="https://yourcrm.com"
API_KEY="your-secure-api-key-minimum-32-characters"

# Send notification
curl -X POST "${CRM_URL}/crm/notification/send" \
-H "X-API-KEY: ${API_KEY}" \
-H "Content-Type: application/json" \
-d '{
"user_id": 123,
"type": "provision_complete",
"title": "Service Activated",
"message": "Your mobile service has been successfully activated",
"link": "/services/167",
"metadata": {
"service_id": 167,
"provision_job_id": "prov-2026-00042",
"duration_seconds": 45
}
}'

Node.js Example

const axios = require('axios');

const CRM_URL = 'https://yourcrm.com';
const API_KEY = 'your-secure-api-key-minimum-32-characters';

async function sendNotification(userId, type, title, options = {}) {
try {
const response = await axios.post(
`${CRM_URL}/crm/notification/send`,
{
user_id: userId,
type: type,
title: title,
message: options.message,
link: options.link,
metadata: options.metadata,
related_ticket_id: options.relatedTicketId,
related_user_id: options.relatedUserId
},
{
headers: {
'X-API-KEY': API_KEY,
'Content-Type': 'application/json'
}
}
);

console.log('✓ Notification sent:', response.data);
return response.data;
} catch (error) {
console.error('✗ Failed to send notification:', error.response?.data || error.message);
throw error;
}
}

// Example usage
sendNotification(
123,
'provision_complete',
'Service Activated',
{
message: 'Your mobile service has been successfully activated',
link: '/services/167',
metadata: {
service_id: 167,
provision_job_id: 'prov-2026-00042',
duration_seconds: 45
}
}
);

Integration Scenarios

Ansible Provisioning Playbook

Notify users when Ansible playbooks complete:

# At the end of your Ansible callback plugin or post-playbook script
import requests

def notify_provisioning_complete(service_id, user_id, success=True):
"""Notify user of provisioning result"""

notification_type = "provision_complete" if success else "provision_failed"
title = "Service Activated" if success else "Service Activation Failed"
message = f"Service {service_id} provisioning {'completed successfully' if success else 'encountered an error'}"

requests.post(
"https://yourcrm.com/crm/notification/send",
headers={"X-API-KEY": "your-api-key"},
json={
"user_id": user_id,
"type": notification_type,
"title": title,
"message": message,
"link": f"/services/{service_id}",
"metadata": {
"service_id": service_id,
"playbook": "mobile_service_activation",
"success": success
}
}
)

Billing System Integration

Send invoice notifications from billing system:

def notify_invoice_generated(customer_id, invoice_id, amount, due_date):
"""Notify customer contact of new invoice"""

# Find user associated with customer
user_id = get_customer_primary_contact_user_id(customer_id)

if user_id:
requests.post(
"https://yourcrm.com/crm/notification/send",
headers={"X-API-KEY": "your-billing-api-key"},
json={
"user_id": user_id,
"type": "billing_invoice",
"title": f"New Invoice #{invoice_id}",
"message": f"Invoice for ${amount} is now available. Due date: {due_date}",
"link": f"/invoices/{invoice_id}",
"metadata": {
"invoice_id": invoice_id,
"amount": amount,
"due_date": due_date,
"customer_id": customer_id
}
}
)

Monitoring System Integration

Send alerts from monitoring systems:

def send_monitoring_alert(admin_user_ids, alert_title, alert_message, severity="warning"):
"""Send system alert to administrators"""

for user_id in admin_user_ids:
requests.post(
"https://yourcrm.com/crm/notification/send",
headers={"X-API-KEY": "your-monitoring-api-key"},
json={
"user_id": user_id,
"type": "system_alert",
"title": alert_title,
"message": alert_message,
"metadata": {
"severity": severity,
"alert_time": datetime.now().isoformat(),
"source": "prometheus_alertmanager"
}
}
)

# Example: Disk space alert
send_monitoring_alert(
admin_user_ids=[1, 2, 3],
alert_title="⚠️ Disk Space Warning",
alert_message="Database server disk usage has exceeded 85%",
severity="warning"
)

Payment Gateway Webhook

Notify users when payments are processed:

from flask import Flask, request

app = Flask(__name__)

@app.route('/webhook/payment', methods=['POST'])
def payment_webhook():
"""Handle payment gateway webhook"""

payment_data = request.json

if payment_data['status'] == 'succeeded':
# Notify user of successful payment
requests.post(
"https://yourcrm.com/crm/notification/send",
headers={"X-API-KEY": "your-payment-webhook-api-key"},
json={
"user_id": payment_data['user_id'],
"type": "billing_payment",
"title": "Payment Received",
"message": f"Payment of ${payment_data['amount']} has been processed successfully",
"link": f"/payments/{payment_data['payment_id']}",
"metadata": {
"payment_id": payment_data['payment_id'],
"amount": payment_data['amount'],
"payment_method": payment_data['payment_method']
}
}
)

return {"status": "ok"}

Service Expiration Monitor

Automated script to notify users of expiring services:

import datetime
from sqlalchemy import create_engine, text

def check_expiring_services():
"""Check for services expiring in next 7 days and notify users"""

engine = create_engine("postgresql://...")

# Query services expiring soon
query = text("""
SELECT s.service_id, s.end_date, u.id as user_id, s.service_name
FROM services s
JOIN customer_contacts cc ON s.customer_id = cc.customer_id
JOIN users u ON cc.contact_id = u.contact_id
WHERE s.end_date BETWEEN CURRENT_DATE AND CURRENT_DATE + INTERVAL '7 days'
AND s.deleted = false
""")

with engine.connect() as conn:
results = conn.execute(query)

for row in results:
days_until_expiry = (row.end_date - datetime.date.today()).days

requests.post(
"https://yourcrm.com/crm/notification/send",
headers={"X-API-KEY": "your-automation-api-key"},
json={
"user_id": row.user_id,
"type": "service_expiring",
"title": f"Service Expiring in {days_until_expiry} Days",
"message": f"Your {row.service_name} will expire on {row.end_date}",
"link": f"/services/{row.service_id}",
"metadata": {
"service_id": row.service_id,
"days_remaining": days_until_expiry,
"expiry_date": str(row.end_date)
}
}
)

# Run daily via cron
if __name__ == "__main__":
check_expiring_services()

Best Practices

API Key Security

  1. Generate Strong Keys — Use cryptographically secure random generators:

    openssl rand -base64 48
  2. Separate Keys per System — Use different API keys for different external systems

  3. Document Key Purpose — Always include a description in crm_config.yaml

  4. Rotate Keys Regularly — Change API keys periodically (e.g., quarterly)

  5. Never Commit Keys — Keep API keys out of version control

  6. Minimal Permissions — Only grant necessary roles to each API key

Notification Design

  1. Clear Titles — Make titles descriptive and actionable (e.g., "Service Activated" not "Update")

  2. Concise Messages — Keep messages brief but informative

  3. Include Links — Always provide a link for users to get more details

  4. Use Metadata — Store structured data for future reference and debugging

  5. Choose Correct Type — Use appropriate notification types for categorization

  6. Test Notifications — Test with real users before deploying to production

Error Handling

  1. Handle Failures Gracefully — Don't let notification failures break main workflows

  2. Log All Attempts — Log notification attempts for debugging

  3. Retry on Transient Errors — Implement retry logic for network issues

  4. Validate User IDs — Verify user exists before sending

  5. Check API Responses — Always check response status codes

Performance

  1. Batch When Possible — For multiple users, consider sending in parallel

  2. Async Processing — Send notifications asynchronously to avoid blocking

  3. Rate Limiting — Implement rate limiting to prevent API abuse

  4. Connection Pooling — Reuse HTTP connections for better performance

Testing

Test API Key Setup

Before deploying, verify your API key works:

# Test authentication
curl -X POST "https://yourcrm.com/crm/notification/send" \
-H "X-API-KEY: your-api-key" \
-H "Content-Type: application/json" \
-d '{
"user_id": 1,
"type": "custom",
"title": "Test Notification",
"message": "This is a test notification to verify API key authentication"
}'

Expected response: 201 Created with notification details

Test in Development

Use a test user ID to verify notifications appear:

# Send test notification
response = send_notification(
user_id=1, # Your test user
notification_type="custom",
title="Integration Test",
message="Testing notification API integration"
)

print(f"Notification ID: {response['notification']['notification_id']}")

Then log in to OmniCRM as that user and verify the notification appears in the notification dropdown.

Troubleshooting

Issue: 401 Unauthorized

  • Cause: Invalid or missing API key
  • Solution: Verify API key in crm_config.yaml and request header
  • Check: Ensure API key is at least 32 characters

Issue: 404 User Not Found

  • Cause: Invalid user_id
  • Solution: Verify user exists in database
  • Check: Query users table: SELECT id FROM users WHERE id = ?

Issue: 400 Bad Request - "user_id is required"

  • Cause: Missing required field in request
  • Solution: Include all required fields: user_id, type, title
  • Check: Validate JSON payload structure

Issue: Notification sent but not appearing

  • Cause: User not logged in or browser cache
  • Solution: Refresh page or clear cache
  • Check: Query database: SELECT * FROM notifications WHERE user_id = ? ORDER BY created_at DESC

Issue: 500 Internal Server Error

  • Cause: Server-side error
  • Solution: Check CRM server logs for details
  • Check: Review /var/log/omnicrm/api.log for errors

API Reference Summary

Endpoints

MethodEndpointDescriptionAuth
POST/crm/notification/sendSend notification to userAPI Key or Bearer
GET/crm/notification/Get current user's notificationsBearer
GET/crm/notification/unread-countGet unread countBearer
POST/crm/notification/{id}/mark-readMark notification as readBearer
POST/crm/notification/mark-all-readMark all as readBearer
DELETE/crm/notification/{id}Delete notificationBearer

Required Permissions

  • Send Notification: Requires valid API key or admin role
  • View Notifications: User can only view their own notifications
  • Manage Notifications: User can only manage their own notifications
  • Using the API <concepts_api> — Complete API authentication guide
  • Support Ticket System <support_tickets> — Ticket notifications and @mentions
  • Provisioning System <concepts_provisioning> — Ansible integration
  • Monitoring & Metrics <monitoring_metrics> — System monitoring and alerting
  • RBAC <rbac> — Roles and permissions