pollInbox

This method polls your monitored inbox to retrieve captured messages and receive new ones across every conversation, for both standard and Sales Navigator inboxes. With personUrl, it returns the whole conversation with one person instead.

This is the default way to read messages. Before polling, enable inbox monitoring once with syncInbox or nvSyncInbox.

typescript
try {
  const { data, errors } = await linkedapi.pollInbox({
    since: "2024-01-01T00:00:00Z", // Optional: only messages after this timestamp
    type: "st",                     // Optional: "st" | "nv"; omit for both
    threadId: "2-abc123..."         // Optional: restrict to a single thread
  });

  // The list of possible execution errors is below
  if (errors && errors.length > 0) {
    console.warn('Workflow completed with execution errors:');
    errors.forEach(error => {
      console.warn(` - Type: ${error.type}, Message: ${error.message}`);
    });
  }

  if (data) {
    console.log(`Retrieved ${data.messages.length} messages`);

    data.messages.forEach(message => {
      const sender = message.sender === 'us' ? 'You' : 'Them';
      console.log(`[${message.type}] ${sender} (${message.time}): ${message.text}`);
    });
  }
} catch (e) {
  // A list of all critical errors can be found here:
  // https://linkedapi.io/sdks/handling-results-and-errors/#handling-critical-errors
  if (e instanceof LinkedApiError) {
    console.error(`Critical Error - Type: ${e.type}, Message: ${e.message}`);
  } else {
    console.error('An unexpected, non-API error occurred:', e);
  }
}

Params

All fields are optional:

  • since – timestamp indicating the starting point for retrieving messages. If not provided, all captured messages are returned.
  • type – enum to filter by inbox type; omit for both:
    • st – standard inbox messages only.
    • nv – Sales Navigator inbox messages only.
  • threadId – restrict the result to a single conversation thread.
  • personUrl – return the conversation with one person instead of the whole inbox. See Polling one person for how this changes the result.

The inbox only captures messages that arrive after monitoring is enabled – unless you ask for one person with personUrl, which also returns history loaded for that person. If inbox monitoring is not enabled on the account, the call still succeeds with an empty messages array.

Data

  • messages – flat array of messages across all threads, ordered newest first.
    • id – unique identifier for the message.
    • type – inbox type the message belongs to (st or nv).
    • threadId – identifier of the conversation thread. Pass it to sendMessage / nvSendMessage to reply into the thread.
    • personUrn – URN of the other participant, or null if LinkedIn does not expose it.
    • personHashedUrl – hashed LinkedIn URL of the other participant. This is the form the inbox exposes; every method that takes a person URL accepts it.
    • personPublicUrl – public LinkedIn URL of the other participant, or null if it has not been resolved. It can be null on any message, including the first one in a thread.
    • personUrl – deprecated, replaced by personHashedUrl, which carries the same value. Still returned so existing integrations keep working; do not use it in new code.
    • sender – enum indicating who sent the message. Possible values:
      • us – message was sent by you (through the LinkedIn UI or the Linked API).
      • them – message was sent by the other person.
    • text – message text.
    • time – timestamp when the message was sent or received.

A person is resolved by the periodic sync, and only when their thread produces a message after monitoring was enabled by syncInbox. personPublicUrl is therefore null for everyone you have not heard from yet, and some people are never resolvable at all – so always handle null rather than assuming a message carries a public URL. Messages captured before this field existed, and people whose resolution did not succeed, stay null until that person sends another message or Linked API learns their public URL another way, for example through fetchPerson. personHashedUrl is always present and is the safe input for follow-up methods.


Recommended flow for integrations:

  1. Leave since empty on the first request to retrieve everything captured so far.
  2. For subsequent requests, pass the timestamp of the most recent message you received as since to fetch only newer messages.
  3. Continue polling with an advancing since. Whenever new messages arrive, update since to the latest message time.

since is inclusive and message times are whole minutes, so the messages at the latest time come back on the next request. Remember their ids and skip them, so you never process – or reply to – the same message twice.

For push-based delivery instead of polling, subscribe to the inbox webhook events.

Polling one person

Pass personUrl to read the whole known conversation with one person. Besides the messages the inbox captured, the result includes that person's earlier history if it was loaded with syncConversation or nvSyncConversation – a message present in both appears once. Loaded history is returned even if inbox monitoring is not enabled on the account.

