Django SDK for SignalBridge SMS Gateway
Project description
SignalBridge Django SDK
Official Django SDK for SignalBridge SMS Gateway - Send SMS through multiple vendors with a unified API.
Features
- Unified SMS API - Single interface for multiple SMS vendors (SpeedaMobile, Africa's Talking, etc)
- Batch Sending - Send bulk SMS efficiently with detailed results
- Balance Management - Real-time balance tracking and transaction history
- Segment Calculation - Automatic GSM 7-bit vs Unicode detection and cost estimation
- Django Integration - Native Django settings, logging, and session support
- Management Commands - CLI tools for common SMS operations
- Session Pooling - HTTP session reuse for optimal performance
- Typed Exceptions - Specific exceptions for different error scenarios
Installation
pip install signalbridge-django
Add to your Django INSTALLED_APPS:
# settings.py
INSTALLED_APPS = [
# ...
'signalbridge',
]
# SignalBridge Configuration
SIGNALBRIDGE_TOKEN = 'your-api-token-here'
Or use environment variables:
# .env
SIGNALBRIDGE_TOKEN=your-api-token-here
Quick Start
Basic SMS Sending
from signalbridge.client import get_client
client = get_client()
# Send single SMS
result = client.send_sms(
recipient='256700000000',
message='Hello from SignalBridge!'
)
print(result['message']) # "SMS queued successfully"
In Django Views
from django.http import JsonResponse
from django.views import View
from signalbridge.client import get_client
from signalbridge.exceptions import SignalBridgeException
class SendSMSView(View):
def post(self, request):
try:
client = get_client()
result = client.send_sms(
recipient=request.POST.get('phone'),
message=request.POST.get('message')
)
return JsonResponse({
'success': True,
'message': result['message']
})
except SignalBridgeException as e:
return JsonResponse({
'success': False,
'message': str(e)
}, status=500)
Real-World Use Cases
1. OTP Verification System
from django.views import View
from django.http import JsonResponse
from django.views.decorators.csrf import csrf_exempt
from django.utils.decorators import method_decorator
import random
from signalbridge.client import get_client
class SendOTPView(View):
@method_decorator(csrf_exempt)
def post(self, request):
phone = request.POST.get('phone')
otp = random.randint(100000, 999999)
# Store in session
request.session['otp'] = str(otp)
request.session['otp_phone'] = phone
client = get_client()
result = client.send_sms(
recipient=phone,
message=f'Your verification code is {otp}. Valid for 5 minutes.',
metadata={'purpose': 'otp'}
)
return JsonResponse({
'success': True,
'message': 'OTP sent successfully'
})
class VerifyOTPView(View):
@method_decorator(csrf_exempt)
def post(self, request):
submitted = request.POST.get('otp')
stored = request.session.get('otp')
if submitted == stored:
del request.session['otp']
return JsonResponse({'success': True, 'message': 'Verified'})
else:
return JsonResponse({'success': False, 'message': 'Invalid OTP'}, status=400)
2. Batch Student Notifications
from signalbridge.client import get_client
from signalbridge.exceptions import InsufficientBalanceException
def send_exam_results(students):
"""Send exam results to multiple students"""
messages = []
for student in students:
messages.append({
'recipient': student.phone,
'message': f"Dear {student.name}, your exam result: {student.marks}/100",
'metadata': {'student_id': student.id}
})
try:
client = get_client()
result = client.send_batch(messages)
print(f"Sent {result['data']['successful']} of {result['data']['total']} messages")
return result
except InsufficientBalanceException as e:
print(f"Need {e.get_required_balance()} UGX, have {e.get_current_balance()} UGX")
raise
3. Appointment Reminders with Balance Check
from signalbridge.client import get_client
def send_appointment_reminder(appointment):
client = get_client()
# Check balance first
balance = client.get_balance()
if balance['data']['balance'] < 100: # Minimum threshold
raise ValueError("Balance too low. Please top up.")
message = (
f"Reminder: Dear {appointment.patient_name}, "
f"you have an appointment with Dr. {appointment.doctor} "
f"on {appointment.date} at {appointment.time}."
)
result = client.send_sms(
recipient=appointment.phone,
message=message,
metadata={'appointment_id': appointment.id}
)
return result
4. Cost Estimator Before Sending
from signalbridge.client import get_client
def estimate_campaign_cost(message, recipient_count):
"""Calculate cost before sending bulk SMS"""
client = get_client()
# Get current pricing
balance = client.get_balance()
segment_price = balance['data']['segment_price']
# Calculate segments
segments = client.calculate_segments(message)
cost_per_message = client.estimate_cost(message, segment_price)
total_cost = cost_per_message * recipient_count
return {
'segments': segments,
'cost_per_message': cost_per_message,
'recipient_count': recipient_count,
'total_cost': total_cost,
'current_balance': balance['data']['balance'],
'sufficient': balance['data']['balance'] >= total_cost
}
# Usage
estimate = estimate_campaign_cost("Your message here", recipient_count=500)
print(f"Campaign will cost {estimate['total_cost']} for {estimate['recipient_count']} recipients")
5. Transaction History and Reporting
from signalbridge.client import get_client
from datetime import datetime, timedelta
def generate_monthly_report():
"""Generate SMS usage report for the past month"""
client = get_client()
end_date = datetime.now().strftime('%Y-%m-%d')
start_date = (datetime.now() - timedelta(days=30)).strftime('%Y-%m-%d')
transactions = client.get_transactions(
per_page=100,
transaction_type='debit', # Only SMS sends
start_date=start_date,
end_date=end_date
)
total_spent = sum(t['amount'] for t in transactions['data']['data'])
total_messages = len(transactions['data']['data'])
return {
'period': f"{start_date} to {end_date}",
'total_messages': total_messages,
'total_spent': total_spent,
'average_cost': total_spent / total_messages if total_messages > 0 else 0
}
Management Commands
The SDK includes Django management commands for CLI operations:
Send SMS from Command Line
python manage.py signalbridge_send_sms 256700000000 "Your message"
Check Balance
python manage.py signalbridge_check_balance --currency=UGX
Output:
Balance Summary
Currency: UGX
Balance: 50000.0
Credit Limit: 0.0
Segment Price: 50.0
View Transaction History
python manage.py signalbridge_transactions --page=1 --per-page=20 --type=debit
API Reference
Client Methods
send_sms(recipient, message, metadata=None, is_test=False, scheduled_at=None)
Send a single SMS message.
Parameters:
recipient(str): Phone number in international format (e.g., '256700000000')message(str): Message content (max 1000 characters)metadata(dict, optional): Custom data to store with messageis_test(bool): Flag as test message (won't be charged)scheduled_at(datetime, optional): Schedule for future sending
Returns: Dict with success, message, and data keys
send_batch(messages, is_test=False)
Send multiple SMS messages in one request.
Parameters:
messages(list): List of message dicts withrecipient,message, optionalmetadatais_test(bool): Mark all as test messages
Returns: Dict with total, successful, failed counts
get_balance(currency='UGX')
Get current balance for a currency.
Returns: Dict with balance, credit_limit, segment_price
get_balance_summary()
Get comprehensive balance summary with recent activity.
get_transactions(per_page=15, page=1, transaction_type=None, start_date=None, end_date=None)
Retrieve transaction history.
Parameters:
per_page(int): Results per page (1-100)page(int): Page numbertransaction_type(str): Filter by 'credit' or 'debit'start_date(str): Start date (YYYY-MM-DD)end_date(str): End date (YYYY-MM-DD)
calculate_segments(message)
Calculate number of SMS segments for a message.
Returns: int - Number of segments
estimate_cost(message, segment_price)
Estimate cost for sending a message.
Returns: float - Estimated cost
Exception Handling
The SDK provides specific exceptions for different scenarios:
from signalbridge.exceptions import (
InsufficientBalanceException,
ValidationException,
NoClientException,
ServiceUnavailableException,
SignalBridgeException
)
try:
client.send_sms(recipient='256700000000', message='Test')
except InsufficientBalanceException as e:
print(f"Balance: {e.get_current_balance()}")
print(f"Required: {e.get_required_balance()}")
print(f"Segments: {e.get_segments()}")
except ValidationException as e:
print(f"Errors: {e.get_errors()}")
print(f"First error: {e.get_first_error()}")
except NoClientException as e:
print("Client not found or unauthorized")
except ServiceUnavailableException as e:
print("Service temporarily unavailable")
except SignalBridgeException as e:
print(f"Error: {e.message}")
print(f"Status: {e.status_code}")
Configuration
Django Settings
# settings.py
# Required
SIGNALBRIDGE_TOKEN = 'your-api-token-here'
# Logging
LOGGING = {
'loggers': {
'signalbridge': {
'level': 'INFO',
'handlers': ['console'],
},
},
}
Environment Variables
SIGNALBRIDGE_TOKEN=your-api-token-here
Testing
from django.test import TestCase
from unittest.mock import patch, MagicMock
from signalbridge.client import SignalBridgeClient
class SMSTestCase(TestCase):
@patch('signalbridge.client.requests.Session')
def test_send_sms(self, mock_session):
# Mock API response
mock_response = MagicMock()
mock_response.status_code = 200
mock_response.json.return_value = {
'success': True,
'message': 'SMS queued successfully'
}
mock_session.return_value.request.return_value = mock_response
client = SignalBridgeClient(token='test-token')
result = client.send_sms('256700000000', 'Test message')
self.assertTrue(result['success'])
Requirements
- Python 3.8+
- Django 3.2+
- requests >= 2.25.0
Support
For issues and questions:
- Documentation: https://signal-bridge.nugsoftstagging.com/docs
License
MIT License - see LICENSE file for details.
Related SDKs
- Laravel SDK: nugsoft/signalbridge-laravel-sdk
- PHP SDK: nugsoft/signalbridge-php-sdk
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 signalbridge_django_sdk-1.0.0.tar.gz.
File metadata
- Download URL: signalbridge_django_sdk-1.0.0.tar.gz
- Upload date:
- Size: 19.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7a14c83e7e42272c6749471b73954600c0e74146286243794d371af2470f3419
|
|
| MD5 |
d30a5ff0fa0ea3340c977bbf4b1851b5
|
|
| BLAKE2b-256 |
675a7654c73aab8a3e1570a03cbc9a1e529d36843d2569c01c8ec7e52deb3741
|
File details
Details for the file signalbridge_django_sdk-1.0.0-py3-none-any.whl.
File metadata
- Download URL: signalbridge_django_sdk-1.0.0-py3-none-any.whl
- Upload date:
- Size: 12.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9a53e79a939050e960580e00af248456d89416698667babe5a3ff61ec0c3784f
|
|
| MD5 |
857fe5872aee2895e372b00a1d7fe596
|
|
| BLAKE2b-256 |
3af9158fac81ba62d667c617f0018000774eaea92ac433a143f3e63f86b8b2ca
|