Custom SMS Configuration
RainMaker sends a one-time password (OTP) over SMS for three user events: sign-up, forgot password, and account deletion. These messages are delivered through AWS End User Messaging (Amazon SNS SMS) from your deployment's own AWS account.
By default the deployment sends a generic OTP message using AWS's default settings. The custom_sms deployment setting lets you customise the message text per country and attach the identifiers (Sender ID, India DLT details) that many countries require.
SMS delivery is governed primarily by AWS and the destination country's mobile carriers, not by RainMaker. The custom_sms setting only controls the message content and the identifiers RainMaker passes to AWS. The origination identity (Sender ID / toll-free number / short code) and the country-level permissions must be set up separately in the AWS End User Messaging console. Without that, AWS will reject or silently drop the SMS even when custom_sms is configured correctly.
How OTP SMS Works
- A user triggers sign-up, forgot-password, or account deletion.
- RainMaker asks AWS to send the OTP to the user's phone number.
- RainMaker reads the user's country from the phone number (e.g.
+91…→IN,+1…→US,+852…→HK,+86…→CN). - If that country code is present in your
custom_smsconfiguration, RainMaker applies the configured message text and identifiers; otherwise it falls back to a generic default message. - AWS attempts delivery using the origination identity available for that country and the destination country's carrier rules.
If AWS rejects or the carrier drops the message, the user simply receives nothing — the sign-up / forgot-password flow still appears to succeed, and no error is shown in the app. The only place the failure is visible is CloudWatch logs (see Troubleshooting). Always confirm delivery from the logs, not just from the API response.
Why SMS Fails Without Proper Configuration
| Symptom (in CloudWatch) | Cause | Fix |
|---|---|---|
ParameterValueInvalid … senderID … is not valid | The sender_id value is not a valid Sender ID. It must be 1–11 characters, only letters/digits/hyphen, and must start and end with a letter or digit (no spaces, no underscore). A phone/toll-free number (e.g. +18667246978) here is also invalid. | Use a valid Sender ID, or leave sender_id empty for countries that don't support Sender IDs. Never put a phone number in sender_id. |
InvalidParameter: AWS.MM.SMS.EntityId is missing | A template id (event.*.id) is non-empty while entity_id is empty, so RainMaker sends a TemplateId with no matching EntityId. These are India DLT-only fields. This is the most common misconfiguration — teams blank sender_id/entity_id but forget the template ids. | For every non-India country, set entity_id and all three event.*.ids to "". A leftover placeholder like signup_sms_template_id is the usual culprit. |
No origination identity available to send to destination number | There is no active origination identity (Sender ID / toll-free / 10DLC / short code) for that country. | Provision and activate an origination identity for the country in AWS End User Messaging. |
The provided number does not exist or does not belong to the account | The destination number could not be resolved/routed — usually not a real, SMS-reachable mobile (a fake/test number, a landline, or VoIP). | Test with a real mobile you control; verify it's a valid SMS-capable handset (not the config's fault). |
Destination country blocked by SMS protect configuration | The destination country is blocked by your AWS Protect configuration (or it is not on an allow-list). | Set the country to Allow in the Protect configuration's country rules. |
Unknown error attempting to reach phone | The carrier accepted but dropped the message — typically missing country registration (e.g. India DLT, China template registration) or filtered content. | Complete the country's registration and send only approved template content. |
| Nothing sent / message never reaches AWS | Account is in the SMS sandbox (only verified numbers receive SMS) or the monthly SMS spend limit is exhausted. | Move the account to production and/or raise the spend limit. |
Origination Identities and Country Support
AWS requires a valid origination identity for each destination country. The type that is allowed varies by country:
- Sender ID — an alphanumeric name (for example a brand name) shown as the sender. Supported in many countries (e.g. Hong Kong, India, most of Europe/Asia). Not supported by the US, Canada, or China. Some countries require the Sender ID to be registered first.
- Toll-free number — common for the US/Canada. Requires toll-free verification before it can send.
- 10DLC (long code) — US local numbers. Requires brand + campaign registration.
- Short code — dedicated numeric code (US, China, and others). Higher cost and longer lead time.
Check the Supports Sender IDs column and per-country notes in the AWS documentation before choosing an identity: Supported countries and regions for SMS messaging (AWS End User Messaging SMS).
Configuring AWS End User Messaging
All of the following are done in the AWS End User Messaging SMS console (formerly Amazon Pinpoint SMS), in the same AWS account and region as your deployment (for example us-east-1).
1. Request a Sender ID
Console → Configurations → Origination identities → Request originator → Sender ID. Choose the destination country and the requested ID text. For countries that require registration, you will be guided into a registration (see step 3).
2. Request a phone number (toll-free / 10DLC / short code)
Console → Request originator → Phone number. Choose the country, number type, and SMS capability.
- Toll-free (US/CA): after the number is provisioned you must complete toll-free verification — submit your company name (exact legal name), website, use case, sample messages, and a clear description of your opt-in workflow.
- 10DLC (US): register a brand and a campaign.
- Short code: submit the request (long provisioning time).
3. Track registrations (status: pending vs. action needed)
Console → Registrations. Each Sender ID registration, toll-free verification, and 10DLC campaign appears here with a status:
CREATED/SUBMITTED/REVIEWING— in AWS / carrier review. Wait; do not resubmit while reviewing.REQUIRES_UPDATES/DENIED— action is on your side: open the registration, read the reviewer's reason, fix the flagged fields, and resubmit.COMPLETE— approved; the origination identity becomes Active and can send.
Toll-free verification and Sender ID / DLT registrations are reviewed by AWS and the carriers and can take from a few business days up to a couple of weeks. Common rejection reasons are unclear opt-in language, company-name mismatch, and inconsistent opt-in workflow. If a registration is stuck, contact your AWS account manager and ask them to prioritise the review.
4. Check country block / unblock (Protect configuration)
Console → Protect configurations → (your configuration) → Country rules.
A Protect configuration controls which destination countries are allowed. Make sure every country you send to is set to Allow (or Monitor). A country set to Block — or any country missing from an allow-list style configuration — is silently rejected with Destination country blocked by SMS protect configuration.
If your Protect configuration only allows a small set of countries, users in every other country receive no SMS at all. Review the full country rule set, not just the countries you are actively testing.
5. Account-level checks
- SMS sandbox: while in the sandbox, SMS is delivered only to verified destination numbers. Request production access to send to any number.
- Spend limit: the monthly SMS spend limit stops all sending once exhausted (silently). Raise it before going to production.
Country-Specific Configuration
The table below summarises what to set up for the four most common regions. The custom_sms columns refer to the per-country fields described in Configure custom_sms.
| Country | AWS origination identity | sender_id | entity_id + template id | Notes |
|---|---|---|---|---|
India (IN) | Registered Sender ID + DLT | Registered DLT header | Required — DLT Entity ID + DLT Template IDs | Strictest. Register the header and templates on the DLT portal and with AWS (India Sender ID registration), then supply the resulting Entity ID + Template IDs. The message text must match the registered template exactly. Ensure IN is Allowed in the Protect config. |
United States (US) | Toll-free (verified) / 10DLC / short code | (empty) | (empty) | US does not support Sender IDs. SMS cannot be sent until a US origination identity is Active (e.g. toll-free verification COMPLETE). |
Hong Kong (HK) | Sender ID (registration recommended) | Your Sender ID | (empty) | Sender IDs are supported. Do not set entity_id or template id (those are India-only). |
China (CN) | Short code + template registration | (empty) | (empty) | China does not support Sender IDs. Templates must be pre-registered with the Chinese carriers (via AWS Support). Delivery is best-effort even after registration, due to local carrier filtering. |
For any country not present in your config_data.countries, RainMaker sends a generic default OTP message with no Sender ID or DLT attributes. That is fine for countries that don't need them, but India and China will not deliver without their respective registrations.
Configure custom_sms via the Superadmin API
The custom_sms setting is configured through the Deployment Setting API on the RainMaker Superadmin APIs Swagger.
Step 1 — Log in
Call the Login API using the HTTP Base URL from your deployment details email. The response returns an access token; include it as the Authorization header for the next call.
Step 2 — Call the configuration API
Endpoint: configureServiceConfiguration
PUT /v1/admin/deployment_settings/config/custom_sms
Authorization: <access_token>
Content-Type: application/json
Example request body
This example shows the correct shape for each region — India with DLT, Hong Kong with a Sender ID, and US/China with empty identifiers (they rely on the AWS origination identity).
{
"enabled": true,
"config_data": {
"countries": {
"IN": {
"sender_id": "MYBRND",
"entity_id": "1234567890123456789",
"event": {
"signup": { "id": "1112223334445556667", "text": "MYBRND: Your OTP for signup is {#var#}. It expires in 5 minutes. Do not share this code." },
"forgotpassword": { "id": "1112223334445556668", "text": "MYBRND: Your OTP for password reset is {#var#}. It expires in 5 minutes. Do not share this code." },
"delete": { "id": "1112223334445556669", "text": "MYBRND: Your OTP for account deletion is {#var#}. It expires in 5 minutes. Do not share this code." }
}
},
"HK": {
"sender_id": "MYBRND",
"entity_id": "",
"event": {
"signup": { "id": "", "text": "MYBRND: Your OTP for signup is {#var#}. It expires in 5 minutes. Do not share this code." },
"forgotpassword": { "id": "", "text": "MYBRND: Your OTP for password reset is {#var#}. It expires in 5 minutes. Do not share this code." },
"delete": { "id": "", "text": "MYBRND: Your OTP for account deletion is {#var#}. It expires in 5 minutes. Do not share this code." }
}
},
"US": {
"sender_id": "",
"entity_id": "",
"event": {
"signup": { "id": "", "text": "MYBRND: Your OTP for signup is {#var#}. It expires in 5 minutes. Do not share this code." },
"forgotpassword": { "id": "", "text": "MYBRND: Your OTP for password reset is {#var#}. It expires in 5 minutes. Do not share this code." },
"delete": { "id": "", "text": "MYBRND: Your OTP for account deletion is {#var#}. It expires in 5 minutes. Do not share this code." }
}
},
"CN": {
"sender_id": "",
"entity_id": "",
"event": {
"signup": { "id": "", "text": "MYBRND: Your OTP for signup is {#var#}. (registered template text)" },
"forgotpassword": { "id": "", "text": "MYBRND: Your OTP for password reset is {#var#}. (registered template text)" },
"delete": { "id": "", "text": "MYBRND: Your OTP for account deletion is {#var#}. (registered template text)" }
}
}
}
}
}
Field reference
| Field | Meaning |
|---|---|
enabled | Enables the custom_sms service. Once enabled it cannot be disabled via this API. |
config_data.countries | A map keyed by ISO 3166-1 alpha-2 country code (IN, US, HK, CN, …). |
sender_id | Alphanumeric Sender ID (1–11 chars, letters/digits/hyphen). Leave empty for countries that don't support Sender IDs (US, Canada, China). Never put a phone or toll-free number here — origination numbers are provisioned in AWS End User Messaging and used automatically once ACTIVE; a value like +18667246978 is an invalid Sender ID and fails with ParameterValueInvalid. |
entity_id | India DLT Entity ID. Leave empty for every non-India country. |
event.signup / event.forgotpassword / event.delete | Per-event message configuration. |
event.*.id | India DLT Template ID for that event. Leave empty for non-India countries. |
event.*.text | The message body. Must contain the {#var#} placeholder, which is replaced by the OTP at send time. |
- The
PUTcall replaces the entireconfig_data— always send the full set of countries you want to keep. - For every non-India country,
entity_idAND all threeevent.*.ids must be empty ("") — only India uses these DLT fields. (sender_idis separate: leave it empty for countries that don't support Sender IDs — US, Canada, China — or set a registered Sender ID for countries that do, e.g. Hong Kong.) A leftover templateid(e.g."signup_sms_template_id") makes RainMaker attachAWS.MM.SMS.TemplateIdwith noEntityId, so AWS rejects the publish withAWS.MM.SMS.EntityId is missingand the SMS is silently dropped — even though thePUTstill returns200 success. enabledcannot be set back tofalseonce enabled — submit a correctedconfig_datawithenabled: trueto make changes.
Expected response
A successful call returns:
{
"status": "success",
"description": "Successfully added custom_sms configuration setting"
}
Troubleshooting / Verifying Delivery
- Enable SNS delivery status logging for SMS (in the SNS / End User Messaging settings) so delivery results are written to CloudWatch.
- Check these CloudWatch log groups (replace
<region>and<account-id>):/aws/lambda/esp-LambdaCustomSMSPy— publish errors such as the invalid Sender ID error.sns/<region>/<account-id>/DirectPublishToPhoneNumber— successful carrier hand-offs (Message has been accepted by phone carrier).sns/<region>/<account-id>/DirectPublishToPhoneNumber/Failure— failed deliveries with aproviderResponsereason.
- Match the
providerResponseto the Why SMS Fails table to identify the fix.
A SUCCESS status means AWS handed the message to the carrier — it is not a handset delivery receipt. Always confirm at least one real device test in addition to checking the logs.
For help with SMS configuration, contact the ESP RainMaker support team (esp-rainmaker-support@espressif.com).