This application transforms any Android device into a dedicated, self-hosted SMS Gateway. It provides a robust RESTful API that allows you to programmatically send SMS messages over your cellular network, manage device connections via ADB, and enforce secure, role-based access control for multiple users or services.
- Features & Capabilities
- System Architecture
- Deployment
- Environment Configuration
- User Management System
- ADB Connection & Hardware Setup
- Turn Key SMS Gateway: Send SMS messages programmatically via simple HTTP requests.
- Device Management: Seamlessly connect and manage Android devices via ADB (Android Debug Bridge) over Wi-Fi or USB.
- Role-Based Access Control (RBAC): Distinct permission levels for Administrators (infrastructure management) and Standard Users (message dispatch).
- Quota Management: Automatic tracking of SMS usage per user with monthly resets on a configurable billing day.
- Remote Shell Execution: Administrators can execute raw
ADB SHELLcommands directly on the device for advanced debugging or automation. - Simple Authentication: Secure access via JWT-based tokens.
Note on Message Content: Currently, the send-message endpoint supports ASCII/Plain text only. Emoji support is in development and is not supported (YET).
In this API, a "Standard User" is not limited to a human operator. A user entity functions effectively as a Service Account or API Key.
- Example Use Case: You can create a user named
alert-systemwith a 500-message limit and a separate user namedmarketing-botwith a 5,000-message limit. - This allows multiple external applications to share the same physical Android hardware while maintaining isolated quotas and credentials.
The application is available as a Docker image. For data persistence (logs and database), you must mount the /data volume.
Run the container directly using Docker. This method is useful for quick setups, testing, or when you don’t need Docker Compose.
Important: Make sure you are running this command from the directory where you want the
datafolder to be created, as it will be mounted into the container for persistent storage.
To start the container, run:
docker run \
--restart unless-stopped \
-p 8080:8000 \
-v "$(pwd)/data:/app/data" \
--name android-sms-api \
agamsol/android-sms-api:latest
This command will:
- Pull the image if it’s not already available locally
- Start a single container named
android-sms-api - Expose the API on port 8080 (host) mapped to 8000 (container)
- Persist application data in the local
./datadirectory - Automatically restart the container unless it is explicitly stopped
If you need to perform device QR pairing or any other interactive setup, run the container in the foreground (as shown above) so you can see the terminal output.
To stop the container:
docker stop android-sms-apiTo remove the container:
docker rm android-sms-apiFor more information about Docker commands and options, see the official Docker documentation: https://docs.docker.com/engine/reference/run/
For a persistent, server-ready deployment, use the provided docker-compose.yml file. This setup is recommended for long-running or production-like environments, as it simplifies service management, networking, and restarts.
Important: Make sure you are in the same directory as the
docker-compose.ymlfile before running any Docker Compose commands.
To start the service in detached (background) mode, run:
docker compose up -dThis will start the container in the background. Use this mode once everything is already configured.
If you need to perform device QR pairing or any other interactive setup, start Docker Compose without the -d flag so you can see the terminal output and interact when needed:
docker compose upYou can stop the service at any time by pressing Ctrl + C when running in the foreground.
Check the status of the running service:
docker compose psView logs for the service (useful for debugging):
docker compose logs -fStop the service without removing the container:
docker compose stopStop and remove the container, network, and volumes created by Docker Compose:
docker compose down -vFor a full list of available commands, configuration options, and advanced usage, see the official Docker Compose documentation: https://docs.docker.com/compose/
Create a .env file in the root directory using the keys below. You can copy .env.sample to get started.
| Key | Description | Default |
|---|---|---|
VERSION |
The current version of the application meta info. | Unknown |
ADMIN_USERNAME |
The username for the immutable hardcoded administrator. | admin |
ADMIN_PASSWORD |
The password for the hardcoded administrator. If not specified, a secure random string is automatically generated on startup. | <Auto-Generated> |
LOGGER_LEVEL |
Logging verbosity level. | INFO |
LOGGER_PATH |
Directory path where logs will be stored. | data/logs |
PLAN_RESET_DAY_OF_MONTH |
The day of the month (1-31) when user message limits are reset. Set to 0 to disable the monthly reset. |
23 |
DATABASE_PATH |
File path for the SQLite3 database. | data/Android-SMS-API.db |
ADB_QR_DEVICE_PAIRING |
Set to True to enable the QR code pairing endpoint. |
True |
ADB_AUTO_CONNECT |
If True, the server attempts to auto-connect to the specific device identifier defined in ADB_DEFAULT_DEVICE on startup. |
False |
ADB_DEFAULT_DEVICE |
(Optional) Pre-define a specific device identifier to connect to (Required if Auto-Connect is enabled). | Empty |
ADB_SHELL_EXECUTION_ROUTE_ENABLED |
Enables the endpoint allowing admins to run raw ADB shell commands. | True |
JWT_ALGORITHM |
Algorithm used for signing JSON Web Tokens. | HS256 |
JWT_ACCESS_TOKEN_EXPIRE_MINUTES |
Token validity duration in minutes. | 60 |
JWT_SECRET |
Secret key used to sign the JWT. If not specified, a secure random string is automatically generated on startup. | <Auto-Generated> |
The server manages a tiered user system. Message limits are reset automatically based on the PLAN_RESET_DAY_OF_MONTH defined in your environment variables.
The Hardcoded User is a fallback super-admin defined at the code-level within the .env file.
- Persistence: This user does not exist in the SQLite database and persists through database wipes.
- Immutability: This user cannot be deleted or modified via the API.
- Purpose: Ensures administrative access is always available for system recovery or initial setup.
Administrators (Hardcoded or Database-created) have elevated privileges:
- User Management: Create/Delete users and adjust monthly quotas.
- Security: Reset passwords for any user in the system.
- Device Ops: Manage ADB pairing, connections, and view device lists.
- Code Execution: Permission to execute ADB SHELL commands.
- Unlimited Limits: Administrators are NOT subject to monthly message caps.
Standard users are designed for operational use (apps or humans):
- Message Dispatch: Can send SMS messages via the API (Strictly Text/ASCII).
- Quota Enforcement: Message sending is rejected if the monthly limit is exceeded.
- Self-Management: Can only reset or change their own password.
Reliability relies on correct hardware setup and persistent ADB connections. The system supports Standard Connection (IP/Port or USB) and Wireless QR-Pairing (Android 11+).
The Android device must be connected to a power source 24/7 to ensure uninterrupted availability of the SMS gateway.
⚠️ Warning: If possible, remove the physical battery from the device and power it directly via the charging cable. Keeping a battery at 100% charge 24/7 creates a high risk of battery swelling and fire hazards.
- Navigate to Settings > About Phone.
- Tap Build Number 7 times until you see "You are now a developer".
- Navigate to Settings > System > Developer Options.
- Enable "Stay Awake" (Ensures the CPU/Screen does not sleep while charging).
- Enable USB Debugging (for cable) or Wireless Debugging (for Wi-Fi).
Requires Android 11+ and devices on the same Wi-Fi network.
If ADB_QR_DEVICE_PAIRING is set to True, the server allows for wireless pairing via QR code. This can be triggered automatically on startup or manually via the API.
You can generate the pairing code in two ways:
- Automatic Prompt: On server startup, if
ADB_AUTO_CONNECTis disabled (or if the auto-connection fails), the server will automatically generate and display a pairing QR code in the terminal. - Manual Trigger: You can generate a new QR code at any time by calling the GET
/adb/pair-deviceendpoint.
Note: The generated QR code is valid for 5 minutes before it expires.
Once the QR code is displayed:
- Navigate to Settings > Developer Options on your Android device.
- Enable Wireless debugging.
- Tap the text "Wireless debugging" (not the toggle) to enter the sub-menu.
- Tap Pair device with QR code.
- Scan the QR code displayed in your terminal or browser
After scanning, the pairing process completes automatically. You can confirm success by:
- Checking the terminal logs for a "Successfully Paired" message.
- Calling the
GET /adb/list-devicesendpoint to verify your device appears with the statusauthorized.