A modern Python client for seamless integration with the SMSGate API. Send SMS messages programmatically through your Android devices with this powerful yet simple-to-use library.
The Python client for SMSGate provides a clean, type-safe interface to interact with the SMSGate API. It's designed specifically for Python developers who need to integrate SMS functionality into their applications with minimal setup and maximum reliability.
Key value propositions:
- 🐍 Pythonic API - Designed with Python conventions and best practices in mind
- 🛡️ Robust Security - Guidance for secure credential handling and optional end‑to‑end encryption
- 🔄 Flexible Architecture - Supports both synchronous and asynchronous programming patterns
- 💻 Type Safety - Full type hinting for better developer experience and fewer runtime errors
- 🔗 Webhook Integration - Simplified webhook management for event-driven architectures
This client abstracts away the complexities of the underlying HTTP API while providing all the necessary functionality to send and track SMS messages through Android devices.
- 📱 SMS Gateway for Android™ Python API Client
- 🔄 Dual Client: Supports both synchronous (
APIClient) and asynchronous (AsyncAPIClient) interfaces - 🔐 Flexible Authentication: Supports both Basic Auth and JWT token authentication
- 🔒 End-to-End Encryption: Optional message encryption using AES-256-CBC
- 🌐 Multiple HTTP Backends: Native support for
requests,aiohttp, andhttpx - 🔗 Webhook Management: Programmatically create, query, and delete webhooks
- ⚙️ Customizable Base URL: Point to different API endpoints
- 💻 Full Type Hinting: Fully typed for better development experience
⚠️ Robust Error Handling: Specific exceptions and clear error messages- 📈 Delivery Reports: Track your message delivery status
- 🔑 Token Management: Generate and revoke JWT tokens with custom scopes and TTL
- Python: 3.9 or higher
- HTTP Client (choose one):
Optional Dependencies:
- 🔒 pycryptodome - For end-to-end encryption support
pip install android-sms-gateway# Choose an HTTP client: pip install android-sms-gateway[requests] # For synchronous use pip install android-sms-gateway[aiohttp] # For asynchronous use pip install android-sms-gateway[httpx] # For both synchronous and asynchronous use# For encrypted messages: pip install android-sms-gateway[encryption] # Or install everything: pip install android-sms-gateway[requests,encryption]-
Configure your credentials:
export SMSGATE_USERNAME="your_username" export SMSGATE_PASSWORD="your_password"
-
Basic usage example:
import asyncio import os from android_sms_gateway import client, domain # Configuration login = os.getenv("SMSGATE_USERNAME") password = os.getenv("SMSGATE_PASSWORD") # Create message message = domain.Message( phone_numbers=["+1234567890"], text_message=domain.TextMessage( text="Hello! This is a test message.", ), with_delivery_report=True, ) # Synchronous Client def sync_example(): with client.APIClient(login, password) as c: # Send message state = c.send(message) print(f"Message sent with ID: {state.id}") # Check status status = c.get_state(state.id) print(f"Status: {status.state}") # Asynchronous Client async def async_example(): async with client.AsyncAPIClient(login, password) as c: # Send message state = await c.send(message) print(f"Message sent with ID: {state.id}") # Check status status = await c.get_state(state.id) print(f"Status: {status.state}") if __name__ == "__main__": print("=== Synchronous Example ===") sync_example() print("\n=== Asynchronous Example ===") asyncio.run(async_example())from android_sms_gateway import client, domain, Encryptor # Encryption setup encryptor = Encryptor("my-super-secure-secret-passphrase") # Encrypted message message = domain.Message( phone_numbers=["+1234567890"], text_message=domain.TextMessage( text="This message will be encrypted!" ), ) # Client with encryption with client.APIClient(login, password, encryptor=encryptor) as c: state = c.send(message) print(f"Encrypted message sent: {state.id}")import os from android_sms_gateway import client, domain # Option 1: Using an existing JWT token jwt_token = os.getenv("ANDROID_SMS_GATEWAY_JWT_TOKEN") # Create client with JWT token with client.APIClient(login=None, password=jwt_token) as c: message = domain.Message( phone_numbers=["+1234567890"], text_message=domain.TextMessage( text="Hello from JWT authenticated client!", ), ) # Option 2: Generate a new JWT token with Basic Auth login = os.getenv("SMSGATE_USERNAME") password = os.getenv("SMSGATE_PASSWORD") with client.APIClient(login, password) as c: # Generate a new JWT token with specific scopes and TTL token_request = domain.TokenRequest( scopes=["sms:send", "sms:read"], ttl=3600 # Token expires in 1 hour ) token_response = c.generate_token(token_request) print(f"New JWT token: {token_response.access_token}") print(f"Token expires at: {token_response.expires_at}") # Use the new token for subsequent requests with client.APIClient(login=None, password=token_response.access_token) as jwt_client: message = domain.Message( phone_numbers=["+1234567890"], text_message=domain.TextMessage( text="Hello from newly generated JWT token!", ), ) state = jwt_client.send(message) print(f"Message sent with new JWT token: {state.id}") # Revoke the token when no longer needed jwt_client.revoke_token(token_response.id) print(f"Token {token_response.id} has been revoked")Both clients (APIClient and AsyncAPIClient) support these parameters:
| Parameter | Type | Description | Default |
|---|---|---|---|
login | str | API username | Required (for Basic Auth) |
password | str | API password or JWT token | Required |
base_url | str | API base URL | "https://api.sms-gate.app/3rdparty/v1" |
encryptor | Encryptor | Encryption instance | None |
http | HttpClient/AsyncHttpClient | Custom HTTP client | Auto-detected |
Authentication Options:
-
Basic Authentication (traditional):
client.APIClient(login="username", password="password")
-
JWT Token Authentication:
# Using an existing JWT token client.APIClient(login=None, password="your_jwt_token") # Or generate a token using Basic Auth first with client.APIClient(login="username", password="password") as c: token_request = domain.TokenRequest(scopes=["sms:send"], ttl=3600) token_response = c.generate_token(token_request) # Use the new token with client.APIClient(login=None, password=token_response.access_token) as jwt_client: # Make API calls with JWT authentication pass
| Method | Description | Return Type |
|---|---|---|
send(message: domain.Message) | Send SMS message | domain.MessageState |
get_state(id: str) | Check message status | domain.MessageState |
create_webhook(webhook: domain.Webhook) | Create new webhook | domain.Webhook |
get_webhooks() | List all webhooks | List[domain.Webhook] |
delete_webhook(id: str) | Delete webhook | None |
generate_token(token_request: domain.TokenRequest) | Generate JWT token | domain.TokenResponse |
revoke_token(jti: str) | Revoke JWT token | None |
class Message: message: str # Message text phone_numbers: List[str] # List of phone numbers with_delivery_report: bool = True # Delivery report is_encrypted: bool = False # Whether message is encrypted # Optional fields id: Optional[str] = None # Message ID ttl: Optional[int] = None # Time-to-live in seconds sim_number: Optional[int] = None # SIM numberclass MessageState: id: str # Unique message ID state: ProcessState # Current state (SENT, DELIVERED, etc.) recipients: List[RecipientState] # Per-recipient status is_hashed: bool # Whether message was hashed is_encrypted: bool # Whether message was encryptedclass Webhook: id: Optional[str] # Webhook ID url: str # Callback URL event: WebhookEvent # Event typeclass TokenRequest: scopes: List[str] # List of scopes for the token ttl: Optional[int] = None # Time to live for the token in secondsclass TokenResponse: access_token: str # The JWT access token token_type: str # The type of the token (e.g., 'Bearer') id: str # The unique identifier of the token (jti) expires_at: str # The expiration time of the token in ISO formatFor more details, see domain.py.
The library automatically detects installed HTTP clients with this priority:
| Client | Sync | Async |
|---|---|---|
| aiohttp | ❌ | 1️⃣ |
| requests | 1️⃣ | ❌ |
| httpx | 2️⃣ | 2️⃣ |
from android_sms_gateway import client, http # Force httpx usage client.APIClient(..., http=http.HttpxHttpClient()) # Force requests usage client.APIClient(..., http=http.RequestsHttpClient()) # Force aiohttp (async only) async with client.AsyncAPIClient(..., http_client=http.AiohttpHttpClient()) as c: # ...Implement your own HTTP client following the http.HttpClient (sync) or ahttp.AsyncHttpClient (async) protocols.
- 🔐 Credentials: Store credentials in environment variables
- 🚫 Code: Never expose credentials in client-side code
- 🔒 HTTPS: Use HTTPS for all production communications
- 🔑 Encryption: Use end-to-end encryption for sensitive messages
- 🔄 Rotation: Regularly rotate your credentials
When using JWT authentication, follow these additional security practices:
- ⏱️ Short TTL: Use short time-to-live (TTL) for tokens (recommended: 1 hour or less)
- 🔒 Secure Storage: Store JWT tokens securely, preferably in memory or secure storage
- 🎯 Minimal Scopes: Request only the minimum necessary scopes for each token
- 🔄 Token Rotation: Implement token refresh mechanisms before expiration
- 🛑 Revocation: Immediately revoke compromised tokens using
revoke_token()
import os from dotenv import load_dotenv # Load environment variables load_dotenv() # Secure configuration login = os.getenv("SMSGATE_USERNAME") password = os.getenv("SMSGATE_PASSWORD") if not login or not password: raise ValueError("Credentials not configured!")For complete API documentation including all available methods, request/response schemas, and error codes, visit: 📘 Official API Documentation
Contributions are very welcome! 🎉
- 🍴 Fork the repository
- 🌿 Create your feature branch (
git checkout -b feature/NewFeature) - 💾 Commit your changes (
git commit -m 'feat: add new feature') - 📤 Push to branch (
git push origin feature/NewFeature) - 🔄 Open a Pull Request
# Clone repository git clone https://github.com/android-sms-gateway/client-py.git cd client-py # Create virtual environment pipenv install --dev --categories encryption,requests pipenv shell- Code follows style standards (black, isort, flake8)
- Tests pass locally
- Documentation updated
- Test coverage maintained or improved
This project is licensed under the Apache License 2.0 - see LICENSE for details.
- 📧 Email: support@sms-gate.app
- 💬 Discord: SMS Gateway Community
- 📖 Documentation: docs.sms-gate.app
- 🐛 Issues: GitHub Issues
Note: Android is a trademark of Google LLC. This project is not affiliated with or endorsed by Google.