intercom api "conversation already closed" on reopen
A guide to handling the Intercom "conversation already closed" API error when reopening, in the business-apis-integrations category: conversation state transitions, the correct reopen call, and state checks. Use when reply or reopen calls fail on closed conversations, or when building agents that act on Intercom conversations. Not for Intercom inbox UI, conversation assignment, or close-reason analytics.
TL;DR
"Conversation already closed" fires when you send a reply-type call against a closed conversation instead of a state-changing call. Reopening is a state transition, not a message: call the open/state endpoint first, then send the reply as a separate call. Check state before acting and your agent stops tripping over closed conversations.
The query
intercom api "conversation already closed" on reopenUse this when
- Reopen attempts fail with "already closed"
- Agents cannot reply to closed conversations via API
- You are building Intercom conversation automations
- Closed conversations need follow-up messages
Not for
- Working the Intercom inbox UI
- Assigning conversations
- Analyzing close reasons
- Conversation ratings
Steps
1. Separate the state change from the message
Reopening takes two calls: first transition the conversation to open, then post the reply. Combining them into one reply call is what produces the error. Model every closed-conversation interaction as state-then-message.
Expected output: reopen flows using two distinct calls.
2. Read conversation state before acting
Fetch the conversation and check its open/closed state before deciding which calls to make. Blind reply attempts against unknown state are the whole bug class. State first, action second.
Expected output: state read on every automated conversation action.
3. Handle the already-open case gracefully
If the conversation is already open, skip the state call and just reply. Reopen logic that assumes closed will error in the other direction. Both branches must exist.
Expected output: idempotent reopen handling for either state.
4. Serialize state changes and messages
Do not fire the open call and the reply concurrently; the reply can land before the state change applies and fail. Await the state transition, confirm it, then send. Ordering is load-bearing.
Expected output: ordered, confirmed state-then-message sequences.
5. Log state transitions for audit
Record who or what reopened each conversation and when. Reopens are customer-visible events; unexplained reopens erode trust. The log also debugs "it reopened itself" reports.
Expected output: an auditable reopen trail.
Template: the checklist
Intercom reopen handling:
[ ] State transition separated from the reply message
[ ] Conversation state read before acting
[ ] Already-open branch handled without error
[ ] State change awaited and confirmed before reply
[ ] Reopen events logged with actor and timeVariant phrasings
reopen closed intercom conversation api
Steps 1 and 2. State change first, then message.
reply to closed conversation fails
Steps 1 and 4. Two calls, ordered.
conversation already closed error
Steps 2 and 3. Check state, handle both branches.
Why it happens
Intercom models "closed" as a real state with real guards, not as a label. The reply endpoint enforces the guard because replying to a closed conversation would silently resurrect it without intent. The API is forcing you to be explicit about reopening, which is correct behavior wearing an error's clothes.
Edge cases
- Conversations closed by the customer: reopening may be unwanted. Check close source before auto-reopening.
- Snoozed versus closed: distinct states with distinct transitions. Do not treat them the same.
- Bulk reopen jobs: state-check each conversation; bulk blind reopens recreate this error at scale.
- Webhook-driven reopens: a close webhook arriving after your reopen needs ordering logic, or the conversation flaps.
Provenance
Resolved from the public thread: https://vectle.com/posts/pstn-cNOK7aLB8nwHIRT1qrw