TryVox

Conversations

List, fetch, and mark-as-read message conversations.

A conversation is the running thread between one of your channels and one recipient phone number. It's created automatically the first time a message flows in either direction. You don't create conversations directly — these endpoints are for reading and managing them.

List conversations

GET /v1/messaging/conversations

Query parameters

ParameterTypeDescription
channel_iduuidRestrict to one channel.
statusstringopen or closed. Omit to return both.
categorystringRestrict to one category (e.g. service).
searchstringMatches contact name, contact phone number, or the last message text.
pageinteger1-indexed. Default: 1.
per_pageintegerDefault: 20, max: 100.

There's no unread_only filter — filter client-side on unread_count > 0 after fetching, or use search/status to narrow the list first.

Example

curl -u $TRYVOX_AUTH_ID:$TRYVOX_AUTH_TOKEN \
  "https://api.tryvox.io/v1/messaging/conversations?status=open&per_page=50"

Response

200 OK:

{
  "data": [
    {
      "id": "3c4d5e6f-7a8b-9c0d-1e2f-3a4b5c6d7e8f",
      "account_id": "TJab12cd34",
      "channel_id": "8f7a4b2e-91c2-4f3d-9a1e-2c4b6d8f0a1c",
      "contact_id": "4d5e6f70-8192-a3b4-c5d6-e7f8a9b0c1d2",
      "contact": {
        "id": "4d5e6f70-8192-a3b4-c5d6-e7f8a9b0c1d2",
        "name": "Alex Carter",
        "phone_number": "+14155551234"
      },
      "category": "service",
      "status": "open",
      "last_message_at": "2026-04-09T11:14:32Z",
      "last_message_preview": "Yes, please go ahead.",
      "unread_count": 2,
      "created_at": "2026-04-09T09:00:00Z",
      "updated_at": "2026-04-09T11:14:32Z"
    }
  ],
  "meta": {"page": 1, "per_page": 50, "total": 1}
}

The recipient's phone number is contact.phone_number (nested), not a top-level contact_phone field. expires_at, when present, is when the 24-hour customer service window closes — check it before sending plain text/media; past it, TryVox returns 403 OUTSIDE_CS_WINDOW and you need a template instead.

Get a conversation

GET /v1/messaging/conversations/{id}
curl -u $TRYVOX_AUTH_ID:$TRYVOX_AUTH_TOKEN \
  https://api.tryvox.io/v1/messaging/conversations/3c4d5e6f-7a8b-9c0d-1e2f-3a4b5c6d7e8f

Returns the same shape as a list entry — no extra message history attached. Use Get messages for that.

Get messages in a conversation

GET /v1/messaging/conversations/{id}/messages

Query parameters

ParameterTypeDescription
beforeuuidReturn messages older than this message_id (cursor for paging back).
limitintegerMax messages. Default: 50, max: 100.

Example

curl -u $TRYVOX_AUTH_ID:$TRYVOX_AUTH_TOKEN \
  "https://api.tryvox.io/v1/messaging/conversations/$CONV_ID/messages?limit=50"

Response

200 OK:

{
  "data": [
    {
      "id": "2c3d4e5f-6071-8293-a4b5-c6d7e8f9a0b1",
      "conversation_id": "3c4d5e6f-7a8b-9c0d-1e2f-3a4b5c6d7e8f",
      "contact_id": "4d5e6f70-8192-a3b4-c5d6-e7f8a9b0c1d2",
      "direction": "inbound",
      "message_type": "text",
      "content": "Thanks! Confirmed.",
      "status": "received",
      "has_media": false,
      "timestamp": "2026-04-09T11:14:32Z",
      "created_at": "2026-04-09T11:14:32Z"
    },
    {
      "id": "1b2c3d4e-5f60-7180-9a2b-3c4d5e6f7a8b",
      "conversation_id": "3c4d5e6f-7a8b-9c0d-1e2f-3a4b5c6d7e8f",
      "contact_id": "4d5e6f70-8192-a3b4-c5d6-e7f8a9b0c1d2",
      "direction": "outbound",
      "message_type": "text",
      "content": "Hi, your appointment is confirmed for tomorrow at 10am.",
      "status": "delivered",
      "has_media": false,
      "timestamp": "2026-04-09T09:00:12Z",
      "created_at": "2026-04-09T09:00:12Z"
    }
  ]
}

Messages are returned newest-first (matching the prose above — the inbound reply at 11:14:32 comes before the outbound message from 09:00:12). Page back in time with ?before={oldest_id_you_have}. There's no has_more flag — if you get back exactly limit rows, assume there may be more and page again; fewer than limit means you've reached the start of the conversation.

There's no to/from field on a message — the recipient/sender phone number is the conversation's contact_phone (Get a conversation), not repeated on every message. For inbound media (message_type is image, video, audio, or document), has_media is true and media_id/media_mime_type are set — see Download inbound media below. For a button or list reply, message_type is interactive, content is a human-readable summary (e.g. the button's label), and interactive_payload carries the full structured reply if you need to branch on it programmatically.

Download inbound media

When a customer sends an image, video, audio note, or document, TryVox downloads it from Meta and stores it; the message row has has_media: true and a media_id. Fetch the bytes with:

GET /v1/messaging/messages/{message_id}/media
curl -u $TRYVOX_AUTH_ID:$TRYVOX_AUTH_TOKEN \
  https://api.tryvox.io/v1/messaging/messages/$MESSAGE_ID/media \
  -o received-file

This streams the raw file, not JSON — the response Content-Type is the media's real MIME type (from media_mime_type on the message), and it supports HTTP Range requests for partial/resumable downloads. 404 MEDIA_NOT_FOUND means TryVox hasn't successfully downloaded the file from Meta yet (or the download failed) — call POST /v1/messaging/messages/{message_id}/media/retry-download to force another attempt. Meta eventually expires media it hasn't served, so a very old undelivered file may never succeed — treat repeated retry failures as permanent.

Mark as read

Marks every unread inbound message in the conversation as read. Outbound messages are unaffected.

POST /v1/messaging/conversations/{id}/read
curl -X POST \
  -u $TRYVOX_AUTH_ID:$TRYVOX_AUTH_TOKEN \
  https://api.tryvox.io/v1/messaging/conversations/$CONV_ID/read

204 No Content. The conversation's unread_count resets to zero in TryVox. This does not send a read receipt to Meta/WhatsApp — it only affects your own unread count, not whether the sender sees blue ticks.

Errors

StatusCodeReason
401INVALID_CREDENTIALSAuth ID / Auth Token bad
404CONVERSATION_NOT_FOUNDNo conversation with this id on this tenant

Notes

  • No "create conversation" endpoint. Conversations exist as a side effect of messages. To start a thread, send a template message via Send a Message.
  • Status is auto-managed. Conversations close after 30 days of inactivity (status: "closed"). A new inbound or outbound message on a closed conversation reopens it.
  • No archive endpoint. Use status=closed filter to see archived threads.

On this page