Messaging & channels
SMS
The assistant answers texts sent to its phone number, and replies from that same number.
Customers can text the same number they call. The assistant answers in writing, from that number, and each thread is a conversation you can read back through the API.
Overview#
SMS is a two-way text channel on a Twilio number already linked to an assistant. Someone texts that number, the assistant replies from it, and the exchange is stored as a conversation with channel set to sms. Voice calls on the number keep working as before.
- Answer the number people already have. A text to the business line gets a reply from the assistant, instead of sitting unread.
- Use the assistant you already configured. Texts are handled by the assistant on that number. If it has a chat prompt (
chatPromptId), that prompt is used. Otherwise the voice prompt is used. A chat prompt is not required to turn SMS on. - Read every thread afterwards. Each exchange is a conversation you can list, open, and export.
- Get a webhook when a thread starts and ends. SMS uses the same messaging webhooks as web chat, with
channelset tosms.
This channel does not send a text during a voice call. That is SMS reasons: a fixed message sent to someone who is still on the phone. Those texts show up on the call record. They do not create an SMS conversation, and turning this channel on does not enable them.
Enable or disable SMS#
SMS is off until you turn it on for that assistant. Link a Twilio number first by setting phoneNumberId on the assistant (Phone numbers). You cannot set the SMS flag on POST /assistants or PATCH /assistants/{id}. This route is the only write.
curl -X PATCH https://core-api.heysadie.ai/assistants/0195f1e2-0000-0000-0000-000000000000/sms-enabled \
-H "Authorization: ApiKey YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "smsEnabled": true }'smsEnabled: true turns the channel on. false turns it off. The request body field is camel case. The flag in the response is sms_enabled.
A 200 means the channel is on. Enabling attaches the number before the flag is written, so sms_enabled: true only comes back after that attach succeeds. The data object is only id and featureFlags, not the rest of the assistant. Flags you did not change are still included.
{
"success": true,
"data": {
"id": "0195f1e2-0000-0000-0000-000000000000",
"featureFlags": {
"sms_enabled": true
}
},
"metadata": {
"timestamp": "2026-07-30T12:00:00.000Z",
"version": "1.0",
"path": "/assistants/0195f1e2-0000-0000-0000-000000000000/sms-enabled"
}
}Read the flag back from this response, or from GET /assistants/{id}. The assistant list does not include featureFlags.
Enabling needs a Twilio number
If the assistant has no linked phone number, the request fails with 400 and error.code NO_PHONE_NUMBER_LINKED. If the linked number is not a Twilio number, it fails with 400 and NON_TWILIO_PROVIDER. Either way the flag is left unchanged.
Turning SMS off only clears sms_enabled. The number stays registered for messaging, so a later enable does not register it with the carrier again.
While the flag is off, a text to the number gets no reply, and OnCore does not open a conversation for it. That includes a thread that was already open: the next text is ignored.
What a text conversation does#
Replies come from the number the customer texted. They do not come from a separate OnCore sender, and they do not change based on the customer's country.
The first text in a new conversation does not get a model answer. The customer receives the assistant's opening line (firstMessage), and their text is stored on the thread. The model answers the following text. If they send several texts before that reply goes out, those texts are answered once, as a single reply. The one exception is a text sent shortly after a thread ended, described below.
A conversation starts when someone texts the number. You read it afterwards with Conversations: GET /conversations?channel=sms, GET /conversations/{id}, and GET /conversations/export?channel=sms (up to 10,000 rows).
To send a text yourself, from a number on your tenant, use Send an SMS (POST /sms). That send does not start one of these conversations, and it is not an SMS reason.
A thread ends when the customer says goodbye, when the assistant ends it, or after a quiet period with no new text from the customer. That wait is not a published number. OnCore POSTs an assistant-request when the thread starts and an end-of-conversation-report when it ends. Both use channel: "sms". The end event's ended_reason is conversation-ended-by-user, conversation-ended-by-agent, or conversation-idle-timeout. See End-of-conversation report.
When the customer texts again right after a goodbye#
Customers often answer the assistant's goodbye. For a short window after the customer or the assistant ends a thread, the next text is handled like this:
- A short goodbye such as "thanks, you too!", "ok" or 👍 gets no reply and does not open a new conversation, so no extra webhooks fire.
- Anything else, including "hi" or a question, opens a new conversation straight away. The model answers it directly instead of sending the opening line, and it sees the last few messages of the previous conversation. A text like "no, tomorrow evening" or "yes" is read as a follow-up to that exchange, and a "hi" gets a reply that picks up where the customer left off rather than the opening line. Those earlier messages are not copied into the new conversation's messages or its report.
A text with a question mark always counts as a real message. Once the window has passed, a new text starts a new conversation with the opening line as usual. A thread closed after the quiet period does not start this window.
Limits & FAQ#
- Only a linked Twilio number can be enabled. Other providers are rejected at enable time with
NON_TWILIO_PROVIDER. - While SMS is off, inbound texts are ignored. No error text is sent back.
- The assistant cannot transfer a text thread to a person. Transfers apply to voice calls. See Transfers.
- SMS reasons are independent of this flag. You can text someone during a call without enabling the channel, and you can answer inbound SMS without any SMS reasons.
Do we need our own number? Yes. Replies come from a Twilio number linked to the assistant. This channel has no shared OnCore sender.
Can we text someone who has not texted us? Yes. Send an SMS (POST /sms) sends from a number on your tenant. That is not this channel, and it does not open a conversation. To text someone who is on a phone call, use SMS reasons.
What if enabling fails? Set phoneNumberId to a Twilio number on the assistant, then retry. NO_PHONE_NUMBER_LINKED means there is no number. NON_TWILIO_PROVIDER means the linked number is not Twilio. The flag is left as it was.
Next steps#
- Conversations: list and export SMS threads.
- End-of-conversation report: receive each thread when it starts and ends.
- Send an SMS: text someone from a number on your tenant.
- SMS reasons: send a fixed text during a voice call.