Notifications
4 API calls in this section.
Endpoints for listing, acknowledging, marking as read, and getting notification statistics. Acknowledgement is intentionally separate from read state.
List Notifications
/messaging/notificationsRetrieve the authenticated user's sent notifications, sorted by created_at descending.
Authorization
JWT required. Rows are scoped to the authenticated recipient and tenant.
Filters
page, limit (max 100), read_status=true|false, notification_type, priority=normal|important|critical, display_mode=toast|banner|modal, acknowledged=true|false, and optional tenant_id.
Response contract
Each row includes priority, display_mode, requires_acknowledgement, acknowledged_at, channel_status, template_data, and the existing action. action.secondary_actions may contain copy, call, navigate, or external_url; these actions never acknowledge the row. The response also includes unread_count and pending_critical_count.
Delivery exception decision notification
A delivery_exception_resolved row has associated_entity_type=delivery, associated_entity_id=<deliveryId>, and template_data containing deliveryId, deliveryCode, actionKey (retry or return), isRetry, isReturn, and returnDestinationLabel. It uses priority=critical, display_mode=modal, and requires_acknowledgement=true, so the driver app receives it through GET /messaging/notifications?priority=critical&acknowledged=false&page=1&limit=100. Show a dedicated modal using the returned localized title and body; the modal action is “I understand” and calls PUT /messaging/notifications/:notificationId/acknowledge with no body. Acknowledgement closes only the alert. GET /delivery/driver-deliveries remains the persistent operational source through each row's returnStatus.
Frontend integration
On driver login, cold launch, and foreground resume call GET /messaging/notifications?priority=critical&acknowledged=false&page=1&limit=100. Use notification_type to choose the specialized component and display_mode to choose toast, banner, or modal presentation. Render title/body as plain text. Unknown types fall back to the generic title/body component. Show the oldest unacknowledged critical row first.
Query parameters
| Parameter | Type | Description |
|---|---|---|
page | string | Page number for pagination (default: 1) Example: |
limit | string | Number of notifications per page (max 100, default: 20) Example: |
read_status | string | Filter by read status: 'true', 'false', or omit for all Example: |
notification_type | string | Filter by notification type ( |
priority | string | Filter by priority: normal, important, or critical Example: |
display_modeOptional | string | Optional filter: toast, banner, or modal |
acknowledged | string | Filter by acknowledgement timestamp: true or false Example: |
tenant_id | string | UUID of the tenant (required if not in auth token) Example: |
Headers
| Parameter | Type | Description |
|---|---|---|
Authorization | string | Example: |
Content-Type | string | Example: |
1curl --globoff --request GET "https://staging-api.ondi.io/functions/v1/messaging/notifications?page=1&limit=100&priority=critical&acknowledged=false&tenant_id=${TENANT_ID}" \2 --header "Authorization: Bearer ${ONDI_ACCESS_TOKEN}" \3 --header "Content-Type: application/json"Response examples
1{2 "success": true,3 "message": "Notifications retrieved successfully",4 "notifications": [5 {6 "id": "123e4567-e89b-42d3-a456-426614174000",7 "notification_type": "assignment_driver_switched",8 "title": "Driver changed for delivery #3239A",9 "body": "You were switched from delivery #3239A after pickup. Coordinate with your dispatcher and transfer the package to Ahmed Hassan.",10 "read_status": false,11 "priority": "critical",12 "display_mode": "modal",13 "requires_acknowledgement": true,14 "acknowledged_at": null,15 "associated_entity_type": "delivery",16 "associated_entity_id": "123e4567-e89b-42d3-a456-426614174001",17 "template_data": {18 "deliveryId": "123e4567-e89b-42d3-a456-426614174001",19 "deliveryCode": "3239A",20 "newDriver": {21 "driverId": "123e4567-e89b-42d3-a456-426614174002",22 "userId": "123e4567-e89b-42d3-a456-426614174003",23 "fullName": "Ahmed Hassan",24 "avatarUrl": "https://example.com/ahmed.jpg",25 "phone": "+9647500000000"26 }27 },28 "action": {29 "target": "internal",30 "path": "/driver/pickup_and_delivery/123e4567-e89b-42d3-a456-426614174001",31 "secondary_actions": [32 {33 "id": "copy_driver_contact",34 "type": "copy",35 "label": "Copy contact",36 "value": "Ahmed Hassan — +9647500000000"37 },38 {39 "id": "call_driver",40 "type": "call",41 "label": "Call driver",42 "value": "+9647500000000"43 }44 ]45 },46 "channel_status": {47 "in_app": {48 "status": "available",49 "available_at": "2026-07-27T10:30:03Z"50 },51 "push": {52 "status": "failed",53 "retry_count": 1,54 "error": "push delivery failed"55 }56 }57 }58 ],59 "pagination": {60 "page": 1,61 "limit": 100,62 "total": 1,63 "total_pages": 164 },65 "unread_count": 1,66 "pending_critical_count": 167}Acknowledge Notification
/messaging/notifications/{{notification_id}}/acknowledgeAcknowledge one persistent notification. No request body or user ID is accepted. The UUID is scoped to the authenticated recipient and tenant. The operation atomically sets acknowledged_at, read_status=true, and updated_at; repeated calls return HTTP 200 with the existing timestamp. HTTP 404 notification_not_found is used for missing or unauthorized rows. HTTP 409 notification_acknowledgement_not_required is used for non-acknowledgeable rows. Driver-switch notifications keep their existing acknowledgement behavior, but acknowledgement no longer controls delivery custody or status actions; custody already transferred during Switch Driver and the response returns handoff=null.
Frontend integration contract
Continue showing the existing “I understand” action when a driver-switch notification has requires_acknowledgement=true. Treat HTTP 200 as notification acknowledgement only; do not wait for handoff.completed before allowing the replacement driver to continue. Queue valid acknowledgement requests while offline and retry safely. Secondary actions do not acknowledge a notification.
Path parameters
| Parameter | Type | Description |
|---|---|---|
notification_idRequired | string | Variable used inside the request path. |
Headers
| Parameter | Type | Description |
|---|---|---|
Authorization | string | Example: |
Content-Type | string | Example: |
1curl --globoff --request PUT "https://staging-api.ondi.io/functions/v1/messaging/notifications/${NOTIFICATION_ID}/acknowledge" \2 --header "Authorization: Bearer ${ONDI_ACCESS_TOKEN}" \3 --header "Content-Type: application/json"Response examples
1{2 "success": true,3 "message": "Notification acknowledged successfully",4 "notification": {5 "id": "123e4567-e89b-42d3-a456-426614174000",6 "acknowledged_at": "2026-07-27T10:35:00Z",7 "requires_acknowledgement": true,8 "read_status": true,9 "updated_at": "2026-07-27T10:35:00Z"10 },11 "already_acknowledged": false,12 "handoff": null13}Mark Notifications as Read
/messaging/notifications/mark-readMark notifications as read for the current user. Users can only mark their own notifications as read.
If
notification_idsarray is provided: marks only those specific notifications as readIf request body is empty or not provided: marks all unread notifications as read
Validation
The system validates that all provided notification IDs belong to the authenticated user
Only unread notifications are updated (already read notifications are skipped)
Returns error
invalid_notification_idswith list of invalid IDs if any provided IDs don't exist or don't belong to the user
Query parameters
| Parameter | Type | Description |
|---|---|---|
tenant_id | string | UUID of the tenant (required if not in auth token) Example: |
Headers
| Parameter | Type | Description |
|---|---|---|
Authorization | string | Example: |
Content-Type | string | Example: |
Body parameters
| Parameter | Type | Description |
|---|---|---|
notification_ids | array<string> | — |
1curl --globoff --request PUT "https://staging-api.ondi.io/functions/v1/messaging/notifications/mark-read?tenant_id=${TENANT_ID}" \2 --header "Authorization: Bearer ${ONDI_ACCESS_TOKEN}" \3 --header "Content-Type: application/json" \4 --data-raw '{5 "notification_ids": [6 "uuid1",7 "uuid2",8 "uuid3"9 ]10}'Response examples
1{2 "success": true,3 "message": "Notifications marked as read",4 "updated_count": 35}Get Notification Statistics
/messaging/notifications/statsGet notification statistics for the current user including total, unread, and read counts.
Authorization
Requires valid authentication token
Users can only view their own notification statistics
Response
Returns notification counts (total, unread, read)
Useful for displaying notification badges in UI
Query parameters
| Parameter | Type | Description |
|---|---|---|
tenant_id | string | UUID of the tenant (required if not in auth token) Example: |
Headers
| Parameter | Type | Description |
|---|---|---|
Authorization | string | Example: |
Content-Type | string | Example: |
1curl --globoff --request GET "https://staging-api.ondi.io/functions/v1/messaging/notifications/stats?tenant_id=${TENANT_ID}" \2 --header "Authorization: Bearer ${ONDI_ACCESS_TOKEN}" \3 --header "Content-Type: application/json"Response examples
1{2 "success": true,3 "message": "Notification stats retrieved",4 "stats": {5 "total": 45,6 "unread": 12,7 "read": 338 }9}