Mark Reply Handled
li_mark_reply_handledRecord that a person DEALT WITH this conversation. Call it after you answer a reply, or to close one you are not going to answer.
It is no longer what empties li_replies_to_answer — that queue is derived from the thread, so an answer sent with li_send_reply drops the row once the send lands. What this still does, and nothing else does: it writes the conversation down as handled, which is what makes the contact stop reading "needs reply" on their dossier and in the campaign, takes them out of the reply-rate numerator, and puts a dated line with your note on their timeline. It is also the only way out for a thread the queue cannot read — an answer typed by hand in LinkedIn (nothing re-reads that thread), a reply sent from a different account than the one that campaign uses, or a send that reported a failure after the message had in fact gone out.
It says NOTHING about how the conversation went — that is li_mark_outcome (won / meeting_booked / interested / not_interested / no_outcome), and marking an outcome does this as well, so use that one instead whenever you already know the verdict.
If they write AGAIN after you mark this, the conversation REOPENS on its own: the inbox sweep (about hourly) still watches a handled thread for new messages from them, puts it back in li_replies_to_answer with reopened, and li_list_conversations(onlyNeedsReply) lists it again. ⚠️ Still NOT for "not right now" — nothing brings a handled conversation back on a DATE. Use li_snooze_reply for that.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| note | No | Optional note for the contact timeline, e.g. what you answered | |
| contactId | No | One contact by id (from li_contact_dossier or li_campaign_contacts), instead of profileUrl | |
| messageId | No | The exact message row, when you already have it from a dossier or a queue read. | |
| sessionId | No | The account this conversation is on. Only used when the person is in NO campaign: then a light record is created on this account so the mark has something to act on. Needed only when you have more than one account. | |
| campaignId | No | Which campaign membership to act on. A contact can be in more than one campaign, and without this the row is whichever was touched last — so stopping them in one campaign while leaving the other running was not possible. Pass it whenever the contact might be in two. | |
| profileUrl | No | One contact, by profile URL | |
| profileUrls | No | Several contacts in ONE call, max 200. Each is resolved and marked independently: one refusal does not stop the rest, and the reply reports every one by URL. | |
| sessionLabel | No | Same, by account label | |
| conversationUrn | No | The thread, straight from li_list_conversations (single-person form). Recorded on the conversation so the live inbox recognises it as decided. On its own it finds the person only when their thread is already stored — pass profileUrl (the participantProfileId / ACoAA… URL) too. | |
| participantName | No | Their name from li_list_conversations — kept on a newly recorded contact. |