Workflow Send SMS

Module-local action for contact events and a deal's primary contact. Company events have no recipient. Production registration belongs to the workflow adoption batch (#5830).

The action has kind: 'send_sms', body, and optional fromNumberId (a reviewed telephony_sms_senders.id belonging to this organization and matching its configured SMS number). Body accepts the existing workflow merge fields and fallbacks; both the template and rendered text must fit SMS_BODY_MAX.

Automatic messages require telephony and SMS enabled, a current contact phone, written marketing consent for that exact phone, no do-not-contact or suppression/STOP/review state, current clear DNC evidence, reviewed sender registration, and available organization/sender caps. A recent inbound message never exempts an automatic message from quiet hours.

Contact timezone takes precedence over the organization's configured outreach business timezone. Organization business and quiet windows narrow the telephony window of 08:00–21:00. Missing or invalid policy fails closed. A closed window returns deferred with the next permitted UTC instant, computed using recipient-local clock checks so DST changes are respected. Dry-run planning renders text and estimates SMS segments without reserving, auditing, writing a timeline entry, or calling the provider.

Delivery uses the existing two-way phone SMS service, ledger, timeline and inbox adapter. The logical request key is workflowStep:<stepId>; the adapter must map it deterministically to the ledger's existing UUID field. An ambiguous or interrupted send stays unknown and must never be replayed. The provider is injected; module tests use only a recording provider.

The existing engine executes transactional CRM segments. External SMS dispatch must use a committed, stable step identity and an independent root database handle after that segment commits. Calling a provider inside a savepoint could send a real text and then erase its dedupe row on rollback. The registration proposal must address this boundary before adoption; registering only a synchronous act() branch is insufficient.

Segment estimates follow Twilio's SMS character limits: GSM-7 counts extension characters twice; other text uses UTF-16 units. Multipart capacity differs for US/Canada toll-free senders. These are estimates; the provider receipt remains authoritative.

We use essential cookies to keep you signed in. See our Privacy Policy for details.