Skip to content

SMS Quality Checks

SMS Inspect analyzes a text-message template before you send it — checking segmentation and encoding (what you'll be billed for), opt-out language, and the sender number. It re-uses the exact send-path engine, so the numbers you see in Inspect are the numbers you'll actually be charged.


What it checks

SMS Inspect runs a single stage against your stored SMS template (body_nlt and the optional from_number), rendered against a sample contact. It covers three concerns:

  1. Cost & encoding — how many segments the message occupies, and whether a stray character forced the expensive Unicode encoding.
  2. Compliance — whether the message carries recognizable opt-out language.
  3. Configuration — whether a per-template sender number override is valid.
  4. Rendering — whether the plain-English NLT expressions resolve against a sample contact.
Note

Every segmentation, encoding, and cost number reported by SMS Inspect is read directly from render_sms, the same engine that runs at delivery time. Inspect never re-derives these values — so the segment count you see is the segment count you're billed for.


Segments and encoding: why length is about cost

SMS is billed per segment, and how much text fits in a segment depends on the encoding:

EncodingWhen it's usedOne segmentConcatenated part
GSM-7Standard alphabet160 characters153 characters
UCS-2Any emoji or non-GSM character70 characters67 characters

The critical thing to understand: a single non-GSM character forces the whole message into UCS-2, dropping the per-segment budget from 160 to 70. The usual culprits are invisible — a smart quote ( instead of '), an em dash, an ellipsis, or an emoji.

That means a 90-character message you expected to send as one segment can quietly become two or three segments — and cost two or three times as much — because of one auto-inserted curly quote.

SMS Inspect surfaces this with three findings:

FindingSeverityFires when
SMS_UCS2_FORCEDwarningA non-GSM character forced UCS-2 encoding.
SMS_MULTI_SEGMENTwarningThe body occupies more than one segment.
SMS_BODY_TOO_LONGwarningThe body occupies more than three segments (4+).
Tip

If you see SMS_UCS2_FORCED and SMS_MULTI_SEGMENT together, fix the encoding first — replacing the smart quote with a straight quote often drops you back to GSM-7 and resolves the segment count in one move.


Opt-out language

Recurring marketing SMS in the US is governed by A2P 10DLC and TCPA. Recipients need a clear way to stop messages, and carriers can filter senders that don't provide it.

SMS_NO_OPT_OUT_LANGUAGE (advisory warning) fires when the rendered body contains none of the standard opt-out phrasings — reply STOP, text STOP, opt out, opt-out, a whole-word STOP, or unsubscribe.

This is advisory only — it never blocks a send, because the opt-out instruction may legitimately be carried elsewhere (for example, in an earlier message in the conversation). Synapse also honors the platform-level STOP keyword regardless of message text; this check is about the visible instruction A2P guidance expects.


Sender number

An SMS template can override the sending number with a from_number field. SMS_FROM_NUMBER_INVALID (warning) fires when that override is present but does not normalize to a valid E.164 number.

Leaving from_number unset is valid and never triggers the finding — the Twilio Messaging Service selects the sender automatically. The check only fires when you set an override to an invalid value.


NLT rendering

SMS Inspect renders the plain-English NLT in your body against a sample contact:

FindingSeverityPage
SMS_NLT_REQUIRED_MISScriticalSMS_NLT_REQUIRED_MISS
SMS_NLT_UNRESOLVED_EXPRESSIONwarningSMS_NLT_UNRESOLVED_EXPRESSION

A required miss suppresses the whole message for matching contacts (a durable failed log row, no send). An unresolved expression still sends, but leaves the raw token visible to the recipient.


Running an SMS Inspect

Trigger a run against an SMS template by ID or slug:

bash
curl -X POST https://synapse-api.pyrx.tech/v1/inspect \
-H "X-WORKSPACE-ID: <workspace-uuid>" \
-H "X-API-KEY: psk_live_<hex32>" \
-H "Content-Type: application/json" \
-d '{
"channel": "sms",
"sms_template_slug": "order-shipped-sms"
}'

See the Inspect API reference for the full request and response shape.