smsgora
Python client for the SMS Gora SMS Gateway API.
SMS Gora turns Android phones with ordinary SIM cards into an SMS gateway. Your server calls the API, a linked phone sends the text, and replies and delivery reports come back to you. There's no sender ID registration and no per-message fee from us: your mobile operator bills the texts like any SMS.
- Zero dependencies (standard library only), Python 3.8+
- Works in Django, Flask, FastAPI, scripts and cron jobs
- Webhook signature check built in
Install
pip install smsgora
Quick start
Create an API key in the SMS Gora dashboard (SMS Gora -> API keys) and keep it on your server.
import os
from smsgora import SmsGora
sms = SmsGora(api_key=os.environ["SMSGORA_KEY"])
result = sms.send_sms(to="+15551234567", message="Your verification code is 482913")
print(result["message_ids"]) # [1873]
Sending
from datetime import datetime, timezone
# Several recipients (up to 1,000 per call)
sms.send_sms(to=["+15551234567", "+447700900123"], message="Your order has shipped")
# From a chosen phone and SIM, scheduled for later
sms.send_sms(
to="+15551234567",
message="Reminder: your appointment is tomorrow at 10:00",
device_id=42,
sim_slot=1, # 0 = SIM 1, 1 = SIM 2
schedule_at=datetime(2026, 12, 1, 8, 0, tzinfo=timezone.utc),
)
# Different texts for different people in one call (up to 5,000 recipients)
sms.send_bulk_sms(
42,
message_template="Hello, your parcel is ready for pickup.",
messages=[
{"recipients": ["+15551234567"], "message": "Hi Aline, parcel #1042 is ready."},
{"recipients": ["+15557654321"]},
],
)
Delivery status and incoming SMS
msg = sms.get_message(1873)
print(msg["status"]) # queued -> dispatched -> sent -> delivered (or failed)
sms.cancel_message(1874) # works while queued or scheduled
inbox = sms.list_received_sms(since="2026-11-01", limit=50)
phones = sms.list_devices()
account = sms.get_account()
Anything else in the API reference is one call away:
batch = sms.request("GET", "/batches/311")
Webhooks
Add your HTTPS URL in SMS Gora -> Webhooks (or with create_webhook) and keep the secret. Each request carries X-SmsGora-Signature: sha256=..., an HMAC-SHA256 of the raw body. Check it before trusting the request. Flask example:
import json, os
from flask import Flask, request, abort
from smsgora import verify_webhook
app = Flask(__name__)
@app.post("/sms/webhook")
def sms_webhook():
if not verify_webhook(request.get_data(), request.headers.get("X-SmsGora-Signature"),
os.environ["SMSGORA_WEBHOOK_SECRET"]):
abort(401)
event = json.loads(request.get_data())
if event["event"] == "sms.received":
print(event["data"]["from"], event["data"]["message"])
return "", 200 # answer within 10 seconds; queue slow work
In Django use request.body; in FastAPI use await request.body(). Always pass the raw bytes, not re-encoded JSON.
Errors
Failed calls raise SmsGoraError with status, message, field errors and, on 429, retry_after in seconds.
from smsgora import SmsGoraError
try:
sms.send_sms(to="+15551234567", message="Hi")
except SmsGoraError as err:
if err.status == 429:
pass # rate limit (300 requests/minute per key) or plan limit reached
Never ship the key inside a browser or mobile app: anyone could read it. Call the API from your server.
Migrating from TextBee
SMS Gora accepts TextBee-style requests, so most integrations switch by changing the base URL and key. See the compatibility notes.
Good to know
A phone-based gateway suits OTPs, order alerts, reminders and two-way conversations at moderate volume. It isn't meant for mass marketing blasts, and in the US high-volume business texting belongs on registered 10DLC or toll-free numbers.
More from Tekservix
- WAservix WhatsApp API Gateway: send WhatsApp messages from your own number (
pip install waservix) - AI Sales Agent: answers customers on WhatsApp and SMS using your website's content
- Website to App: turn your website into Android and iOS apps
- Also on npm:
npm install smsgora
License
MIT
Metadata
Release files for smsgora 1.0.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| smsgora-1.0.1.tar.gz | 7.9 kB | Without provenance | Details for smsgora-1.0.1.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| smsgora-1.0.1-py3-none-any.whl | Python 3 | none | any | Details for smsgora-1.0.1-py3-none-any.whl |
Total release size: 14.8 kB
Release files / smsgora-1.0.1.tar.gz
| Download URL | smsgora-1.0.1.tar.gz |
|---|---|
| Size | 7.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
9b2925778ac2aa078862a95cdd0fc2ebbfb89700edc98629c5ac1632b7d4b325
|
|
BLAKE2b-256 checksum How to use checksums |
4a0703b0f959f315b966439018c8f14ebc1a9c67878931054206000c84bd5102
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.8
|
Release files / smsgora-1.0.1-py3-none-any.whl
| Download URL | smsgora-1.0.1-py3-none-any.whl |
|---|---|
| Size | 6.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
27bb6bc993b343353c967a7c258c1d809c1d22a8c4f431edfdce9d25c3eb34d9
|
|
BLAKE2b-256 checksum How to use checksums |
d16be8578e9dbcc2ffb12378ee5fe3cfdc0739e5eb4d7ee361094cad0992c2c5
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.8
|
Security for smsgora 1.0.1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.