SMS smart encoding
Most characters that push an SMS out of GSM-7 are not ones you chose. A word processor turns ' into ’, an em dash arrives with a paste, a form field carries a non-breaking space. Each reads the same to your recipient and each doubles the cost of the message, because one non-GSM character converts the whole body to UCS-2.
Smart encoding replaces those characters with their GSM-7 equivalents before Bird hands the message to the carrier, so a body that only looked non-GSM stays GSM-7 and bills as fewer segments.
Turning it on
It is off by default, because it changes the text your recipient reads. Set options.smart_encoding to true on a send:
代码示例
curl -X POST https://eu1.platform.bird.com/v1/sms/messages \
-H "Authorization: Bearer bk_eu1_..." \
-H "Content-Type: application/json" \
-d '{
"to": "+31612345678",
"from": "Bird",
"text": "Your order shipped — track it here…",
"category": "transactional",
"options": { "smart_encoding": true }
}'On the CLI, pass --smart-encoding to bird sms send. In the SDKs the field is a per-send option: SmartEncoding (Go), smart_encoding= (Python), smartEncoding (PHP), options.smart_encoding (TypeScript).
There is no account-wide or per-sender setting yet: pass it per message.
When it declines
Replacement is all or nothing. If the body still holds a character outside GSM-7 after the replacements, the message is UCS-2 either way, so Bird sends your body exactly as you supplied it rather than altering it for no saving.
That is the common surprise. A single emoji, one CJK character, or an accented letter outside GSM-7 keeps the whole message in UCS-2, and nothing in the table can rescue it:
代码示例
{ "text": "Hoe gaat het vandaag? á “" }The “ is replaceable, but á is not in GSM-7 and has no entry in the table, so this body sends unchanged as UCS-2. GSM-7 includes à, ä, å, é, è, ì, ò, ù, ö, ñ, ü but not á, í, or ú.
Accented letters are deliberately absent from the table. Folding á to a would change the word rather than approximate it, which is the wrong trade for a sender writing Spanish or Portuguese. Twilio's equivalent feature draws the line in the same place.
One exception is worth knowing if your text is normalized to NFD, where an accent is stored as a separate combining mark rather than part of the letter. Those marks are on the table, so a decomposed ê becomes e^ and reaches GSM-7, while a precomposed ê is left alone. The same word can behave differently depending on how your system stores it.
What it does not do
- It never truncates. A body over the 12-segment cap is rejected with a 422, and the cap is measured after replacement, so opting in can bring an oversized body under it.
- It does not touch a body that is already GSM-7, which has no segments to save.
- It does not change what you are billed for beyond the segment count: the count is computed from the body as sent.
Reading back what happened
The message reports both halves. text is the body as sent, and options.smart_encoding reports the setting that applied:
代码示例
{
"text": "Your order shipped - track it here...",
"segments": { "count": 1, "encoding": "GSM_7BIT", "characters": 36 },
"options": { "smart_encoding": true }
}An encoding of UCS2 on a send you opted in tells you the body could not be brought into GSM-7. To see what would happen to a specific message before you send it, paste the text into the SMS segment calculator.
The full replacement table
Every character below is replaced when smart encoding is on. Characters not listed here are left alone, including every character already in GSM-7.
| Replacement | Characters replaced |
|---|---|
| space | U+00A0, U+2000, U+2001, U+2002, U+2003, U+2004, U+2005, U+2006, U+2007, U+2008, U+2009, U+200A, U+202F, U+205F, U+3000 |
| ! | ǃ U+01C3, ︕ U+FE15, ﹗ U+FE57, ! U+FF01 |
| !! | ‼ U+203C |
| " | « U+00AB, » U+00BB, ʺ U+02BA, ˮ U+02EE, “ U+201C, ” U+201D, „ U+201E, ‟ U+201F, ❝ U+275D, ❞ U+275E, 〝 U+301D, 〞 U+301E, " U+FF02 |
| # | ﹟ U+FE5F, # U+FF03 |
| $ | ﹩ U+FE69, $ U+FF04 |
| % | ﹪ U+FE6A, % U+FF05 |
| & | ﹠ U+FE60, & U+FF06 |
| ' | ``` U+0060, ´ U+00B4, ʹ U+02B9, ʻ U+02BB, ʼ U+02BC, ʽ U+02BD, ˈ U+02C8, ˊ U+02CA, ˋ U+02CB, U+0313, U+0314, ‘ U+2018, ’ U+2019, ‛ U+201B, ❛ U+275B, ❜ U+275C, ︐ U+FE10, ︑ U+FE11, ' U+FF07 |
| ( | ❨ U+2768, ❪ U+276A, ⟮ U+27EE, ⦅ U+2985, ﹙ U+FE59, ( U+FF08 |
| ) | ❩ U+2769, ❫ U+276B, ⟯ U+27EF, ⦆ U+2986, ﹚ U+FE5A, ) U+FF09 |
| * | ⁎ U+204E, ∗ U+2217, ⊛ U+229B, ✢ U+2722, ✣ U+2723, ✤ U+2724, ✥ U+2725, ✱ U+2731, ✲ U+2732, ✳ U+2733, ✺ U+273A, ✻ U+273B, ✼ U+273C, ✽ U+273D, ❃ U+2743, ❉ U+2749, ❊ U+274A, ❋ U+274B, ⧆ U+29C6, ﹡ U+FE61, * U+FF0A |
| + | ˖ U+02D6, ﹢ U+FE62, + U+FF0B |
| , | U+0326, ‚ U+201A, 、 U+3001, ﹐ U+FE50, ﹑ U+FE51, , U+FF0C, 、 U+FF64 |
| - | ‐ U+2010, – U+2013, — U+2014, ― U+2015, • U+2022, ⁃ U+2043, ⎼ U+23BC, ⎽ U+23BD, ﹣ U+FE63, - U+FF0D |
| . | 。 U+3002, ﹒ U+FE52, . U+FF0E, 。 U+FF61 |
| ... | … U+2026 |
| / | ÷ U+00F7, U+0337, U+0338, ⁄ U+2044, ∕ U+2215, ⧸ U+29F8, / U+FF0F |
| 0 | 0 U+FF10 |
| 1 | 1 U+FF11 |
| 1/2 | ½ U+00BD |
| 1/4 | ¼ U+00BC |
| 2 | 2 U+FF12 |
| 3 | 3 U+FF13 |
| 3/4 | ¾ U+00BE |
| 4 | 4 U+FF14 |
| 5 | 5 U+FF15 |
| 6 | 6 U+FF16 |
| 7 | 7 U+FF17 |
| 8 | 8 U+FF18 |
| 9 | 9 U+FF19 |
| : | ː U+02D0, ˸ U+02F8, ⦂ U+2982, ꞉ U+A789, ︓ U+FE13, : U+FF1A |
| ; | ⁏ U+204F, ︔ U+FE14, ﹔ U+FE54, ; U+FF1B |
| < | ‹ U+2039, ﹤ U+FE64, < U+FF1C |
| = | U+0347, ꞊ U+A78A, ﹦ U+FE66, = U+FF1D |
| > | › U+203A, ﹥ U+FE65, > U+FF1E |
| ? | ︖ U+FE16, ﹖ U+FE56, ? U+FF1F |
| @ | ﹫ U+FE6B, @ U+FF20 |
| A | ᴀ U+1D00, A U+FF21 |
| B | ʙ U+0299, B U+FF22 |
| C | ᴄ U+1D04, C U+FF23 |
| D | ᴅ U+1D05, D U+FF24 |
| E | ᴇ U+1D07, E U+FF25 |
| F | ꜰ U+A730, F U+FF26 |
| G | ɢ U+0262, G U+FF27 |
| H | ʜ U+029C, H U+FF28 |
| I | ɪ U+026A, I U+FF29 |
| J | ᴊ U+1D0A, J U+FF2A |
| K | ᴋ U+1D0B, K U+FF2B |
| L | ʟ U+029F, L U+FF2C |
| M | ᴍ U+1D0D, M U+FF2D |
| N | ɴ U+0274, N U+FF2E |
| O | ᴏ U+1D0F, O U+FF2F |
| P | ᴘ U+1D18, P U+FF30 |
| Q | Q U+FF31 |
| R | ʀ U+0280, R U+FF32 |
| S | ꜱ U+A731, S U+FF33 |
| T | ᴛ U+1D1B, T U+FF34 |
| U | ᴜ U+1D1C, U U+FF35 |
| V | ᴠ U+1D20, V U+FF36 |
| W | ᴡ U+1D21, W U+FF37 |
| X | X U+FF38 |
| Y | ʏ U+028F, Y U+FF39 |
| Z | ᴢ U+1D22, Z U+FF3A |
| [ | [ U+FF3B |
| \ | U+20E5, ⧵ U+29F5, ⧹ U+29F9, ﹨ U+FE68, \ U+FF3C |
| ] | ] U+FF3D |
| ^ | ˆ U+02C6, U+0302, U+1DCD, ^ U+FF3E |
| _ | U+0332, ‗ U+2017, _ U+FF3F |
| { | ❴ U+2774, ﹛ U+FE5B, { U+FF5B |
| | | U+20D2, U+20D3, ∣ U+2223, ⎜ U+239C, ⎟ U+239F, ⎸ U+23B8, ⎹ U+23B9, ⏐ U+23D0, | U+FF5C |
| } | ❵ U+2775, ﹜ U+FE5C, } U+FF5D |
| ~ | ˜ U+02DC, ˷ U+02F7, U+0303, U+0330, U+0334, ∼ U+223C, ~ U+FF5E |
| removed | U+200B, U+2028, U+2029, U+2060, U+FEFF |
Whitespace variants collapse to a single space (U+0020). The removed row lists characters that are deleted rather than replaced: zero-width and formatting characters that carry no visible content.