Skip to content
Documentation
pozyskajpacjentaDocs

API referenceConversations

List messages of a conversation

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

Since
1.14.0
Auth
Bearer key
operationId
listMessages

The messages of one conversation, newest first; nextCursor pages to older ones. A webhook message.received names the conversation and the message: the message is on the first page. The first chat message of a chat lead is its enquiry, in lead.message of the conversation. Needs the scope conversations:read; the read is written to the clinic's audit log. The response holds patient data and is never cached (Cache-Control: no-store); call it from your server only.

Request

Send the clinic's key in Authorization: Bearer (see API keys).

Path parameters

  • idstringrequired

    The conversation id (conversationId of webhook events).

Query parameters

  • cursorstring

    nextCursor of the previous page; omit for the newest messages.

  • limitinteger

    Messages per page, 1 to 100 (default 50).

curl "https://app.pozyskajpacjenta.pl/api/v1/conversations/Vb3nQ8sLk2PzX5wRt9YcE/messages" \
  -H "Authorization: Bearer $PP_API_KEY"
import { PozyskajPacjentaClient } from "@pozyskajpacjenta/sdk";

const client = new PozyskajPacjentaClient({
  apiKey: process.env.PP_API_KEY ?? "",
  baseUrl: "https://app.pozyskajpacjenta.pl",
});

const { messages, nextCursor } = await client.listMessages("Vb3nQ8sLk2PzX5wRt9YcE", {
  limit: 20,
});
<?php
$response = wp_remote_get(
    'https://app.pozyskajpacjenta.pl/api/v1/conversations/Vb3nQ8sLk2PzX5wRt9YcE/messages',
    array(
        'headers' => array( 'Authorization' => 'Bearer ' . getenv( 'PP_API_KEY' ) ),
        'timeout' => 10,
    )
);
if ( is_wp_error( $response ) ) {
    error_log( $response->get_error_message() );
    return;
}
$status = wp_remote_retrieve_response_code( $response );
$data   = json_decode( wp_remote_retrieve_body( $response ), true );

Response

200A page of messages.

  • messagesConversationMessage[]required

    The messages, newest first.

    Fields of each item (12)
    • idstringrequired

      Message id: the messageId of webhook events.

    • conversationIdstringrequired

      The conversation it belongs to.

    • channelstringrequired

      The channel: email, sms, whatsapp, instagram or chat (the chat on the clinic's site).

      One of emailsmswhatsappinstagramchat

    • directionstringrequired

      inbound: from the patient. outbound: from the clinic (the inbox, an automation or this API). outbound_echo: the clinic replied from the WhatsApp or Instagram app itself.

      One of inboundoutboundoutbound_echo

    • statusstringrequired

      received for every inbound message. Outbound messages move forward only: queued, sent, delivered, read; or failed.

      One of queuedsentdeliveredreadfailedreceived

    • subjectstring | nullrequired

      E-mail subject; null on other channels.

    • textstring | nullrequired

      The text; null for a message with attachments only.

    • attachmentsMessageAttachment[]required

      Files that came with the message.

      Fields of each item (3)
      • filenamestringrequired

        File name.

      • mimestringrequired

        Media type, e.g. image/jpeg.

      • sizeintegerrequired

        Size in bytes.

    • createdAtstring (date-time)required

      When the message was stored.

    • sentAtstring (date-time) | nullrequired

      Outbound: when the provider accepted it; null otherwise.

    • deliveredAtstring (date-time) | nullrequired

      Outbound: when it reached the patient's device, where the channel reports it.

    • readAtstring (date-time) | nullrequired

      Inbound: when someone at the clinic opened it. Outbound: the provider's read receipt, where the channel reports it.

  • nextCursorstring | nullrequired

    Pass it as cursor for older messages; null at the first message.

The newest message

{
  "messages": [
    {
      "id": "gH2jK4lZ6xC8vB0nM1qWe",
      "conversationId": "Vb3nQ8sLk2PzX5wRt9YcE",
      "channel": "sms",
      "direction": "inbound",
      "status": "received",
      "subject": null,
      "text": "Pasuje, dziękuję. Do zobaczenia w czwartek.",
      "attachments": [],
      "createdAt": "2026-10-12T08:02:44.000Z",
      "sentAt": null,
      "deliveredAt": null,
      "readAt": null
    }
  ],
  "nextCursor": "1791792164.gH2jK4lZ6xC8vB0nM1qWe"
}

Errors

StatuscodeWhen
400invalid_querylimit above 100
401No Authorization header
401Unknown or rotated key
403missing_scopeThe key lacks conversations:read
404not_foundUnknown id, another clinic's conversation or an archived lead's
429Over 120 requests in this minute

Branch on the status and code, never on the Polish error text. All statuses in Errors.

400 · limit above 100
{
  "error": "limit: od 1 do 100",
  "code": "invalid_query"
}
401 · No Authorization header
{
  "error": "missing Authorization: Bearer <klucz z panelu Ustawienia>"
}
401 · Unknown or rotated key
{
  "error": "invalid key"
}
403 · The key lacks conversations:read
{
  "error": "Klucz nie ma uprawnienia conversations:read. Placówka nadaje je w panelu: Ustawienia › Integracje › Klucz API.",
  "code": "missing_scope",
  "scope": "conversations:read"
}
404 · Unknown id, another clinic's conversation or an archived lead's
{
  "error": "Nie ma takiej rozmowy.",
  "code": "not_found"
}
429 · Over 120 requests in this minute
{
  "error": "przekroczono limit 120 zapytań/min"
}

Rate limit

  • 120 requests per minute per key, shared by every endpoint.
  • Every response to a valid key carries RateLimit-Remaining and RateLimit-Reset; see Rate limits.

SDK method

client.listMessages(conversationId: string, params?: { cursor?, limit? }): Promise<MessageList>

The TypeScript tab above uses it. Install and errors: TypeScript SDK.