Conversations
5 API calls in this section.
Endpoints for managing message conversations between users.
Create Driver Dispatcher Order Conversation
/messaging/dispatcher-conversationsCreates or returns an active private conversation for the authenticated driver, selected dispatcher, and order.
Authentication and business rules
Driver JWT authentication is required.
delivery_idanddispatcher_user_idmust be UUIDs.The driver must have a current operational assignment for the delivery; cancelled, rejected, unassigned, completed, and returned assignments are not eligible.
The selected user must be an active dispatcher in the same tenant.
When both actors have explicit team mappings, they must share at least one team. Existing all-team behavior is preserved for actors without mappings.
The customer is never added to this conversation.
Repeating the same request returns the same active conversation; it does not create duplicate conversations or participants.
The conversation type is
dispatcher_order.
Success (HTTP 200)
returns conversation.id, delivery_id, type, status, and dispatcher_user_id.
Important errors
HTTP 400 for missing or invalid UUID fields.
HTTP 403 when the caller is not an eligible driver, is not assigned to the delivery, or cannot contact the selected dispatcher.
HTTP 404 when the delivery or dispatcher is unavailable.
Every error
messageis localized; English for a non-driver isOnly drivers can perform this action.
Frontend integration contract
Call this endpoint after the driver selects Message for a dispatcher returned by GET /delivery/dispatcher-contacts. Navigate to the chat using the returned conversation.id. On HTTP 403 or 404, do not open a chat and display the returned plain-language message.
Headers
| Parameter | Type | Description |
|---|---|---|
Authorization | string | Example: |
Content-Type | string | Example: |
Body parameters
| Parameter | Type | Description |
|---|---|---|
delivery_id | string | — |
dispatcher_user_id | string | — |
1curl --globoff --request POST "https://staging-api.ondi.io/functions/v1/messaging/dispatcher-conversations" \2 --header "Authorization: Bearer ${ONDI_ACCESS_TOKEN}" \3 --header "Content-Type: application/json" \4 --data-raw '{5 "delivery_id": "delivery-uuid",6 "dispatcher_user_id": "dispatcher-user-uuid"7}'Response examples
1{2 "success": true,3 "conversation": {4 "id": "conversation-uuid",5 "delivery_id": "delivery-uuid",6 "type": "dispatcher_order",7 "status": "active",8 "dispatcher_user_id": "dispatcher-user-uuid"9 }10}Get Chat Unread Count
/messaging/conversations/unread-countReturns one lightweight unread-chat summary for every chat icon in the authenticated user's application.
Authentication and scope
Requires a valid bearer token and tenant context.
The user and tenant are always derived from the authenticated request; this endpoint accepts no
user_id,tenant_id, body, or query parameters.Counts only conversations where the current user is an active participant (
left_atis null) in the current tenant.Driver clients exclude support-ticket conversations, matching
GET /messaging/conversations.
Unread definition
unread_countis the total number of qualifying unread messages.unread_conversation_countis the number of distinct conversations containing at least one qualifying unread message.Counts messages sent by another user after the participant's
last_read_message_id.If the participant has not read any message, counting starts at
joined_at; older history is not treated as unread.Excludes
system_notificationmessages and messages sent by the current user.Muting affects push delivery, not unread state, so muted conversations remain included.
Success
HTTP 200 returns success, a localized plain-language message, integer unread_count, and integer unread_conversation_count. A user with no unread messages receives both counts as 0.
Important errors
HTTP 401 when authentication is missing or invalid.
HTTP 404 when tenant context is unavailable.
HTTP 500 when the unread summary cannot be retrieved.
Frontend integration contract
Store both counts in shared application state; do not call this endpoint separately for each icon.
Use
unread_countwhen the badge represents unread messages, orunread_conversation_countwhen the badge represents chats awaiting attention.Fetch after authenticated app startup and foreground resume.
Refetch when a chat push notification arrives and after the existing conversation read-status request succeeds.
Hide the badge when the selected count is
0. A visual99+cap may be applied without changing the stored numeric value.The endpoint returns no action, entity ID, or navigation instruction.
Headers
| Parameter | Type | Description |
|---|---|---|
Authorization | string | Example: |
Content-Type | string | Example: |
1curl --globoff --request GET "https://staging-api.ondi.io/functions/v1/messaging/conversations/unread-count" \2 --header "Authorization: Bearer ${ONDI_ACCESS_TOKEN}" \3 --header "Content-Type: application/json"Response examples
1{2 "success": true,3 "message": "Unread chat count retrieved successfully",4 "unread_count": 12,5 "unread_conversation_count": 36}List Conversations
/messaging/conversationsRetrieves conversations based on specified filter criteria. Supports pagination and filtering by type, status, user ID, and optional server-side search.
Search behavior
searchis trimmed and matched case-insensitively as a substringA conversation matches when its
titleorlatest_message.contentcontains the termSearch combines with
tenant_id,type,status, anduser_idfiltersSearch is applied before pagination and exact counting, so
page,limit, andtotalremain valid for infinite paginationAn empty or whitespace-only
searchbehaves as if search was omitted
Authorization and driver behavior
Requires valid authentication token
Users can view their own conversations
Users with 'view:tenant' or 'manage:messaging:tenant' permission can view all conversations
When the authenticated actor has the
driverrole, support-ticket conversations (type=support) are excluded before exact count and pagination, even if a historical active participant row exists
Successful response
HTTP 200 with
success,message,conversations,page,limit, andtotalReturns the existing conversation objects with participants,
latest_message, andunread_countunchangedFor drivers,
totalcounts only accessible non-support conversations
Important errors
HTTP 403 when requesting another user's conversations without permission
HTTP 404 when tenant context is unavailable
HTTP 500 when conversation retrieval fails
Frontend integration contract
Send the mobile search text as the
searchquery parameterKeep the same
search,type,status, anduser_idvalues while incrementingpageUse
totalwith the accumulated result count to stop infinite paginationDriver clients must not expect support-ticket chats in this list
No response field or navigation-action shape changes
Query parameters
| Parameter | Type | Description |
|---|---|---|
tenant_id | string | UUID of the tenant (required if not in auth token) Example: |
type | string | Filter by conversation type (support, order, delivery, team, etc.) |
status | string | Filter by conversation status |
user_id | string | UUID of the user to filter conversations by (defaults to authenticated user) |
searchOptional | string | Optional case-insensitive substring search across conversation title and latest-message content. Applied with all existing filters before counting and pagination. |
page | string | Page number for pagination (default: 1) Example: |
limit | string | Number of items per page (default: 20) Example: |
Headers
| Parameter | Type | Description |
|---|---|---|
Authorization | string | Example: |
Content-Type | string | Example: |
1curl --globoff --request GET "https://staging-api.ondi.io/functions/v1/messaging/conversations?tenant_id=${TENANT_ID}&type=&status=&user_id=&search=&page=1&limit=20" \2 --header "Authorization: Bearer ${ONDI_ACCESS_TOKEN}" \3 --header "Content-Type: application/json"Response examples
1{2 "success": true,3 "message": "Conversations retrieved successfully",4 "conversations": [5 {6 "id": "uuid",7 "tenant_id": "uuid",8 "title": "Support Chat #123",9 "type": "support",10 "status": "active",11 "metadata": {12 "order_id": "12345",13 "priority": "high"14 },15 "created_at": "2023-01-01T00:00:00Z",16 "updated_at": "2023-01-01T01:00:00Z",17 "created_by": "uuid",18 "is_system_conversation": false,19 "participants": [20 {21 "id": "uuid",22 "user_id": "uuid",23 "role": "admin",24 "joined_at": "2023-01-01T00:00:00Z",25 "left_at": null,26 "muted": false,27 "notification_preferences": {28 "email": true,29 "push": true30 },31 "user": {32 "id": "uuid",33 "full_name": "John Doe",34 "email": "john@example.com",35 "avatar_url": "https://example.com/avatar.jpg",36 "phone": "+1234567890"37 }38 }39 ],40 "latest_message": {41 "id": "uuid",42 "sender_id": "uuid",43 "message_type": "text",44 "content": "Hello!",45 "content_url": null,46 "sent_at": "2023-01-01T01:00:00Z"47 },48 "unread_count": 049 }50 ],51 "page": 1,52 "limit": 20,53 "total": 154}Create Conversation
/messaging/conversationsCreates a new conversation.
Rules
If
delivery_idis provided, only one conversation per delivery is allowed. If a conversation for that delivery exists, it will be reused and new participants will be added.For drivers/users/dispatchers,
delivery_idis required.For free (non-delivery) conversations, only dispatcher/admin can create.
For delivery conversations, participants are auto-determined (driver + customer) and optional in request. If provided, they are added as additional participants.
For free conversations, participants are required.
The delivery's customer (user who created the delivery) is auto-added as a participant for delivery conversations.
Creator is automatically added as admin if not in participants list.
All participants must belong to the tenant.
If
titleis not provided anddelivery_idis present, the title will be auto-generated as#<external reference id> - <customer name>.The
typefield is always set to 'order' by the backend and is not required in the request.
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 |
|---|---|---|
delivery_id | string | — |
metadata | object | — |
metadata.order_id | string | — |
metadata.priority | string | — |
1curl --globoff --request POST "https://staging-api.ondi.io/functions/v1/messaging/conversations?tenant_id=${TENANT_ID}" \2 --header "Authorization: Bearer ${ONDI_ACCESS_TOKEN}" \3 --header "Content-Type: application/json" \4 --data-raw '{5 "delivery_id": "delivery-uuid",6 "metadata": {7 "order_id": "12345",8 "priority": "high"9 }10}'Other request examples (1)
1{2 "title": "string", // optional, auto-generated if not provided and delivery_id is present3 "participants": ["uuid"], // optional for delivery conversations, required for free conversations4 "delivery_id": "uuid", // required for delivery conversations5 "metadata": {} // optional6}Response examples
1{2 "success": true,3 "message": "Conversation created successfully",4 "conversation": {5 "id": "uuid",6 "tenant_id": "uuid",7 "delivery_id": "delivery-uuid",8 "title": "Support Chat #123",9 "type": "order",10 "status": "active",11 "metadata": {12 "order_id": "12345",13 "priority": "high"14 },15 "created_at": "2023-01-01T00:00:00Z",16 "updated_at": "2023-01-01T00:00:00Z",17 "created_by": "uuid",18 "is_system_conversation": false,19 "participants": [20 {21 "id": "uuid",22 "user_id": "uuid1",23 "role": "admin",24 "joined_at": "2023-01-01T00:00:00Z",25 "muted": false,26 "notification_preferences": null,27 "user": {28 "id": "uuid1",29 "full_name": "John Doe",30 "email": "john@example.com",31 "profile_image_url": "https://example.com/avatar.jpg"32 }33 },34 {35 "id": "uuid2",36 "user_id": "uuid2",37 "role": "member",38 "joined_at": "2023-01-01T00:00:00Z",39 "muted": false,40 "notification_preferences": null,41 "user": {42 "id": "uuid2",43 "full_name": "Jane Smith",44 "email": "jane@example.com",45 "profile_image_url": "https://example.com/avatar2.jpg"46 }47 }48 ]49 }50}Get Conversation
/messaging/conversations/:conversationIdRetrieves detailed information about a specific conversation including participants and latest message.
Authorization
Requires valid authentication token
Standard conversations: user must be an active participant, have
view:tenant, or be system adminSupport-ticket conversations: only the ticket customer, a configured tenant support user while support is enabled, or a system admin can access
A historical participant row does not grant a driver access to a support-ticket conversation
Unauthorized support-ticket access returns HTTP 403 with
{"success":false,"message":"Insufficient Permissions"}
Response
Returns conversation details with participant information and latest message
Includes participant user details (name, email, avatar)
Path parameters
| Parameter | Type | Description |
|---|---|---|
conversationIdRequired | string | UUID of the conversation to retrieve Example: |
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/conversations/${CONVERSATIONID}?tenant_id=${TENANT_ID}" \2 --header "Authorization: Bearer ${ONDI_ACCESS_TOKEN}" \3 --header "Content-Type: application/json"Response examples
1{2 "success": true,3 "conversation": {4 "id": "uuid",5 "title": "Support Chat #123",6 "type": "order",7 "status": "active",8 "tenant_id": "uuid",9 "created_at": "2023-01-01T00:00:00Z",10 "updated_at": "2023-01-01T01:00:00Z",11 "metadata": {12 "order_id": "12345",13 "priority": "high"14 },15 "participants": [16 {17 "user_id": "uuid1"18 },19 {20 "user_id": "uuid2"21 }22 ],23 "latest_message": {24 "id": "uuid",25 "content": "Hello, how can I help you?",26 "sender_id": "uuid1",27 "created_at": "2023-01-01T01:00:00Z",28 "metadata": {},29 "status": "sent"30 },31 "participant_details": [32 {33 "id": "uuid1",34 "full_name": "John Doe",35 "email": "john@example.com",36 "avatar_url": "https://example.com/avatar.jpg",37 "phone": "+1234567890",38 "metadata": {}39 },40 {41 "id": "uuid2",42 "full_name": "Jane Smith",43 "email": "jane@example.com",44 "avatar_url": "https://example.com/avatar2.jpg",45 "phone": "+0987654321",46 "metadata": {}47 }48 ]49 }50}