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
- Flexible Integration — Any system can send notifications via API
- Multiple Notification Types — Support for various event types (provisioning, billing, tickets, custom)
- Rich Metadata — Include structured data with notifications
- Link Navigation — Notifications can link to specific pages
- API Key Authentication — Secure server-to-server integration
- Real-time Delivery — Notifications appear immediately in user interface
- 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 Key Authentication (Recommended for External Systems)
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
| Field | Type | Required | Description |
|---|---|---|---|
user_id | integer | Yes | ID of the user to notify |
type | string | Yes | Notification type (see types below) |
title | string | Yes | Notification title (max 255 chars) |
message | string | No | Detailed notification message |
link | string | No | URL/path to navigate when clicked |
metadata | object | No | Additional structured data (JSON) |
related_ticket_id | integer | No | Associated ticket ID |
related_user_id | integer | No | Related user ID (e.g., who caused event) |
Notification Types
| Type | Description | Common Use Case |
|---|---|---|
provision_complete | Provisioning completed successfully | Ansible playbook finished |
provision_failed | Provisioning failed | Service activation error |
ticket_mention | User @mentioned in ticket | Collaboration alert |
ticket_assigned | Ticket assigned to user | Support workflow |
ticket_updated | Ticket was updated | Ticket subscriber notification |
customer_reply | Customer replied to ticket | Support alert |
system_alert | System-wide alert | Critical system event |
billing_invoice | New invoice generated | Billing system integration |
billing_payment | Payment processed | Payment gateway webhook |
service_expiring | Service expiring soon | Automated monitoring |
custom | Custom notification type | Any 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
-
Generate Strong Keys — Use cryptographically secure random generators:
openssl rand -base64 48 -
Separate Keys per System — Use different API keys for different external systems
-
Document Key Purpose — Always include a description in
crm_config.yaml -
Rotate Keys Regularly — Change API keys periodically (e.g., quarterly)
-
Never Commit Keys — Keep API keys out of version control
-
Minimal Permissions — Only grant necessary roles to each API key
Notification Design
-
Clear Titles — Make titles descriptive and actionable (e.g., "Service Activated" not "Update")
-
Concise Messages — Keep messages brief but informative
-
Include Links — Always provide a link for users to get more details
-
Use Metadata — Store structured data for future reference and debugging
-
Choose Correct Type — Use appropriate notification types for categorization
-
Test Notifications — Test with real users before deploying to production
Error Handling
-
Handle Failures Gracefully — Don't let notification failures break main workflows
-
Log All Attempts — Log notification attempts for debugging
-
Retry on Transient Errors — Implement retry logic for network issues
-
Validate User IDs — Verify user exists before sending
-
Check API Responses — Always check response status codes
Performance
-
Batch When Possible — For multiple users, consider sending in parallel
-
Async Processing — Send notifications asynchronously to avoid blocking
-
Rate Limiting — Implement rate limiting to prevent API abuse
-
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.yamland 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.logfor errors
API Reference Summary
Endpoints
| Method | Endpoint | Description | Auth |
|---|---|---|---|
| POST | /crm/notification/send | Send notification to user | API Key or Bearer |
| GET | /crm/notification/ | Get current user's notifications | Bearer |
| GET | /crm/notification/unread-count | Get unread count | Bearer |
| POST | /crm/notification/{id}/mark-read | Mark notification as read | Bearer |
| POST | /crm/notification/mark-all-read | Mark all as read | Bearer |
| DELETE | /crm/notification/{id} | Delete notification | Bearer |
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
Related Documentation
Using the API <concepts_api>— Complete API authentication guideSupport Ticket System <support_tickets>— Ticket notifications and @mentionsProvisioning System <concepts_provisioning>— Ansible integrationMonitoring & Metrics <monitoring_metrics>— System monitoring and alertingRBAC <rbac>— Roles and permissions