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.
P.S. Parts of this release are preperations for the UI Interface which is coming VERY soon!
- Features & Capabilities
- System Architecture
- Deployment
- Environment Configuration
- User Management System
- ADB Connection & Hardware Setup
- Whats New In 0.4
- 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).
The API uses a Role-Based Access Control (RBAC) system centered around API Tokens.
- Administrator: The single owner of the server. Has full control over the infrastructure, devices, and tokens.
- API Tokens: Secure keys issued by the Administrator. They are used by external applications or scripts to interact with the API (e.g., sending messages). Each token has its own isolate message quota.
The application is available as a Docker image. For data persistence (logs and database), you must mount the /data volume.
Requirement: To pair a device, you must run this container with Host Networking enabled or map the device via USB Passthrough.
Run the container directly using Docker. This method is useful for quick setups, testing, or when you don’t need Docker Compose.
Here is the refined block. I have structured it to clearly separate the "Whole Bus" (recommended) method from the "Specific Device" method, while adding the necessary warning about hot-plugging reliability.
Important:
Persistence: Execute this command from the directory where you want the
datafolder to be created.Connectivity: If you'd like to use the QR-Pairing feature replace
-p 8000:8000with--net=host(Flag Working Only On Linux Environments)Passthrough:
Whole Bus (Recommended): Use
--device /dev/bus/usb:/dev/bus/usb. This allows the container to detect the phone even if it is unplugged and replugged.Specific Device: Use
--device /dev/bus/usb/XXX/YYY(replace with your specific device path found vialsusb).
- Warning: This binds to a specific file descriptor. If the cable is disconnected, the device node ID will change, and the container will lose access until you update the command and restart it.
If you choose the specific device method, users will need to know how to find that path. You might want to add this small tip below the block:
# Run 'lsusb' on the host to find the Bus and Device numbers
# Example Output: Bus 001 Device 004: ID 18d1:4ee7 Google Inc.
# Path: /dev/bus/usb/001/004To start the container, run:
docker run \
--restart unless-stopped \
-p 8000: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 8000 (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 |
MIGRATE_DATABASE |
Set to True to enable automatic database schema migrations on startup. Required for upgrading from older versions. |
False |
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 Administrator is the sole privileged user of the system, defined by ADMIN_USERNAME and ADMIN_PASSWORD in your .env file.
- Immutability: This user is hardcoded and cannot be deleted via the API.
- Capabilities:
- Full Access: Manage devices, tokens, infrastructure, and execute shell commands.
- Unlimited Quota: The administrator is not subject to message limits.
Instead of creating "User Accounts", the Administrator now issues API Tokens. These are ideal for external applications, bots, or services.
- Created via:
POST /auth/tokens/create(Admin only). - Capabilities:
- Send SMS: Access to
POST /adb/send-text-message(Strictly Text/ASCII). - List Devices: Access to
GET /adb/list-devices. - Check Status: Access to
GET /auth/@me(view own quota).
- Send SMS: Access to
- Quotas: Each token has a strict monthly message limit. If exceeded, sending messages will return
403 Forbidden.
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.
Version 0.4 introduces a major overhaul to the authentication system, replacing traditional user accounts with a more robust API Token system.
- Database Migration: You MUST set
MIGRATE_DATABASE=Truein your environment variables to upgrade your database schema. The application will not start without this if a migration is pending. (only applies for database created with version 0.3 and lower) - User System: "Standard Users" have been replaced by API Tokens.
- API Tokens: New endpoints to create, list, manage, and refresh API tokens with specific message limits.
- Unified Auth: Support for both
Authorization: Bearer <TOKEN>andX-API-Key: <TOKEN>. - Token Refresh: Ability to rotate a token's secret while keeping the same ID and history.
- Expanded Access: API Tokens can now access
/adb/list-devices. - Status Info:
GET /auth/@menow returns detailed quota information.