A command-line interface for interacting with the SMSGate API
Explore the docs »
Report Bug
·
Request Feature
- About The Project
- Getting Started
- Configuration
- Usage
- Certificate Authority (smsgate-ca)
- Contributing
- License
- Legal Notice
There are two CLI tools in this repository:
smsgate-- Interact with the SMS Gateway for Android API to send SMS/MMS messages, manage webhooks, and retrieve logs.smsgate-ca-- Issue TLS certificates for private deployments (webhook receivers and private servers on RFC 1918 addresses).
- Go 1.25+ (for building from source)
- Docker (optional, for containerized execution)
- Go to the Releases page of this repository.
- Download the appropriate binary for your operating system and architecture.
- Extract the archive to a directory of your choice.
- Move the binary to a directory in your system's PATH.
go install github.com/android-sms-gateway/cli/cmd/smsgate@latestThis will download, compile, and install the latest version of the CLI tool. Make sure your Go bin directory is in your system's PATH.
docker run -it --rm --env-file .env ghcr.io/android-sms-gateway/cli \
send --phone '+12025550123' 'Hello, Dr. Turk!'The CLI can be configured using environment variables or command-line flags. You can also use a .env file in the working directory to set these variables (loaded automatically via godotenv).
| Option | Env Var | Description | Default value |
|---|---|---|---|
--endpoint, -e |
ASG_ENDPOINT |
The endpoint URL | https://api.sms-gate.app/3rdparty/v1 |
--username, -u |
ASG_USERNAME |
Your username | required |
--password, -p |
ASG_PASSWORD |
Your password | required |
--format, -f |
n/a | Output format | text |
The CLI supports four output formats:
text: Human-readable text output (default)json: Pretty printed JSON-formatted outputraw: One-line JSON-formatted outputtable: Tab-aligned columnar output for lists and sub-tables
Please note that when the exit code is not 0, the error description is printed to stderr without any formatting.
smsgate [global options] command [command options] [arguments...]The CLI offers three main groups of commands:
- Messages: Commands for sending SMS, MMS, and data messages, and checking their status, including batch operations from CSV and Excel files.
- Webhooks: Commands for managing webhooks, including registering, listing, and deleting them.
- Logs: Commands for retrieving logs for a specific time range.
For a complete list of available commands, you can:
- Run
smsgate helporsmsgate --helpin your terminal. - Visit the official documentation at docs.sms-gate.app.
The CLI uses exit codes to indicate the outcome of operations:
0: success1: invalid options or arguments2: server request error3: output formatting error4: internal error
For security reasons, it is recommended to pass credentials using environment variables or a .env file.
Credentials can also be passed via CLI options:
smsgate -u <username> -p <password> send --phones '+12025550123' 'Hello, Dr. Turk!'The send command supports various options to customize message delivery:
# Send a simple text message
smsgate send --phones '+12025550123' 'Hello, Dr. Turk!'
# Send to multiple numbers
smsgate send --phones '+12025550123' --phones '+12025550124' 'Hello, doctors!'
# or
smsgate send --phones '+12025550123,+12025550124' 'Hello, doctors!'
# Send with explicit device selection
smsgate send --phones '+12025550123' --device-id device123 'Message'
# Send with SIM number selection (1-based)
smsgate send --phones '+12025550123' --sim-number 2 'Message'
# Send with priority (>=100 bypasses limits)
smsgate send --phones '+12025550123' --priority 100 'Urgent message'
# Send with time-to-live (TTL)
smsgate send --phones '+12025550123' --ttl 1h30m 'Expiring message'
# Send with expiration date (RFC3339 format)
smsgate send --phones '+12025550123' --valid-until '2026-12-31T23:59:59Z' 'Message'
# Disable delivery report
smsgate send --phones '+12025550123' --delivery-report=false 'Message'
# Skip phone number validation
smsgate send --phones '+12025550123' --skip-phone-validation 'Message'
# Filter by device activity (devices active within last 12 hours)
smsgate send --phones '+12025550123' --device-active-within 12 'Message'
# Send data message (base64 encoded)
echo -n 'hello world' | base64
smsgate send --phones '+12025550123' --data --data-port 12345 'aGVsbG8gd29ybGQ='
# Send MMS with subject and multiple attachments
smsgate send --mms --subject 'Project update' --phones '+12025550123' \
--attachment /path/to/report.pdf \
--attachment /path/to/chart.png \
'Here are the latest documents'
# Send MMS with attachments only (no text)
smsgate send --mms --phones '+12025550123' \
--attachment /path/to/photo.jpg
# Send MMS to multiple recipients
smsgate send --mms --phones '+12025550123' --phones '+12025550124' \
--subject 'Team update' --attachment /path/to/screenshot.png \
'Please review'Notes:
--dataand--mmsare mutually exclusive.- At least one of text or an attachment is required for MMS.
- MIME type is detected from the file extension (falls back to
application/octet-stream).
Send command options:
| Option | Description | Default Value | Example |
|---|---|---|---|
--id |
A unique message ID. If not provided, one will be automatically generated. | empty | zXDYfTmTVf3iMd16zzdBj |
--device-id, --device |
Optional device ID for explicit selection. If not provided, a random device will be selected. | empty | oi2i20J8xVP1ct5neqGZt |
--phones, --phone, -p |
Specifies the recipient's phone number(s). This option can be used multiple times or accepts comma-separated values. Numbers must be in E.164 format. | required | +12025550123 |
--sim-number, --sim |
The one-based SIM card slot number. If not specified, the device's SIM rotation feature will be used. | empty | 2 |
--delivery-report |
Enables delivery report for the message. | true |
true / false |
--priority |
Sets the priority of the message. Messages with priority >= 100 bypass all limits and delays. Range: -128 to 127. | 0 |
100 |
| Data Message | |||
--data |
Send data message instead of text (content must be base64 encoded). | false |
true |
--data-port |
Destination port for data message (1 to 65535). | 53739 |
12345 |
| MMS Message | |||
--mms |
Send MMS message instead of text; text is optional when at least one attachment is provided. | false |
true |
--subject |
MMS subject line. Requires --mms. |
empty | Photo update |
--attachment |
Path to an attachment file. Repeatable; MIME type is detected from the file extension. Requires --mms. |
empty | /path/to/image.jpg |
| Options | |||
--ttl |
Time-to-live (TTL) for the message. Duration format (e.g., 1h30m). If not provided, the message will not expire.Conflicts with --valid-until. |
empty | 1h30m |
--valid-until |
The expiration date and time for the message. RFC3339 format (e.g., 2006-01-02T15:04:05Z07:00).Conflicts with --ttl. |
empty | 2026-12-31T23:59:59Z |
--skip-phone-validation |
Skip phone number validation. | false |
true |
--device-active-within |
Time window in hours for device activity filtering. 0 means no filtering. |
0 |
12 |
--schedule-at |
Schedule delivery time (RFC3339 format). If not provided, the message is sent immediately. Example: 2026-12-31T23:59:59Z. |
immediate | 2026-12-31T23:59:59Z |
The CLI supports sending messages in bulk from CSV and Excel files. The batch send command also supports the shared delivery/device options from send (such as --device-id, --sim-number, --priority, --ttl, --valid-until, --delivery-report, --skip-phone-validation, --device-active-within), allowing fine-grained control over each message in the batch.
Supported file formats:
- CSV (Comma-Separated Values)
- XLSX (Excel files)
Basic usage:
# Send messages from a CSV file
smsgate batch send contacts.csv --map phone=Phone,text=Message
# Send messages from an Excel file with specific sheet
smsgate batch send campaign.xlsx --sheet Sheet1 --map phone=Phone,text=Message
# Send with custom delimiter and no header
smsgate batch send data.csv --delimiter ';' --header=false --map phone=col_1,text=col_2Batch-specific options:
| Option | Description | Default Value | Example |
|---|---|---|---|
--sheet |
Sheet name (defaults to first sheet) | empty | Sheet1 |
--delimiter |
CSV delimiter character | , |
; |
--header |
Treat first row as header | true |
false |
--map |
Column mapping (required) | required | phone=Phone,text=Message |
--dry-run |
Validate and print normalized rows without sending | false |
true |
--validate-only |
Validate input only (no preview, no sending) | false |
true |
--concurrency |
Number of concurrent send workers | CPU cores | 5 |
--continue-on-error |
Continue sending after per-row failures | false |
true |
Inherited message options:
The shared delivery/device options from the send command are also available (e.g., --device-id, --sim-number, --priority, --ttl, --valid-until, --delivery-report, --skip-phone-validation, --device-active-within). These apply to every message sent in the batch.
Column mapping:
The --map option defines how columns in your file map to message fields:
| Field | Required | Description |
|---|---|---|
phone |
✅ | Phone number column |
text |
✅ | Message text column |
id |
❌ | Message ID column (UUID generated when empty) |
device_id |
❌ | Device identifier column |
sim_number |
❌ | SIM number column (1-255) |
priority |
❌ | Message priority column (-128 to 127) |
Mapping examples:
# Basic mapping with headers
smsgate batch send --map phone=Phone,text=Message contacts.csv
# Excel file with specific sheet
smsgate batch send --sheet Sheet1 --map phone=Phone,text=Message campaign.xlsx
# No headers, column positions
smsgate batch send --header=false --map phone=col_1,text=col_2 data.csv
# Full mapping with optional fields
smsgate batch send --map phone=Phone,text=Message,device_id=Device,sim_number=SIM,priority=Priority contacts.csvFile format examples:
CSV with Headers:
Phone,Message,Device,Priority
+12025550123,"Hello Dr. Turk!",device1,1
+12025550124,"Hello Dr. Smith!",device1,2
+12025550125,"Hello Dr. Jones!",device2,1CSV without Headers:
+12025550123,"Hello Dr. Turk!",device1,1
+12025550124,"Hello Dr. Smith!",device1,2
+12025550125,"Hello Dr. Jones!",device2,1Excel Files:
- Supports multiple sheets (use
--sheetto specify) - First row treated as headers by default
- Column mapping works the same as CSV
Workflow modes:
-
Validation Only - Validates file format and column mapping, checks required fields, exits without sending:
smsgate batch send --map phone=Phone,text=Message --validate-only contacts.csv
-
Dry Run - Validates and processes all rows, shows what would be sent without actually sending:
smsgate batch send --map phone=Phone,text=Message --dry-run contacts.csv
-
Full Send - Sends all messages with real-time progress:
smsgate batch send --map phone=Phone,text=Message --concurrency=5 contacts.csv
Output and error handling:
- Summary:
Batch send summary: total=100 enqueued=95 failed=3 skipped=2 - Real-time progress: Shows each message's UUID and state during sending
- Error handling: By default stops on first error; use
--continue-on-errorto send all rows even if some fail
Best practices:
- Always use
--dry-runor--validate-onlyfirst to test your configuration - Ensure phone numbers are in E.164 format
- Start with lower concurrency values and increase as needed
- Use
--continue-on-errorfor non-critical bulk sends - Combine with inherited message options (e.g.,
--device-id,--priority) for advanced scenarios
# Get the status of a sent message
smsgate status zXDYfTmTVf3iMd16zzdBj# Register a webhook for SMS received events
smsgate webhooks register -e sms:received https://example.com/webhook
# Register a device-specific webhook
smsgate webhooks register -e sms:sent --device-id device123 https://example.com/webhook
# List all registered webhooks
smsgate webhooks list
# Delete a webhook by ID
smsgate webhooks delete <webhook-id>Supported webhook events: sms:received, sms:sent, sms:failed, device:connected, device:disconnected
The logs command retrieves logs for a specific time range. Dates should be in RFC3339 format (e.g., 2024-01-15T10:30:00Z).
# Get logs for the last 24 hours (default)
smsgate logs
# Get logs for a specific time range
smsgate logs --from '2024-01-15T00:00:00Z' --to '2024-01-15T23:59:59Z'
# Get logs with custom time range and output format
smsgate --format json logs --from '2024-01-15T10:00:00+07:00' --to '2024-01-15T18:00:00+07:00'Text
ID: zXDYfTmTVf3iMd16zzdBj
State: Pending
IsHashed: false
IsEncrypted: false
Recipients:
+12025550123 Pending
+12025550124 Pending
JSON
{
"id": "zXDYfTmTVf3iMd16zzdBj",
"state": "Pending",
"isHashed": false,
"isEncrypted": false,
"recipients": [
{
"phoneNumber": "+12025550123",
"state": "Pending"
},
{
"phoneNumber": "+12025550124",
"state": "Pending"
}
],
"states": {}
}Raw
{"id":"zXDYfTmTVf3iMd16zzdBj","state":"Pending","isHashed":false,"isEncrypted":false,"recipients":[{"phoneNumber":"+12025550123","state":"Pending"},{"phoneNumber":"+12025550124","state":"Pending"}],"states":{}}Table
ID EVENT URL DEVICE ID
123e4567-e89b-12d3-a456-426614174000 sms:received https://example.com/webhook dev-abc
def45678-e89b-12d3-a456-426614174000 sms:sent https://example.com/other
The smsgate-ca tool issues TLS certificates for private deployments. It generates ECDSA P-256 certificates signed by the SMS Gateway CA.
smsgate-ca [global flags] <command> [command flags] [arguments]| Flag | Aliases | Env Var | Default | Description |
|---|---|---|---|---|
--timeout |
-t |
ASG_CA_TIMEOUT |
30s |
Request timeout |
Issue a TLS certificate for a webhook receiver running on a private IP address.
smsgate-ca webhooks <ip-address> --out server.crt --keyout server.keyIssue a TLS certificate for a private server running on a private IP address.
smsgate-ca private <ip-address> --out server.crt --keyout server.key| Flag | Default | Description |
|---|---|---|
--out |
server.crt |
Certificate output file |
--keyout |
server.key |
Private key output file |
Note: The IP address must be a private/RFC 1918 address (e.g., 10.x.x.x, 172.16.x.x, 192.168.x.x).
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!
- Fork the Project
- Create your Feature Branch (
git checkout -b feature/AmazingFeature) - Commit your Changes (
git commit -m 'Add some AmazingFeature') - Push to the Branch (
git push origin feature/AmazingFeature) - Open a Pull Request
Distributed under the Apache-2.0 license. See LICENSE for more information.
Android is a trademark of Google LLC.