Skip to main content

Messages

2 API calls in this section.

Endpoints for managing messages within conversations.

Realtime frontend contract

  • Subscribe to Supabase Postgres Changes on schema public, table messages, event: INSERT using a valid authenticated user access token.

  • The database delivers a message only when the JWT user has a message_participants row for that message's conversation with left_at equal to null.

  • A user does not receive messages from conversations where they have no active participant row or where their participant row has left_at set.

  • Do not subscribe with the anon role; anonymous database access to messages and message_participants is revoked.

  • Do not use event * for this listener. The app-wide listener must be INSERT-only.

  • Message creation and participant changes continue through the authenticated Messaging API; frontend clients have read-only table access.

  • On each received INSERT, refetch GET /messaging/conversations/unread-count once and update the shared unread badge state used by every chat icon.

List Messages​

Communications & Feedback / Messaging / Messages
GET/messaging/conversations/:conversationId/messages

Retrieves messages from a specific conversation with filtering and pagination options.

Authorization

  • Requires valid authentication token

  • Standard conversations: user must be a participant in the conversation OR be system admin

  • Support-ticket conversations: only the ticket customer, a configured tenant support user while support is enabled, or a system admin can list messages

  • Active participant membership alone does not grant driver access to a support-ticket conversation

  • Unauthorized support-ticket access returns HTTP 403 with {"success":false,"message":"Insufficient Permissions"}

Response

  • Returns paginated list of messages with sender information

  • Updates participant's last read message automatically

Path parameters

ParameterTypeDescription
conversationIdRequiredstring

UUID of the conversation

Example: uuid

Query parameters

ParameterTypeDescription
tenant_idstring

UUID of the tenant (required if not in auth token)

Example: {{tenant_id}}

pagestring

Page number for pagination (default: 1)

Example: 1

limitstring

Number of items per page (default: 20)

Example: 20

timestamp_rangestring

Filter by message timestamp range (format: 2023-01-01T00:00:00Z,2023-01-02T00:00:00Z)

Headers

ParameterTypeDescription
Authorizationstring

Example: Bearer {{access_token}}

Content-Typestring

Example: application/json

Staging
Request
curl
1curl --globoff --request GET "https://staging-api.ondi.io/functions/v1/messaging/conversations/${CONVERSATIONID}/messages?tenant_id=${TENANT_ID}&page=1&limit=20&timestamp_range=" \2  --header "Authorization: Bearer ${ONDI_ACCESS_TOKEN}" \3  --header "Content-Type: application/json"

Response examples

200OK
Response body
json
1{2  "success": true,3  "messages": [4    {5      "id": "uuid",6      "conversation_id": "uuid",7      "sender_id": "uuid",8      "message_type": "text",9      "content": "Hello!",10      "content_url": null,11      "metadata": null,12      "sent_at": "2023-01-01T00:00:00Z",13      "delivered_status": {},14      "deleted_by": [],15      "parent_message_id": null,16      "sender": {17        "id": "uuid",18        "full_name": "John Doe",19        "email": "john@example.com",20        "avatar_url": "https://example.com/avatar.jpg"21      }22    }23  ],24  "page": 1,25  "limit": 20,26  "total": 127}

Send Message​

Communications & Feedback / Messaging / Messages
POST/messaging/conversations/:conversationId/messages

Sends a new message to a conversation.

Authorization

  • Requires valid authentication token

  • Standard conversations: user must be an active participant

  • Support-ticket conversations: only the ticket customer, a configured/eligible support user, or a system admin can send

  • Active participant membership alone does not grant driver access to a support-ticket conversation

  • Unauthorized support-ticket access returns HTTP 403 with {"success":false,"message":"Insufficient Permissions"}

  • Conversation must be in 'active' status

Asynchronous Push Delivery

  • After the message commits, a database trigger invokes the notifications Edge Function.

  • OneSignal push is sent to active conversation participants except the sender.

  • Muted participants, participants with notification_preferences.push=false, users with notifications_enabled=false, and participants who left the conversation are excluded.

  • No notifications row is created for a chat message.

  • Push failure does not roll back the message or change this endpoint's HTTP 201 response.

  • Push data contains action=open_conversation, conversation_id, message_id, and sender_id.

Frontend Integration

  • Register the authenticated backend user UUID as the OneSignal external_id.

  • On push tap, handle action=open_conversation and navigate using conversation_id.

  • If that conversation is already open, suppress the foreground push banner and continue using message Realtime.

Note

  • message_type=html is reserved for server-generated messages (e.g., support acknowledgements) and is rejected if sent by clients.

Path parameters

ParameterTypeDescription
conversationIdRequiredstring

UUID of the conversation

Example: uuid

Query parameters

ParameterTypeDescription
tenant_idstring

UUID of the tenant (required if not in auth token)

Example: {{tenant_id}}

Headers

ParameterTypeDescription
Authorizationstring

Example: Bearer {{access_token}}

Content-Typestring

Example: application/json

Body parameters

ParameterTypeDescription
message_typestring—
contentstring—
content_urlnull—
metadatanull—
parent_message_idnull—
Staging
Request
curl
1curl --globoff --request POST "https://staging-api.ondi.io/functions/v1/messaging/conversations/${CONVERSATIONID}/messages?tenant_id=${TENANT_ID}" \2  --header "Authorization: Bearer ${ONDI_ACCESS_TOKEN}" \3  --header "Content-Type: application/json" \4  --data-raw '{5  "message_type": "text",6  "content": "Hello!",7  "content_url": null,8  "metadata": null,9  "parent_message_id": null10}'
Other request examples (1)
Request example 1
text
1{2  "message_type": "text" | "image" | "file" | "audio" | "video" | "location", // required3  "content": "string", // required for text messages4  "content_url": "string", // required for media messages (image, file, audio, video)5  "metadata": {}, // optional additional data6  "parent_message_id": "uuid" // optional - for threaded replies7}

Response examples

201Created
Response body
json
1{2  "success": true,3  "message": {4    "id": "uuid",5    "conversation_id": "uuid",6    "sender_id": "uuid",7    "message_type": "text",8    "content": "Hello!",9    "content_url": null,10    "metadata": null,11    "sent_at": "2023-01-01T00:00:00Z",12    "delivered_status": {},13    "deleted_by": [],14    "parent_message_id": null,15    "sender": {16      "id": "uuid",17      "first_name": "John",18      "last_name": "Doe",19      "email": "john@example.com",20      "avatar_url": "https://example.com/avatar.jpg"21    }22  }23}