-
Notifications
You must be signed in to change notification settings - Fork 67
Description
Inconsistency between documented “737 Unicode character” limit and actual API behavior for UCS‑2 messages
Description
According to Plivo’s official documentation on SMS character limits:
Messages containing one or more UCS-2 16-bit Unicode characters have a maximum limit of 737 characters.
However, when sending a message containing 400 non‑GSM‑7 characters, the Plivo API returns:
{
"api_id": "f86be49c-fc50-42b9-8a41-6145b21f4cf1",
"error": "text parameter length exceeds 737 unicode characters"
}Both the Python len() (code points) and the len(text.encode('utf-16-be')) // 2 (UCS‑2 code units) equal 400, well below the documented 737 limit. This suggests either:
- The API is using a different internal length calculation than documented, or
- The error message and/or documentation is inaccurate.
Steps to Reproduce
Python 3.x code:
import configparser
import requests
import plivo
# Load configuration
config = configparser.ConfigParser()
config.read(r"C:\path\to\config.ini")
config.read(config["secret_paths"]["plivo"])
PLIVO_AUTH_ID = config["plivo"]["PLIVO_AUTH_ID"]
PLIVO_AUTH_TOKEN = config["plivo"]["PLIVO_AUTH_TOKEN"]
PLIVO_NUMBER = config["plivo"]["PLIVO_NUMBER"]
SPANISH_NUMBER = config["plivo"]["SPANISH_NUMBER"]
# Create text containing non‑GSM‑7 characters
NOT_GSM7_TEXT = "№—Їжі" * 2 * 10 * 4 # Expected: non-GSM-7 encoding (UCS-2)
url = f"https://api.plivo.com/v1/Account/{PLIVO_AUTH_ID}/Message/"
payload = {
"src": PLIVO_NUMBER,
"dst": SPANISH_NUMBER,
"text": NOT_GSM7_TEXT,
# "type": "unicode" # Explicit type yields same result
}
client = plivo.RestClient(auth_id=PLIVO_AUTH_ID, auth_token=PLIVO_AUTH_TOKEN)
if __name__ == "__main__":
print(f"{len(NOT_GSM7_TEXT)=}")
print(f"{len(NOT_GSM7_TEXT.encode('utf-16-be')) // 2=}")
r = requests.post(url, json=payload, auth=(PLIVO_AUTH_ID, PLIVO_AUTH_TOKEN), timeout=30)
print(f"Response status code: {r.status_code}")
print(r.text)Observed output:
len(NOT_GSM7_TEXT)=400
len(NOT_GSM7_TEXT.encode('utf-16-be')) // 2=400
Response status code: 400
{"error": "text parameter length exceeds 737 unicode characters"}
Expected Behavior
A UCS‑2 message should only be rejected when it exceeds 737 UCS‑2 code units, matching the documentation. Since both counts are far below 737, the API should accept the message.
Possible Explanations
- Server applies a different length check (e.g., byte count after UTF‑8 JSON encoding, rather than UCS‑2 units).
- Error message is misleading — “Unicode characters” might not match the actual metric used.
- Documentation omits critical detail on how length is calculated.
Suggested Improvements
- Clarify in the documentation exactly how message length is calculated for UCS‑2 — including whether the limit is based on:
- UCS‑2 code units
- UTF‑8 byte length
- JSON‑encoded size
- Some other metric
- Update the API error message to match the actual calculation, e.g.,
"text parameter length exceeds maximum UCS‑2 units"if that is the real constraint.
Environment
- Python: 3.12
- Plivo Python SDK: [4.59.1]
- OS: Windows 10 (64-bit)
- Message tested via both
requestsandplivo.RestClient
Experimental Confirmation or Magic number 306
Through direct testing, I have confirmed that the string provided in the code is accepted as a single SMS when its length is 306 characters or less. This suggests that the gateway treats the message as UCS-2 encoded and applies a segmentation threshold consistent with UCS-2 limits (i.e., 306 characters per message segment).
This behavior appears to contradict the SDK’s default assumptions and may lead to silent truncation or missegmentation if not explicitly handled.
Let me know if you'd like me to include a minimal curl example or add a reproducible test case without SDK dependencies.