Turns your smartphone into an SMS gateway for sending and receiving messages via API.
Explore the docs »
Report Bug
·
Request Feature

SMS Gateway turns your Android smartphone into an SMS gateway. It's a lightweight application that allows you to send SMS messages programmatically via an API or CLI tool and receive webhooks on incoming SMS. This makes it ideal for integrating SMS functionality into your own applications or services.
📱 Core Functionality:
💬 Message Handling:
scheduleAt field (it must be a future timestamp).🔒 Security and Privacy:
🔧 Advanced Features:
🔌 Integration:
Note: It is not recommended to use this for batch sending due to potential mobile operator restrictions.
You can install app to your device from prebuilt APK.
The project provides two pre-built variants:
You need an Android device with Android 5.0 (Lollipop) or above for using the application.
To use the application, you need to grant the following permissions:
Prerequisites:
local.properties (created automatically by Android Studio) or the ANDROID_HOME environment variable.app/google-services.json — Firebase configuration required by the Google Services plugin. The file is gitignored, so provide your own copy (CI generates it from a repository secret).The release and insecure variants are signed with your own keystore, which the build expects at app/keystore.jks (also gitignored). Gradle reads the signing variables from the process environment, not from a .env file, and they are listed in .env.example:
| Variable | Purpose | Format | Example |
|---|---|---|---|
SIGNING_STORE_PASSWORD |
Password for the keystore file used to sign release builds | String | your-keystore-password |
SIGNING_KEY_ALIAS |
Alias of the key inside the keystore that signs release builds | String | your-key-alias |
SIGNING_KEY_PASSWORD |
Password for that key alias | String | your-key-password |
ANDROID_HOME |
Path to the Android SDK, used when local.properties has no sdk.dir |
Absolute path | /Users/username/Library/Android/sdk |
The three signing variables are read by signingConfigs.release in app/build.gradle. The debug and debugInsecure variants are signed with the default Android debug keystore and need none of them.
Export the variables and build:
cp .env.example .env
# fill in your values, then:
set -a; source .env; set +a
./gradlew test # run unit tests
./gradlew assembleDebug # debug build, signed with the default debug keystore
./gradlew assembleInsecure # insecure development build, signed with the release keystore
./gradlew assembleRelease # secure release build, signed with the release keystore
./gradlew bundleRelease # release App Bundle (.aab)
app/build.gradle defines four build variants:
| Variant | Signing | Network traffic | Use |
|---|---|---|---|
release |
Release keystore | TLS only (cleartext allowed to 127.0.0.1) |
Production |
insecure |
Release keystore | Cleartext allowed | Development and testing |
debug |
Debug keystore | TLS only (cleartext allowed to 127.0.0.1) |
Local debugging |
debugInsecure |
Debug keystore | Cleartext allowed | Local debugging |
For integration examples, please refer to the CLI Tool Documentation and API Documentation
The SMS Gateway for Android can work in two modes: with a Local Server started on the device or with a Cloud Server. The basic API is the same for both modes and is documented on the SMS Gateway for Android API Documentation page.
This mode is ideal for sending messages from a local network.
Local Server switch to the "on" position.Start Service button at the bottom of the screen to start the gateway. Switch changes take effect after the service is restarted.Local Server section, your device's local and public IP addresses will be displayed, along with the credentials for basic authentication. Note that the public IP address is only accessible if you have a public (or "white") IP and your firewall is configured correctly.To send a message from within the local network, execute a curl command like the one below. Replace <username>, <password>, and <device_local_ip> with the actual values provided in the previous step:
sh
curl -X POST -u <username>:<password> \
-H "Content-Type: application/json" \
-d '{ "textMessage": { "text": "Hello, doctors!" }, "phoneNumbers": ["+19162255887", "+19162255888"] }' \
http://<device_local_ip>:8080/message
Alternatively, you can use the CLI Tool:
sh
smsgate -e 'http://<device_local_ip>:8080/message' -u <username> -p <password> \
send --phones '+19162255887,+19162255888' 'Hello, doctors!'
To send an MMS message, use the mmsMessage field with one or more Base64-encoded attachments:
sh
curl -X POST -u <username>:<password> \
-H "Content-Type: application/json" \
-d '{ "mmsMessage": { "subject": "Hello", "text": "See the photo", "attachments": [ { "contentType": "image/jpeg", "name": "photo.jpg", "data": "<base64-encoded-bytes>" } ] }, "phoneNumbers": ["+19162255887"] }' \
http://<device_local_ip>:8080/message
Note: The data field must contain Base64-encoded bytes. The app must be set as the device's default SMS app for reliable MMS sending on most carriers.
The full API reference is available as interactive Swagger documentation at http://<device_local_ip>:8080/docs.
The same Swagger page is published at https://capcom6.github.io/android-sms-gateway/, where the local-server entry resolves against the GitHub Pages origin. Use the device-hosted page above to exercise the local API.
Use the cloud server mode when dealing with dynamic or shared device IP addresses.
Cloud Server switch to the "on" position.Start Service button located at the bottom of the screen to start the gateway and connect to the cloud server. The device has to be registered first, see Device Registration. Switch changes take effect after the service is restarted.Cloud Server section, the credentials for basic authentication will be displayed.To send a message via the cloud server, perform a curl request with a command similar to the following, substituting <username> and <password> with the actual values obtained in step 4:
sh
curl -X POST -u <username>:<password> \
-H "Content-Type: application/json" \
-d '{ "textMessage": { "text": "Hello, doctors!" }, "phoneNumbers": ["+19162255887", "+19162255888"] }' \
https://api.sms-gate.app/3rdparty/v1/message
Or with CLI:
sh
smsgate -u <username> -p <password> \
send --phones '+19162255887,+19162255888' 'Hello, doctors!'
For further privacy, you can deploy your own private server. See the Private Server section for more details.
When connected to the cloud server, received messages (SMS, Data SMS, and MMS) are automatically uploaded to the server for centralized access.
The device has to be registered with the cloud server before it can be used in cloud mode. The first time you tap the Start Service button, the app asks how to register:
The gateway starts as soon as the registration succeeds. The start button stays disabled while the registration is running, so a double tap cannot create two accounts or two devices.
The Unregister device action in Settings → Cloud server → Credentials clears the registration on the device and stops the cloud session. The device has to sign up or sign in again before the cloud server can be used.
Note: This only clears the registration on the device — the cloud server keeps its own record of it, so commands for the previous registration can still be pushed to the device. The app ignores them while the device is unregistered.
Use webhooks to receive notifications for messaging events (e.g., incoming SMS and MMS).
| Event | Description |
|---|---|
sms:received |
Triggered when an SMS message is received |
sms:batch:received |
Triggered when multiple SMS messages are received at once (batched) |
sms:sent |
Triggered when an SMS message is sent |
sms:delivered |
Triggered when an SMS message is delivered |
sms:failed |
Triggered when an SMS message fails to send |
sms:cancelled |
Triggered when a pending SMS message is cancelled |
sms:data-received |
Triggered when a data SMS is received |
sms:batch:data-received |
Triggered when multiple data SMS messages are received at once (batched) |
mms:received |
Triggered when an MMS notification is received (before download) |
mms:batch:received |
Triggered when multiple MMS notifications are received at once (batched) |
mms:downloaded |
Triggered when an MMS message is fully downloaded with body and attachments |
mms:batch:downloaded |
Triggered when multiple MMS messages are fully downloaded (batched) |
app:started |
Triggered when the app is started, with the list of active SIM cards |
system:ping |
Periodic heartbeat event |
Follow these steps to set up webhooks:
Register your webhook with an API request:
sh
curl -X POST -u <username>:<password> \
-H "Content-Type: application/json" \
-d '{ "id": "unique-id", "url": "https://webhook.site/<your-uuid>", "event": "sms:received" }' \
http://<device_local_ip>:8080/webhooks
3. Send an SMS to the device.
4. The application will dispatch POST request to the specified URL with a payload such as:
json
{
"event": "sms:received",
"payload": {
"messageId": "msg_12345abcde",
"message": "Received SMS text",
"phoneNumber": "+19162255887",
"simNumber": 1,
"receivedAt": "2024-06-07T11:41:31.000+07:00"
}
}
To deregister a webhook, execute a curl request using the following pattern:
sh
curl -X DELETE -u <username>:<password> \
http://<device_local_ip>:8080/webhooks/unique-id
For cloud mode the process is similar, simply change the URL to https://api.sms-gate.app/3rdparty/v1/webhooks. Webhooks in Local and Cloud mode are independent.
Note: Webhooks are transmitted directly from the device; therefore, the device must have an outgoing internet connection. As the requests originate from the device, incoming messages remain inaccessible to us.
See the open issues for a full list of proposed features (and known issues).
Contributions are what make the open source community such an amazing place to learn, inspire, and create. Any contributions you make are greatly appreciated.
If you have a suggestion that would make this better, please fork the repo and create a pull request. You can also simply open an issue with the tag "enhancement". Don't forget to give the project a star! Thanks again!
git checkout -b feature/AmazingFeature)git commit -m 'Add some AmazingFeature')git push origin feature/AmazingFeature)Distributed under the Apache-2.0 license. See LICENSE for more information.
If you have any questions or suggestions, feel free to reach out through the following channels:
| 日期 | 榜单 | 排名 | 周期新增 | 总 STAR |
|---|