Official Python SDK for the GateWire SMS Infrastructure.
Project description
GateWire Python SDK
The official Python library for the GateWire SMS Infrastructure.
Send OTPs to North African carriers (Mobilis, Djezzy, Ooredoo) using our decentralized mesh network.
Installation
pip install gatewire
Requires Python 3.10+ and requests>=2.28.
Quick Start
from gatewire import GateWireClient, GateWireException
gw = GateWireClient(api_key="YOUR_API_TOKEN")
# 1. Send OTP
res = gw.dispatch(phone="+213555123456", template_key="login_otp")
reference_id = res["reference_id"] # store this; you'll need it for verification
# 2. Verify the code the user entered
gw.verify_otp(reference_id=reference_id, code=user_input)
# 3. (Optional) Poll status yourself
info = gw.status(reference_id)
print(info["status"]) # pending | sent | verified | failed | expired
API Reference
GateWireClient(api_key, base_url=...)
Creates the client. A single requests.Session is opened and reused for all requests.
| Parameter | Type | Default | Description |
|---|---|---|---|
api_key |
str |
— | Your API token |
base_url |
str |
https://gatewire.raystate.com/api/v1 |
Override for tests |
dispatch(phone, template_key=None) -> dict
Send an OTP to a phone number.
| Parameter | Type | Required | Description |
|---|---|---|---|
phone |
str |
Yes | Recipient number in E.164 format (e.g. +213555123456) |
template_key |
str or None |
No | Template key configured in the dashboard. Omit to use the default template. |
Returns {"reference_id": "wg_01HX...", "status": "pending"}
Raises GateWireException — see Error Handling.
verify_otp(reference_id, code) -> dict
Verify the OTP code entered by the end-user.
| Parameter | Type | Required | Description |
|---|---|---|---|
reference_id |
str |
Yes | The reference_id returned by dispatch() |
code |
str |
Yes | The code the user submitted |
Returns {"status": "verified", "message": "Success"}
Raises GateWireException (HTTP 400) on wrong, expired, cancelled, or already-used codes.
status(reference_id) -> dict
Check the delivery status of an OTP.
| Parameter | Type | Required | Description |
|---|---|---|---|
reference_id |
str |
Yes | The reference_id returned by dispatch() |
Returns {"reference_id": "wg_01HX...", "status": "sent", "created_at": "2026-03-03T14:22:00Z"}
Possible status values: pending · dispatched · sent · verified · failed · expired · cancelled
Error Handling
Every non-2xx response raises GateWireException. Inspect e.status_code to branch on the cause.
from gatewire import GateWireClient, GateWireException
gw = GateWireClient(api_key="YOUR_API_TOKEN")
try:
res = gw.dispatch(phone="+213555123456")
reference_id = res["reference_id"]
except GateWireException as e:
if e.status_code == 402:
# Wallet is empty — direct the user to top up
print("Insufficient balance. Please top up your account.")
elif e.status_code == 429:
# Daily or hourly rate limit hit — back off and retry later
print(f"Rate limit reached: {e}")
elif e.status_code == 503:
# No devices are online right now — retry after a short delay
print("No devices available. Retrying in 30 s…")
else:
print(f"Unexpected error: {e}")
try:
gw.verify_otp(reference_id=reference_id, code=user_input)
except GateWireException as e:
if e.status_code == 400:
# Wrong code, already used, expired, or cancelled
print(f"Verification failed: {e}")
GateWireException attributes:
| Attribute | Type | Description |
|---|---|---|
args[0] |
str |
Human-readable error message from the API |
status_code |
int |
HTTP status code; 0 for network-level failures |
str(e) renders as [<status_code>] <message> (or just <message> for network errors).
OTP Lifecycle
dispatch()
│
▼
pending ──► dispatched ──► sent ──► verified ← happy path
│ │
▼ ▼
failed expired
│
▼
cancelled
Poll status() after dispatch() if you need to confirm delivery before asking the user for their code.
Framework Integration
Create one GateWireClient at module level and reuse it across requests. The underlying
requests.Session is thread-safe for concurrent reads.
Django (myapp/services.py):
from django.conf import settings
from gatewire import GateWireClient
gw = GateWireClient(api_key=settings.GATEWIRE_API_KEY)
Flask (app/__init__.py):
from flask import Flask
from gatewire import GateWireClient
app = Flask(__name__)
gw = GateWireClient(api_key=app.config["GATEWIRE_API_KEY"])
Then import gw wherever you need it — no need to instantiate it per request.
Development & Testing
Clone the repo and install the dev dependencies:
git clone https://github.com/md-lotfi/gatewire-python.git
cd gatewire-python
pip install -e ".[dev]"
Run the test suite:
pytest
The suite uses unittest.mock only — no network calls are made. All tests run in under a second.
Test coverage at a glance
| Module | Test file | Tests |
|---|---|---|
gatewire.exceptions |
tests/test_exceptions.py |
8 |
gatewire.client |
tests/test_client.py |
45 |
Key scenarios covered:
- Session created once; headers set correctly
dispatch()hitsPOST /send-otp;template_keyomitted whenNoneverify_otp()hitsPOST /verify-otp; all 400 error variantsstatus()hitsGET /status/{reference_id}; all seven lifecycle values- Error body
"error"key preferred over"message"; fallback toHTTP <code> - Network errors (
ConnectionError,Timeout) raiseGateWireExceptionwithstatus_code=0 - Invalid JSON response body handled gracefully
- Removed methods (
get_balance) and removed parameters (message,priority) confirmed absent
License
MIT — see LICENSE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file gatewire-1.1.0.tar.gz.
File metadata
- Download URL: gatewire-1.1.0.tar.gz
- Upload date:
- Size: 8.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
df8a6269892f58f2871cf3a51667f4279bfa6b557a1cc04638f077acdd9af317
|
|
| MD5 |
928522d238cd1e494eeb170930d3c366
|
|
| BLAKE2b-256 |
b9073d8e8cf32d956fc9245fbe8589d32f6ab6e39126c4621bd037647cebe89a
|
File details
Details for the file gatewire-1.1.0-py3-none-any.whl.
File metadata
- Download URL: gatewire-1.1.0-py3-none-any.whl
- Upload date:
- Size: 6.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d619bbdd1255703e06f0d0023ecedd3c7689274fcbc0bedcf3668139adb5a0b1
|
|
| MD5 |
9dee593fc6879c681ce27e966272aa60
|
|
| BLAKE2b-256 |
84ef8dc10628a95498bfbfd01b3b9e561312df3a4f124da410a2a17e2f4a810e
|