All endpoints

List inbox conversations

GEThttps://myagentmail.com/linkedin/conversations

Returns the most recent ~20 conversations on the connected account.

Response shape — read this before parsing

The response returns two parallel views of the people in each thread:

  • participants[] — preferred. Already enriched with name, slug, and headline extracted from the LinkedIn payload server- side, with zero extra API calls. Use these for rendering.
  • participantUrns[] — back-compat, URN strings only.

There is no participant.name at the top level, no peer, no otherPerson, no lastMessage.snippet, no last_message field. If you normalise against those, every contact renders as "(unnamed)".

Field map (exact names, camelCase):

  • conversationUrnurn:li:msg_conversation:(...). Pass this to GET /linkedin/conversations/{conversationUrn}/messages. Always URL-encode when used as a path parameter.
  • participants[] — Enriched: { urn, name, slug, headline }. Any of name/slug/headline may be null (deleted accounts, restricted profiles), but urn is always present.
  • participantUrns[] — Mirror of participants[].urn. Kept for back-compat with clients written before the enrichment landed.
  • title — Group chat title only. Null on 1-on-1 conversations. Don't fall back to this for the contact name; use participants instead.
  • lastMessage.text — Plain text body. Not snippet, not preview, not bodyText.
  • lastMessage.senderName — Display name of the sender of the latest message. Already resolved server-side; null only when LinkedIn omits the inline profile.
  • lastMessage.senderUrn — URN of the same sender.
  • lastActivityAt, lastReadAt, lastMessage.deliveredAt — Unix ms, not seconds. Nullable for system-initiated threads.

Worked example response

{
  "ok": true,
  "conversations": [
    {
      "conversationUrn": "urn:li:msg_conversation:(urn:li:fsd_profile:ACoAAA…,2-MWE…)",
      "backendUrn": "urn:li:fs_conversation:2-MWE…",
      "isGroup": false,
      "title": null,
      "lastActivityAt": 1715990400000,
      "lastReadAt": 1715990405000,
      "unreadCount": 1,
      "read": false,
      "participants": [
        {
          "urn": "urn:li:fsd_profile:ACoAAA…aaaa",
          "name": "Jane Doe",
          "slug": "jane-doe-1a2b3c",
          "headline": "Head of Sales at Acme"
        },
        {
          "urn": "urn:li:fsd_profile:ACoAAA…me",
          "name": "Me",
          "slug": "me-1a2b3c",
          "headline": null
        }
      ],
      "participantUrns": [
        "urn:li:fsd_profile:ACoAAA…aaaa",
        "urn:li:fsd_profile:ACoAAA…me"
      ],
      "lastMessage": {
        "messageUrn": "urn:li:msg_message:(urn:li:fsd_profile:ACoAAA…,2-MWE…)",
        "text": "Sure, happy to chat — Tuesday at 2pm work?",
        "senderUrn": "urn:li:fsd_profile:ACoAAA…aaaa",
        "senderName": "Jane Doe",
        "deliveredAt": 1715990400000
      }
    }
  ]
}

Rendering the contact name (1-on-1 thread)

Filter your own viewer URN out of participants, then read name directly. No profile-lookup round-trip needed:

const { conversations } = await client.linkedinListConversations({ sessionId });
const viewerUrn = (await client.linkedinGetSession({ id: sessionId })).viewerProfileUrn;

for (const c of conversations) {
  const other = c.participants.find(p => p.urn !== viewerUrn);
  const displayName = other?.name
    ?? (c.isGroup && c.title)
    ?? "(unknown)";
  // …render
}

For group chats, prefer title; if absent (rare), join the other participants' names with commas. For the rare case where participants[i].name is null (deleted / restricted), fall back to POST /linkedin/profile/lookup with the URN — but you'll only need that on a handful of edge cases, not every conversation.

Query parameters

sessionId
required
string

Responses

200application/jsonArray of conversations.
ok
boolean
conversations
object[]
conversationUrn
string

`urn:li:msg_conversation:(…)`. URL-encode when used as a path parameter.

backendUrn
string

Internal backend ref. Not usable as a path param.

isGroup
boolean

True for 3+ participants.

title
string

Group chat title. **Null on 1-on-1 conversations** — don't display as the contact name.

lastActivityAt
integer

Unix **ms** (not seconds). Time of the most recent message or system event.

lastReadAt
integer

Unix ms when the viewer last read this thread.

unreadCount
integer

Messages the viewer hasn't read yet.

read
boolean
participants
object[]

Enriched participant list — extracted server-side from the same Voyager payload, so no extra API calls or `profile_lookup` budget is spent. Includes the viewer themselves; filter them out by comparing each URN against the viewer URN (available via GET /linkedin/sessions/{id}). For the rare null `name` (deleted / restricted accounts), fall back to POST /linkedin/profile/lookup with the URN.

urn
string

`urn:li:fsd_profile:xxxx`.

name
string

Display name, typically `"First Last"`. Null when LinkedIn omits the inline profile.

slug
string

`linkedin.com/in/<slug>` segment when LinkedIn includes `publicIdentifier` inline; otherwise the trailing URN token as a fallback (opaque but stable for keying).

headline
string

One-line title shown next to the participant on LinkedIn.

participantUrns
string[]

URN-only list, mirror of `participants[].urn`. Retained for back-compat with clients written before the enrichment landed — prefer `participants` for new code.

lastMessage
object

Null when LinkedIn has no rendered preview (rare — system threads).

messageUrn
string
text
string

Plain text. Not `snippet` / `preview` / `bodyText`.

senderUrn
string

URN of the sender.

senderName
string

Display name of the sender of the latest message, resolved server-side from the same Voyager payload. Null when LinkedIn omits the inline profile (rare).

deliveredAt
integer

Unix ms.

Authentication

Send your API key in the X-API-Key header (or Authorization: Bearer <key>). Any prefix accepted by this endpoint — tk_, wk_, ak_, or sa_ — is documented in the key prefix table.