Skip to main content

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() hits POST /send-otp; template_key omitted when None
  • verify_otp() hits POST /verify-otp; all 400 error variants
  • status() hits GET /status/{reference_id}; all seven lifecycle values
  • Error body "error" key preferred over "message"; fallback to HTTP <code>
  • Network errors (ConnectionError, Timeout) raise GateWireException with status_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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

gatewire-1.1.0.tar.gz (8.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

gatewire-1.1.0-py3-none-any.whl (6.6 kB view details)

Uploaded Python 3

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

Hashes for gatewire-1.1.0.tar.gz
Algorithm Hash digest
SHA256 df8a6269892f58f2871cf3a51667f4279bfa6b557a1cc04638f077acdd9af317
MD5 928522d238cd1e494eeb170930d3c366
BLAKE2b-256 b9073d8e8cf32d956fc9245fbe8589d32f6ab6e39126c4621bd037647cebe89a

See more details on using hashes here.

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

Hashes for gatewire-1.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 d619bbdd1255703e06f0d0023ecedd3c7689274fcbc0bedcf3668139adb5a0b1
MD5 9dee593fc6879c681ce27e966272aa60
BLAKE2b-256 84ef8dc10628a95498bfbfd01b3b9e561312df3a4f124da410a2a17e2f4a810e

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page