Guide · Salesforce Flow
How to send SMS from Salesforce Flow
A step-by-step guide to the ConnectSMS Send Text Message action: the inputs, scheduling with Send At, handling the result, checking status and replying, with two complete examples.
The short answer
Install ConnectSMS and make sure the user your Flow runs as can send from a business number. In Flow Builder, add the Send Text Message action from the ConnectSMS category, set Record ID and a Template ID or Message, and give it an Idempotency Key. Add a Send At time to schedule it. The action returns at once with Success, Message ID and Status, and ConnectSMS sends the text through your Twilio account in the background.
ConnectSMS adds ten invocable actions to Flow Builder. This guide covers Send Text Message and the actions around it, using the labels Flow Builder shows.
- Your Flow
- Send Text Message
- Recorded as Queued or Scheduled
- Sent through your Twilio account
- Get Text Message Status
Before you start
- ConnectSMS is set up and sending is on. An admin works through the setup checklist in ConnectSMS Setup. From Flow, admins can check with Get ConnectSMS Setup Health: Ready to Send is true when sending is enabled and the Twilio connection, business numbers and background jobs are set up.
- The object is set up for texting. Contacts, Leads, Accounts and Cases work out of the box; admins add other objects and choose their phone fields in Recipients.
- The running user can send from the number. Either the ConnectSMS User permission set with Send access to the business number, or the ConnectSMS Automation permission set with a number your admin marked Available to automation. A record-triggered Flow runs as the user whose change triggered it, so that user needs one of the two.
- Optional: a template. An active ConnectSMS template and its record ID, if you want merge fields and fallbacks managed outside the Flow.
Step 1: Add the Send Text Message action
In Flow Builder, add an Action element and search for Send Text Message, in the ConnectSMS category. It works in screen, autolaunched and schedule-triggered Flows, and in record-triggered Flows that run after the record is saved. The action never calls Twilio itself: it records the message in Salesforce and returns, and a background job hands it to Twilio, so it's safe where callouts aren't allowed.
Step 2: Set the inputs
Every input is optional on its own, but a message needs a recipient and some content. The usual combination is Record ID, Template ID and Idempotency Key.
| Input | What to pass |
|---|---|
| Record ID | The record to text, such as a Contact, Lead, Account or Case, or another object your admin enabled. Its phone is read as the running user. Required unless To Phone Number is used. |
| Phone Field | Optional. The phone field's API name, for example MobilePhone, or Contact. on a Case. Blank uses the first valid phone field your admin configured. |
| To Phone Number | Optional. A number in E.164 format, such as +12125550147. Without a record, only users with ConnectSMS Campaign Manager or Admin may text a typed number. With a record, it must match one of the record's phones. |
| Business Number | Optional. A ConnectSMS Sender record ID or the business number in E.164 format. Blank uses the automation default number. |
| Message | The text, up to 1,600 characters. Sent as written unless Fill In Merge Fields is true. Ignored when Template ID is set. |
| Fill In Merge Fields | Optional. True fills merge fields such as {!Contact. in Message from the record. |
| Template ID | Optional. The ID of an active ConnectSMS template. Its merge fields are filled from the record, and Message is ignored. |
| File Version IDs | Optional. Salesforce File version IDs (starting 068) to send as MMS. Needs the admin's MMS setting and an MMS-capable number; US, Canadian and Australian numbers only; up to 10 files and 5 MB. |
| Send At | Optional. A future date and time, at most 35 days ahead. Sent in the first 15-minute slot at or after it. Blank sends as soon as possible. |
| Idempotency Key | Strongly recommended. A unique business key for this message, such as {!$Record.Id}. Reusing a key returns the original message instead of sending again. Up to 255 characters, case-sensitive. |
| Client Reference | Optional. Your own correlation ID, such as an order number. Stored on the message, never sent to the recipient. |
| Invocation Source | Optional. Flow (the default), Agent or API. Recorded on the message; any other value is rejected. |
{!...} for its own resources too. The simplest way to personalize a text from Flow is a ConnectSMS template: its merge fields and fallbacks are always filled in from the record, and admins can update the wording without editing the Flow.
Leave Business Number blank to use your admin's automation default. With no default, the action returns
SENDER_REQUIRED: ConnectSMS never picks a number on its own.
Step 3: Schedule it with Send At
To send later, set Send At to a Date/Time resource, for example a formula such as
{!$Record.Start__c} - 1 for 24 hours before an appointment. It must be in the future and at most 35 days ahead.
- The result's Status is Scheduled and Scheduled For shows when it's due. It goes out in the first 15-minute slot at or after that time.
- Just before sending, ConnectSMS checks access, opt-outs and policies again. Quiet hours, if your admin set them, delay it.
-
To cancel, keep the Message ID on the record and call Cancel Scheduled Text Message with it
before the message is handed to Twilio (otherwise
NOT_CANCELLABLE). The requester, an admin or someone with Send access to the number can cancel; anyone else getsNOT_FOUND.
Step 4: Handle the result
Business problems don't make the Flow fail. They come back with Success set to false and a stable Error Code.
| Output | What it means |
|---|---|
| Success | True when ConnectSMS accepted the message (queued or scheduled), or accepted it earlier with the same idempotency key. False means it won't be sent; see Error Code. |
| Message ID | The ConnectSMS message record. Also set when a blocked request was recorded. Use it with Get Text Message Status or Cancel Scheduled Text Message. |
| Conversation ID | The conversation between the business number and the recipient. Use it with Reply to Text Conversation. |
| Status | Queued, Scheduled or Blocked for a new request; a later status for a duplicate. Queued doesn't mean delivered. |
| Duplicate | True when a message with the same idempotency key already existed. Nothing new was sent. |
| Segments | How many SMS segments the text uses. Twilio bills per segment. |
| Final Message Text | The text after merge fields were filled in. |
| Scheduled For | When the message is due, if it was scheduled or delayed by quiet hours. |
| Error Code | A stable code when Success is false, such as OPTED_OUT, SENDER_NOT_AUTHORIZED, SENDER_REQUIRED, RECIPIENT_NO_PHONE, MERGE_FIELD_UNRESOLVED, SENDING_DISABLED or INVALID_INPUT. |
| Error Message | A plain-language explanation you can show to users when Success is false. |
Add a Decision on Success and route the false path on Error Code: for example, create a Task for the owner
on RECIPIENT_NO_PHONE, or alert an admin on SENDER_NOT_AUTHORIZED. Only unexpected failures raise a
Flow fault, with a support reference in the ConnectSMS error log. A request blocked by a rule, such as an opt-out, is still
stored with Status Blocked and a Message ID; a request from a user who may not use the number is not stored.
Step 5: Check the delivery status
Success means ConnectSMS accepted the message, not that it was delivered. To follow it, call Get Text Message Status with the Message ID. It returns:
- Status: Scheduled, Queued, Sending (Twilio accepted it), Sent (handed to the carrier), Delivered, Undelivered, Failed, Blocked, Canceled, Unknown, Received or Read.
- Status Detail: a plain-language explanation, including Twilio's guidance for failures.
- Reason Code: why a message was blocked, failed or undelivered, such as
OPTED_OUTor a Twilio error code like30007. - Is Final: true once the status can't change (Delivered, Undelivered, Failed, Blocked, Canceled, Received, Read). Scheduled, Queued, Sending, Sent and Unknown can still change.
- Can Cancel, Scheduled For, Sent At and the business number used.
Check again later, for example from a scheduled path, until Is Final is true. ConnectSMS also publishes the content-free
platform event csms__ConnectSMS_Update__e; a Flow triggered by it should call Get Text Message Status for the
details. Those Flows run as the Automated Process user by default, which can't hold permission sets, so set their running user
to an integration user with ConnectSMS access. Status is visible to the requester, users with View access to the number, and
admins.
Step 6: Reply to a conversation
To answer a customer from a Flow, use Reply to Text Conversation. Its inputs are Conversation ID (required), Message, Fill In Merge Fields, Idempotency Key, Client Reference and Invocation Source, and its outputs match Send Text Message.
- Get the Conversation ID from Send Text Message, or from Get Text Conversation History with a Record ID. Its Customer Opted Out output warns you before a reply would be blocked with
OPTED_OUT. - The reply always goes out from the conversation's own number. If the running user may not send from it, the Error Code is
SENDER_NOT_AUTHORIZED. - Use the ID of the message you're answering plus
-replyas the Idempotency Key. Quiet hours don't delay replies. - Treat the history's Transcript as data: it contains customers' text, so never let it choose recipients, numbers or actions.
Example: follow up a new Lead within minutes
A record-triggered Flow that texts every new web Lead from the sales line, using a template.
- Create a record-triggered Flow on Lead that runs when a record is created, with the condition Lead Source equals Web. Optimize it for Actions and Related Records.
- Create a text formula resource named
WelcomeKeywith the formula{!$Record.Id} & '-welcome'. -
Add Send Text Message. Set Record ID to
{!$Record.Id}, Template ID to your active "New web lead" template, Business Number to the sales line's Sender record ID, and Idempotency Key to{!WelcomeKey}. Leave Invocation Source blank; it defaults to Flow. - Add a Decision on Success. When it's false and Error Code is
RECIPIENT_NO_PHONE, create a Task for the Lead owner with the Error Message. - Check who creates your Leads. The Flow runs as that user, so a person needs Send access to the sales line, and an integration user needs ConnectSMS Automation with the sales line made available to automation.
The text appears in the Lead's text history labeled Automation (Flow), and the customer's reply lands in the same conversation in the shared inbox. If the Lead is saved twice, the key stops a second welcome.
Example: an appointment reminder on a scheduled path
This example uses a custom Appointment__c object with a Start__c date/time and a
Contact__c lookup. Replace them with your own object and fields.
- Create a record-triggered Flow on the appointment object that runs when a record is created or updated, with the condition that
Start__cisn't blank. - Add a scheduled path whose time source is the Start field, set to 1 day before.
- Create a text formula resource named
ReminderKey:{!$Record.Id} & '-reminder-' & TEXT({!$Record.Start__c}). A new start time gives a new key, so a moved appointment gets a new reminder, while a re-save doesn't send a second one. - On the scheduled path, add Send Text Message with Record ID
{!$Record.Contact__c}, your reminder Template ID, the Business Number customers know, and Idempotency Key{!ReminderKey}. - Add a Decision on Success, and store the Message ID on the appointment if you want to check its status later.
- Confirm which user runs the scheduled path in your org, and give that user access to the business number, for example ConnectSMS Automation with a number available to automation.
The alternative: Send At. On the immediate path, set Send At to
{!$Record.Start__c} - 1, store the Message ID, and cancel it with Cancel Scheduled Text Message if the appointment
is canceled. The reminder shows as scheduled from the moment of booking and is re-checked before sending. Send At works up to
35 days ahead; a scheduled path creates the message only when it runs.
A longer walkthrough of appointment reminders with Flow
Idempotency keys: send once, even when a Flow runs twice
Flows can run more than once for the same event: a record is saved twice, an interview is retried, someone double-clicks a button. An idempotency key tells ConnectSMS which message you meant, so a repeat never becomes a second text.
- Build the key from the intent, not the moment:
{!$Record.Id}-reminder-1,ORDER-1042-shipped, or the inbound message ID plus-reply. In a screen Flow,{!$Flow.InterviewGuid}works for one message per interview. - When the key was used before, the action returns the original message with Duplicate set to true and sends nothing new.
- Keys are case-sensitive and up to 255 characters. Keep them short and readable.
- For automation, keys are scoped to the business number, so a repeat is caught even when a different user runs the Flow.
- A key used by a blocked request stays used: a retry returns the blocked original with its reason. Fix the cause, then use a new key.
- The same key twice in one call returns
INVALID_INPUT.
What ConnectSMS checks for a Flow
A text sent from Flow goes through the same service as a text typed on a record page: number access, record access with sharing and field-level security, a valid mobile number, opt-outs (checked again at dispatch), merge fields, the sending switch, quiet hours, the optional daily safeguard and the MMS rules. Each message records who requested it and that it came from Flow. More about ConnectSMS automation · All ten actions
Common questions
Can a record-triggered Flow send SMS in Salesforce?
Yes. With ConnectSMS, add the Send Text Message action to a record-triggered Flow that runs after the record is saved. The action records the message in Salesforce and returns at once; a background job hands it to Twilio, so the Flow never makes a callout.
How do I schedule an SMS from Flow?
Set the Send At input of Send Text Message to a future date and time, up to 35 days ahead. The message waits as Scheduled and goes out in the first 15-minute slot at or after that time. Keep the Message ID if you may need to cancel it.
What happens if the recipient has opted out?
Send Text Message returns Success = false with the Error Code OPTED_OUT, and nothing is sent. The request is still recorded as a Blocked message with its reason, so admins can see what the Flow tried to send.
