# Get a conversation

`GET https://app.pozyskajpacjenta.pl/api/v1/conversations/{id}` · operationId `getConversation` · since 1.14.0 · tag Conversations

One conversation with its patient, the channels a message can go out on now (and why not, for the others), and the clinic's reply templates filled in for this patient (empty when the clinic does not use templates). Use it before POST /conversations/{id}/messages to pick a channel that will be accepted. 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

Authorization: `Bearer <the clinic's key>`.

### Path parameters

- `id` (`string`, required): The conversation id (`conversationId` of webhook events).

### cURL

```bash
curl "https://app.pozyskajpacjenta.pl/api/v1/conversations/Vb3nQ8sLk2PzX5wRt9YcE" \
  -H "Authorization: Bearer $PP_API_KEY"
```

### TypeScript

```ts
import { PozyskajPacjentaClient } from "@pozyskajpacjenta/sdk";

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

const { conversation, channels, templates } = await client.getConversation(
  "Vb3nQ8sLk2PzX5wRt9YcE",
);
```

### PHP

```php
<?php
$response = wp_remote_get(
    'https://app.pozyskajpacjenta.pl/api/v1/conversations/Vb3nQ8sLk2PzX5wRt9YcE',
    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

### 200: The conversation.

- `conversation` (`Conversation`, required): The conversation.
  - `id` (`string`, required): Conversation id.
  - `status` (`string`, required): open or closed. The clinic closes a conversation in its inbox; a new message from the patient opens it again. One of `open`, `closed`.
  - `lead` (`ConversationLead`, required): The patient.
    - `id` (`string`, required): The lead id: the `leadId` POST /leads returns and webhook events carry.
    - `name` (`string | null`, required): The patient's name; null when unknown.
    - `phone` (`string | null`, required): The patient's phone; null when unknown.
    - `email` (`string | null`, required): The patient's e-mail; null when unknown.
    - `message` (`string | null`, required): The enquiry the patient sent: a form's message or the first chat message. null when there was none.
    - `source` (`string`, required): Where the lead came from: form, embed, api, manual, inbound or chat.
    - `stage` (`string`, required): The lead's stage in the clinic's CRM, e.g. new, scheduled, visited, not_interested.
    - `locationId` (`string | null`, required): The clinic location the enquiry is for (GET /locations); null when not known.
    - `createdAt` (`string (date-time)`, required): When the lead was created.
  - `lastChannel` (`string | null`, required): Channel of the newest message: email, sms, whatsapp, instagram or chat (the chat on the clinic's site). null before the first message. One of `email`, `sms`, `whatsapp`, `instagram`, `chat`.
  - `lastMessageAt` (`string (date-time) | null`, required): Time of the newest message; null before the first one.
  - `lastInboundAt` (`string (date-time) | null`, required): Time of the patient's newest message; null when the patient has not written.
  - `unreadCount` (`integer`, required): The patient's messages nobody at the clinic has opened yet.
  - `createdAt` (`string (date-time)`, required): When the conversation began.
  - `updatedAt` (`string (date-time)`, required): The later of the conversation's last change (a message, a read, open or closed) and the lead's (stage, contact data). The `updated_since` filter compares with it; delivery receipts do not change it.
- `channels` (`ConversationChannelState[]`, required): Every channel, in a fixed order, with whether a message can go out on it now.
  - `channel` (`string`, required): The channel: email, sms, whatsapp, instagram or chat (the chat on the clinic's site). One of `email`, `sms`, `whatsapp`, `instagram`, `chat`.
  - `available` (`boolean`, required): true when a message sent now would be accepted.
  - `reason` (`string | null`, required): Why not, when `available` is false: the code a send would get in its 409 (see SendRefused). null when available. One of `lead_archived`, `opted_out`, `no_email`, `email_domain_not_configured`, `no_phone`, `no_smsapi_token`, `chat_not_started`, `meta_platform_disabled`, `wa_not_configured`, `wa_window_closed`, `ig_not_configured`, `ig_no_user_id`, `ig_no_user_thread`, `ig_window_closed`, `template_not_found`, `template_channel`.
- `templates` (`ConversationTemplate[]`, required): The clinic's reply templates, filled in for this patient.
  - `id` (`string`, required): Template id: the `templateId` of POST /conversations/{id}/messages.
  - `name` (`string`, required): The template's name in the clinic's inbox.
  - `text` (`string`, required): The text the patient would get.
  - `channels` (`string[] | null`, required): The channels the template suits; null means every channel. One of `email`, `sms`, `whatsapp`, `instagram`, `chat`.

Example (A conversation: SMS available, e-mail opted out (templates trimmed to two)):

```json
{
  "conversation": {
    "id": "Vb3nQ8sLk2PzX5wRt9YcE",
    "status": "open",
    "lead": {
      "id": "rS2bIhedVSStSQLc7DL_T",
      "name": "Anna Kowalska",
      "phone": "+48 600 100 200",
      "email": "anna.kowalska@example.com",
      "message": "Proszę o kontakt w sprawie higienizacji.",
      "source": "form",
      "stage": "scheduled",
      "locationId": "loc_wieliczka",
      "createdAt": "2026-10-12T07:41:09.000Z"
    },
    "lastChannel": "sms",
    "lastMessageAt": "2026-10-12T08:02:44.000Z",
    "lastInboundAt": "2026-10-12T08:02:44.000Z",
    "unreadCount": 1,
    "createdAt": "2026-10-12T07:52:10.000Z",
    "updatedAt": "2026-10-12T08:02:44.000Z"
  },
  "channels": [
    {
      "channel": "email",
      "available": false,
      "reason": "opted_out"
    },
    {
      "channel": "sms",
      "available": true,
      "reason": null
    },
    {
      "channel": "whatsapp",
      "available": false,
      "reason": "wa_window_closed"
    },
    {
      "channel": "instagram",
      "available": false,
      "reason": "ig_not_configured"
    },
    {
      "channel": "chat",
      "available": false,
      "reason": "chat_not_started"
    }
  ],
  "templates": [
    {
      "id": "nHv4l_ALArlouEEfxHLOO",
      "name": "Rezerwacja online",
      "text": "Dzień dobry Anna, wolne terminy i rezerwacja online: https://wzorcowa.pozyskajpacjenta.pl Klinika Wzorcowa",
      "channels": null
    },
    {
      "id": "Olz1kaJ9PjjlsZXlBtly3",
      "name": "Jak do nas trafić",
      "text": "Zapraszamy: ul. Przykładowa 12, 00-950 Warszawa. W razie pytań prosimy dzwonić: +48 22 100 20 30. Klinika Wzorcowa",
      "channels": null
    }
  ]
}
```

## Errors

| Status | code | When |
| --- | --- | --- |
| 401 |  | No Authorization header |
| 401 |  | Unknown or rotated key |
| 403 | `missing_scope` | The key lacks conversations:read |
| 404 | `not_found` | Unknown id, another clinic's conversation or an archived lead's |
| 429 |  | Over 120 requests in this minute |

401 (No Authorization header):

```json
{
  "error": "missing Authorization: Bearer <klucz z panelu Ustawienia>"
}
```

401 (Unknown or rotated key):

```json
{
  "error": "invalid key"
}
```

403 (The key lacks conversations:read):

```json
{
  "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):

```json
{
  "error": "Nie ma takiej rozmowy.",
  "code": "not_found"
}
```

429 (Over 120 requests in this minute):

```json
{
  "error": "przekroczono limit 120 zapytań/min"
}
```

## Rate limit

- 120 requests per minute per key, shared by every endpoint.

## SDK method

`client.getConversation(id: string): Promise<ConversationDetail>`

Throws ApiError 404 for an unknown conversation; 403 without the scope.
