A conversation gathers every message exchanged with one number, in order, like the thread of a messaging app on a phone. The Conversations screen is your shared SMS inbox: several people can read and answer from their own browser, and each sees the others' changes live.
Typical uses: answering customers who reply to a campaign, a support line on a real mobile number, following up an order confirmation that raised a question.
How a conversation is born
There is exactly one conversation per number. It is created the first time a message is sent to that number or received from it, whatever the way (quick send, campaign, API, automatic reply). A message from a number you already talked to joins the existing thread.
A service that writes from a short code or a name (a bank, a payment service, 8080) is not
recorded by default: those senders are refused, and named in the journal so you can see them. To
follow one, record it in Settings, Reception, where the services already seen on your SIM cards
are offered as a list to pick from (see Settings). Such a
conversation reads like any other, but nothing can be sent back to it.
A conversation is not a contact. It exists as soon as a message is exchanged, even with a number that is not in your directory. You can create the contact from the conversation in one click (see The contact panel).
The list
The left column lists the conversations, pinned first, then the most recently active. Each shows the number or the contact's name, the last message, its time, and the number of unread messages.
Above it, a single line: the search field, and a Filters button carrying the number of filters in use. The filters open in a panel, and each one in use comes back as a chip under the search field. Click a chip to drop that filter alone, or Clear all filters to start over.
| Control | Where | Use |
|---|---|---|
| Search | The field | Find a thread by number or by words from its messages |
| Thread state | Filters panel | Show only Open, Pending or Resolved threads |
| Unread only | Filters panel | Show only threads with messages nobody opened yet |
| Archived | Filters panel | Show the archived threads instead of the others |
| Assigned to me | Filters panel | Show only the threads assigned to you |
| Label | Filters panel | Show only the threads carrying a label |
Opening a thread always shows it, whatever the filters: a thread opened from the Unread only or Archived list appears on the right and loses its unread badge, exactly as it would from the full list. If a thread has been deleted since a link to it was shared, the right panel says so and offers to go back to the list.
The list and the unread counters update live, without reloading: a message received while you are on the screen appears at once.
Read and sort a thread
Click a conversation to open it. Opening it marks it as read for everyone. Scroll up, or click Load older history, to go further back.
Above the thread:
| Action | Effect |
|---|---|
| Thread state | Open (to handle), Pending (waiting for something, for example the customer's answer), Resolved (done). Use it as a to-do list shared by the team |
| Pin this thread / Unpin this thread | A pinned thread stays at the top of the list |
| Archive this thread / Move out of archives | An archived thread leaves the main list. If the correspondent writes again, it comes back by itself |
Under each message you see its time and, for an outbound message, its status. A failed message shows its reason and a Retry button (see Sending messages).
Delete a message
Each message carries a menu (the three dots beside it, shown on hover and always on a phone) with Delete. Deleting is permanent and covers this gateway: the message leaves the conversation, the history, the searches and the exports. The other messages of the thread stay, the thread keeps its place, and its unread counter is recomputed.
The copy kept by the phone is not touched. Android only lets the phone's default SMS application erase an SMS, and Selfhostsms is not one: it sends and receives without that role, and asking for it would take the messaging of your phone away from the app you actually use. If you also want the SMS gone from the handset, erase it there, in its Messages app.
Three things a deletion cannot do: bring back a message deleted by mistake, take back an SMS already delivered to your correspondent, and erase the copy the phone keeps. Deleting a message that is still queued cancels it first, so it never leaves.
Deleting publishes the message.deleted webhook event, and every deletion
is written to the journal.
Labels and assignment
Threads can carry labels (for example "invoice", "complaint") and be assigned to a user. The list shows the first labels of each thread and the header shows "Assigned to" its user; the Label and Assigned to me filters use them.
In the current version, labels are applied by the automation rules or
through the API, and assignment through the API (PATCH /conversations/{conversationId}, fields
labels and assignedTo). The dashboard shows them and filters on them, but does not edit them yet.
Reply
Type your message at the bottom of the thread and click Send. The composer offers:
| Field | Default | Effect |
|---|---|---|
| Message to send | The draft kept for this thread | Your text. The counter shows the characters, the number of SMS and the encoding, as in quick send |
| Sending device | Automatic, phone first: the conversation's phone is preferred | Leave it on Automatic in almost every case. Choosing a phone forces it: the reply leaves from that phone or not at all |
| Sending SIM | Automatic; the conversation's SIM when you choose the conversation's phone | Which SIM of the chosen phone. Available once a phone is chosen |
| Send date and time | Empty (now) | Schedules the reply, in the platform time zone |
| Quick replies | None | Type / at the start of the message to insert one of your templates |
Why the reply keeps the same SIM. The gateway remembers which phone and SIM last received a message from this correspondent. On Automatic, the reply leaves from that SIM whenever it can send, so your customer always sees you answer from the number they wrote to; a reply from another number would look like a stranger, or be ignored. The routing rules do not change the SIM of an existing conversation. The first option of Sending device names that phone: "Automatic, Office phone first".
When the conversation's phone is offline. On Automatic, the reply does not wait for it: another available phone sends it at once, following your routing. Your customer then sees it come from another number, which beats a reply that never arrives. As soon as the conversation's phone is back, the next replies leave from its number again.
Forcing a phone. Choose a phone in Sending device only when the reply must leave from it and from no other. Choosing the conversation's phone also selects its SIM. A forced phone is an order, not a preference: while it is offline, the reply stays Queued, is retried, and fails if the phone does not come back before its attempts run out. The choice applies to the thread you are in; the next thread opens on Automatic again.
Unsent text is kept as a draft for each thread, in your browser: you can switch threads and come back to it. Replies are never held by the night pause of campaigns.
The contact panel
The panel on the right shows who you are talking to (open it with Open contact details):
- Unknown number: the number is not in your directory. Create the contact adds it in one click; you can then complete it in Contacts.
- Internal notes: free text for your team, visible here only and never sent to anyone.
- Groups, with Add to a group.
- Labels and Custom fields of the contact.
- Opt out / Opt back in: stops or allows every send to this number. See Contacts and groups.
- Export thread as CSV: downloads the messages of the thread loaded on screen. Load the older history first for a complete export.
A correspondent who answers STOP is opted out automatically, and nothing more can be sent to them
until they are opted back in.
Options
| Option | Where | Default | Allowed values | Effect |
|---|---|---|---|---|
| State | Thread header; API state |
Open | open, pending, resolved |
Sorting for the team, and the Thread state filter |
| Pinned | Thread header; API pinned |
Off | On or off | Pinned threads come first in the list |
| Archived | Thread header; API archived |
Off | On or off | Hidden from the main list; a new inbound message unarchives the thread |
| Labels | API labels, automation rules |
None | Up to 12, 40 characters each, stored in lowercase | Label filter. Different from the labels of a contact |
| Assigned to | API assignedTo (null to unassign) |
Nobody | A user of the gateway | Assigned to me filter |
| Linked contact | API contactId |
The contact with this number, if any | A contact | Which record the panel shows |
| Read | Opening the thread; API POST /conversations/{conversationId}/read |
Unread when a message arrives | None | Clears the unread counter for every user |
In PATCH /conversations/{conversationId}, a field left out is not changed, and a field set to
null is cleared: that is how you unassign a thread without touching the rest.
API
| Method and path | Use |
|---|---|
GET /conversations |
List the threads. Filters q, state, assignedTo, label, unread, archived; pages with limit and cursor |
GET /conversations/{conversationId} |
Read one thread |
PATCH /conversations/{conversationId} |
Change state, assignment, linked contact, labels, pinning, archive |
POST /conversations/{conversationId}/read |
Mark as read |
GET /messages?conversationId=... |
The messages of a thread |
POST /messages |
Reply: send to the conversation's number |
Troubleshooting
| Symptom | What to check |
|---|---|
| A reply stays Queued, then fails | A phone was forced in Sending device and it is offline. Set it back to Automatic, or bring the phone back. On Automatic, check that at least one phone is Online |
| A reply left from another number | The conversation's phone was offline or could not send (quota, cadence): on Automatic, another phone took over. Bring it back online |
| "This number has opted out." | The correspondent sent STOP, or was opted out by hand. Opt them back in only if they asked for it |
| A conversation disappeared | It was archived: open Filters and turn on Archived |
| The list does not update live | The live indicator in the header is off: check the connection to the gateway, then reload the page |
| A received SMS does not appear | The phone that received it is offline, or its app is asleep. The phone keeps what it received and hands it over when it reconnects: see Devices |