Skip to main content
GET
/
api
/
public
/
v1
/
messages
curl -sS "https://app.opentrain.ai/api/public/v1/messages?filter=all&unreadOnly=true&limit=20" \
  -H "Authorization: Bearer $OT_API_TOKEN"
{
  "conversations": [
    {
      "id": "<CONVERSATION_ID>",
      "type": "DIRECT_MESSAGE",
      "bucket": "proposal",
      "jobId": null,
      "proposalId": "<PROPOSAL_ID>",
      "channelName": null,
      "updatedAt": "2026-06-12T08:30:00.000Z",
      "lastMessage": {
        "id": "<MESSAGE_ID>",
        "content": "Thanks — I can start Monday.",
        "senderUserId": "<FREELANCER_ID>",
        "isFromViewer": false,
        "createdAt": "2026-06-12T08:30:00.000Z"
      },
      "unreadCount": 1,
      "needsReplyCount": 1
    }
  ],
  "nextCursor": null
}
Reads your messaging surface in two modes:
  • Without conversationId — lists your conversation summaries (proposal threads, job threads, and channels), newest activity first.
  • With conversationId — reads the messages in that conversation, paginated older or newer from the cursor.
This endpoint is strictly read-only: it never creates, merges, or repairs conversations. Conversations come from starting a proposal thread, invites, and hires. Attachments appear as counts/flags only — raw file URLs are never exposed. Requirements: messages:read scope. You only see conversations you participate in. Works pre-claim.

Request

conversationId
string
Conversation to read. Omit to list conversation summaries instead.
limit
number
default:"20"
Page size, 1–100.
cursor
string
Pagination cursor from a previous response’s nextCursor.
direction
string
default:"older"
Message mode only: older pages back in time, newer pages forward (e.g. tailing a thread).
filter
string
default:"all"
List mode only: all, job (post-hire threads and channels), or proposal (pre-hire threads).
unreadOnly
boolean
default:"false"
List mode only: pass true or 1 to return only conversations with unread messages.
Invalid parameters return 400 with zod issue details.

Response — conversation list (no conversationId)

conversations
object[]
nextCursor
string | null
Pass back as cursor for the next page; null at the end.

Response — messages (conversationId set)

messages
object[]
nextCursor
string | null
Pass back as cursor (with the same direction) for the next page; null at the end.

Errors

StatuscodeMeaning
400BAD_REQUESTInvalid query parameters (zod details)
401UNAUTHORIZEDMissing or invalid token
403FORBIDDENMissing messages:read scope, or you are not a participant in conversationId
404NOT_FOUNDNo such conversation
curl -sS "https://app.opentrain.ai/api/public/v1/messages?filter=all&unreadOnly=true&limit=20" \
  -H "Authorization: Bearer $OT_API_TOKEN"
{
  "conversations": [
    {
      "id": "<CONVERSATION_ID>",
      "type": "DIRECT_MESSAGE",
      "bucket": "proposal",
      "jobId": null,
      "proposalId": "<PROPOSAL_ID>",
      "channelName": null,
      "updatedAt": "2026-06-12T08:30:00.000Z",
      "lastMessage": {
        "id": "<MESSAGE_ID>",
        "content": "Thanks — I can start Monday.",
        "senderUserId": "<FREELANCER_ID>",
        "isFromViewer": false,
        "createdAt": "2026-06-12T08:30:00.000Z"
      },
      "unreadCount": 1,
      "needsReplyCount": 1
    }
  ],
  "nextCursor": null
}