typescript
try {
  const { data, errors } = await linkedapi.pollInbox({
    personUrl: "https://www.linkedin.com/in/john-doe",
    since: "2024-01-01T00:00:00Z" // Optional: omit to get the full conversation
  });

  // The list of possible execution errors is below
  if (errors && errors.length > 0) {
    console.warn('Workflow completed with execution errors:');
    errors.forEach(error => {
      console.warn(` - Type: ${error.type}, Message: ${error.message}`);
    });
  }

  if (data) {
    data.threads.forEach(thread => {
      console.log(`[${thread.type}] thread ${thread.threadId ?? '(unknown)'}, history from ${thread.historyFrom}, complete: ${thread.historyComplete}`);
    });

    data.messages.forEach(message => {
      const sender = message.sender === 'us' ? 'You' : 'Them';
      console.log(`${sender} (${message.time}): ${message.text}`);
    });
  }
} catch (e) {
  // A list of all critical errors can be found here:
  // https://linkedapi.io/sdks/handling-results-and-errors/#handling-critical-errors
  if (e instanceof LinkedApiError) {
    console.error(`Critical Error - Type: ${e.type}, Message: ${e.message}`);
  } else {
    console.error('An unexpected, non-API error occurred:', e);
  }
}

Params

  • personUrl – public or hashed LinkedIn URL of the person. A hashed URL, standard or Sales Navigator, always matches. A public URL matches only once Linked API knows this person's public URL; if inbox messages from this person carry personPublicUrl: null, pass their personHashedUrl instead. In Python, pass it through InboxPersonPollRequest, so the result is typed as the person view below.
  • since, type and threadId (optional) – work as described above and narrow the messages further. Leave since empty to get the full conversation.

Data

With personUrl, the method returns a different shape:

  • messages – messages exchanged with this person across all their threads, ordered newest first. Each message carries the same fields as above, plus inboxMessageId:
    • id – identifier of the message in this view. It stays the same between calls, including after new messages arrive, but it can differ from the id the same message has without personUrl.
    • inboxMessageId – id of the same message in the result without personUrl, which is also messageId in inbox webhook events, or null if the inbox did not capture this message – for example, history from before monitoring was enabled. Use it to match this view against the messages you have already received from the inbox.
    • threadId – may be null in this view: a thread whose history was loaded through the person's profile keeps threadId: null until Linked API discovers the thread during the syncing period. After syncUntil, the same conversation can appear twice in threads – once with threadId: null (the loaded history, which tells you how far back it goes) and once with the inbox's threadId. To reply to such a person, pass personUrl to sendMessage.
  • threads – every thread with this person that Linked API knows about, listed regardless of since.
    • threadId – identifier of the thread, or null as described above.
    • type – inbox type of the thread (st or nv).
    • personUrn – URN of the person, or null if LinkedIn does not expose it.
    • historyFrom – time of the earliest message Linked API has in this thread, or null if it has none.
    • historyComplete – true only when Linked API has read this thread back to its very first message, so historyFrom is where the conversation starts. false means earlier messages may exist that Linked API has not read; load them once with syncConversation or nvSyncConversation.

If Linked API has no messages with this person, messages is empty; threads can still list a known thread with historyFrom: null.

Messages from the inbox and from the loaded history are matched by sender, minute and text within the same thread, so two identical messages sent in the same minute stay two messages. In rare cases the two copies of one message are recorded with a different minute, and then the message appears twice.

Did this lead reply? Enable inbox monitoring before you send: it captures only messages that arrive after it is turned on. Then call pollInbox with the person's personUrl and since set a few minutes before you sent your message. Message times are whole minutes, so a reply sent in the same minute can carry a time earlier than the exact moment you sent yours. Pass the type of your message (st or nv) and take the earliest message with sender us in the result – the one you sent; later messages of yours, such as follow-ups, must not move this point. Treat a message whose sender is them and whose time is not earlier than it as the reply. If your message is not in the result yet, the periodic sync has not captured it, and the answer is not known yet – not "no reply". A them message in the same minute as yours is ambiguous: with minute precision it may have been sent just before yours. A reply appears only after the periodic sync captures it, so an empty result means there is no reply yet.