# Notify Africa Python SMS SDK
A Python SDK for integrating with Notify Africa SMS service, allowing developers to easily send SMS messages through their Python applications.
## Features
- ✅ **Authentication** - API key and sender ID management
- 📤 **Send Single SMS** - Send SMS to individual recipients
- 📦 **Send Bulk SMS** - Send SMS to multiple recipients
- 🕒 **Send Scheduled SMS** - Schedule SMS for future delivery
- 📁 **Excel Integration** - Send SMS from Excel files
- 📊 **Delivery Reports** - Check SMS delivery status
- 🛠️ **Developer Friendly** - Type hints, error handling, and comprehensive documentation
## Installation
```bash
pip install notify-africa-sms
```
## Quick Start
```python
from notify_africa import NotifyAfricaClient
# Initialize client
client = NotifyAfricaClient(
api_key="your_api_key_here",
sender_id="NOTIFYAFRICA"
)
# Send a single SMS
response = client.send_sms(
phone_number="255712345678",
message="Hello from Notify Africa!"
)
print(f"SMS sent: {response.success}")
print(f"Message: {response.message}")
print(f"Balance: {response.balance}")
```
## Usage Examples
### Send Single SMS
```python
response = client.send_sms(
phone_number="255712345678",
message="Hello, this is a test message!"
)
if response.success:
print(f"SMS sent successfully! ID: {response.sms_id}")
print(f"Credits used: {response.credits_spent}")
print(f"Remaining balance: {response.balance}")
else:
print(f"Failed to send SMS: {response.message}")
```
### Send Bulk SMS
```python
phone_numbers = [
"255712345678",
"255687654321",
"255756789012"
]
response = client.send_bulk_sms(
phone_numbers=phone_numbers,
message="Bulk SMS message to all recipients"
)
print(f"Total messages: {response.total_messages}")
print(f"Successful: {response.successful_messages}")
print(f"Failed: {response.failed_messages}")
```
### Send Scheduled SMS
```python
from datetime import datetime, timedelta
# Schedule SMS for tomorrow at 10:00 AM
schedule_time = datetime.now() + timedelta(days=1)
schedule_time = schedule_time.replace(hour=10, minute=0, second=0)
response = client.send_scheduled_sms(
phone_numbers=["255712345678"],
message="This is a scheduled message",
schedule_time=schedule_time
)
print(f"Scheduled SMS: {response.success}")
```
### Send SMS from Excel File
Create an Excel file with columns: `phone`, `names`, `message` (optional)
```python
# Using message template with name placeholder
response = client.send_sms_from_excel(
file_path="contacts.xlsx",
message_template="Hello {names}, welcome to our service!",
phone_column="phone",
names_column="names"
)
# Or using individual messages from Excel
response = client.send_sms_from_excel(
file_path="contacts.xlsx",
message_column="message",
phone_column="phone"
)
print(f"Sent {response.successful_messages} out of {response.total_messages} SMS")
```
### Check SMS History
```python
history = client.get_sms_history(records=50)
print(f"Retrieved {len(history.get('data', []))} SMS records")
```
### Get Sender IDs
```python
sender_ids = client.get_sender_ids()
for sender in sender_ids:
print(f"Sender ID: {sender.name} - Status: {sender.status}")
```
## SMS Status and History Tracking
The Notify Africa Python SDK provides comprehensive methods to track SMS delivery status and retrieve SMS history.
### Check SMS History
Retrieve your SMS sending history with detailed information about each message:
```python
# Get recent SMS history (default: 50 records)
history = client.get_sms_history()
# Get specific number of records
history = client.get_sms_history(records=100)
# Process the history data
messages = history.get('data', [])
print(f"Total messages retrieved: {len(messages)}")
for message in messages:
print(f"SMS ID: {message.get('id')}")
print(f"Recipient: {message.get('recipient')}")
print(f"Message: {message.get('sms')}")
print(f"Status: {message.get('status_id')}")
print(f"Status Description: {message.get('status_description')}")
print(f"Credits Used: {message.get('credits')}")
print(f"Sent At: {message.get('created_at')}")
print(f"Sender ID: {message.get('sender_id')}")
print("-" * 40)
```
### Check Individual SMS Status
Check the delivery status of a specific SMS using its ID:
```python
# Get SMS ID from send response
response = client.send_sms("255712345678", "Test message")
sms_id = response.sms_id
# Check delivery status
status = client.get_delivery_status(sms_id)
if status:
print(f"SMS ID: {status.sms_id}")
print(f"Recipient: {status.recipient}")
print(f"Status: {status.status}")
print(f"Description: {status.status_description}")
print(f"Credits: {status.credits}")
else:
print("SMS not found or status unavailable")
```
### SMS Status Codes
The following status codes are commonly returned:
| Status Code | Description |
|-------------|-------------|
| `pending` | SMS is queued for delivery |
| `sent` | SMS has been sent to the carrier |
| `delivered` | SMS was successfully delivered |
| `failed` | SMS delivery failed |
| `expired` | SMS expired before delivery |
| `rejected` | SMS was rejected by the carrier |
### Advanced History Filtering
```python
# Get comprehensive SMS history with filtering
def get_filtered_sms_history(client, days_back=7, status_filter=None):
"""
Get filtered SMS history
Args:
client: NotifyAfricaClient instance
days_back: Number of days to look back
status_filter: Filter by specific status (optional)
"""
from datetime import datetime, timedelta
# Get recent history (API typically returns newest first)
history = client.get_sms_history(records=500)
messages = history.get('data', [])
# Filter by date range
cutoff_date = datetime.now() - timedelta(days=days_back)
filtered_messages = []
for msg in messages:
try:
# Parse message date
msg_date = datetime.fromisoformat(
msg.get('created_at', '').replace('Z', '+00:00')
)
# Check if within date range
if msg_date >= cutoff_date:
# Apply status filter if specified
if status_filter is None or msg.get('status_id') == status_filter:
filtered_messages.append(msg)
except:
continue
return filtered_messages
# Usage examples
recent_messages = get_filtered_sms_history(client, days_back=7)
failed_messages = get_filtered_sms_history(client, days_back=30, status_filter='failed')
delivered_messages = get_filtered_sms_history(client, days_back=7, status_filter='delivered')
print(f"Recent messages (7 days): {len(recent_messages)}")
print(f"Failed messages (30 days): {len(failed_messages)}")
print(f"Delivered messages (7 days): {len(delivered_messages)}")
```
### Bulk Status Checking
Check status for multiple SMS messages:
```python
def check_bulk_sms_status(client, sms_ids):
"""
Check status for multiple SMS messages
Args:
client: NotifyAfricaClient instance
sms_ids: List of SMS IDs to check
"""
results = []
for sms_id in sms_ids:
status = client.get_delivery_status(sms_id)
if status:
results.append({
'sms_id': status.sms_id,
'recipient': status.recipient,
'status': status.status,
'description': status.status_description
})
else:
results.append({
'sms_id': sms_id,
'status': 'not_found',
'description': 'SMS not found in history'
})
return results
# Usage
sms_ids = ['123', '124', '125'] # Your SMS IDs
statuses = check_bulk_sms_status(client, sms_ids)
for status in statuses:
print(f"SMS {status['sms_id']}: {status['status']} - {status['description']}")
```
### Real-time Status Monitoring
Monitor SMS delivery in real-time:
```python
import time
from datetime import datetime
def monitor_sms_delivery(client, sms_id, timeout=300):
"""
Monitor SMS delivery status until delivered or timeout
Args:
client: NotifyAfricaClient instance
sms_id: SMS ID to monitor
timeout: Maximum time to wait in seconds (default: 5 minutes)
"""
start_time = time.time()
while time.time() - start_time < timeout:
status = client.get_delivery_status(sms_id)
if status:
print(f"[{datetime.now().strftime('%H:%M:%S')}] SMS {sms_id}: {status.status}")
# Check if final status reached
if status.status in ['delivered', 'failed', 'expired', 'rejected']:
return status
time.sleep(10) # Wait 10 seconds before checking again
print(f"Timeout reached for SMS {sms_id}")
return None
# Usage
response = client.send_sms("255712345678", "Test message")
if response.success:
final_status = monitor_sms_delivery(client, response.sms_id)
if final_status:
print(f"Final status: {final_status.status}")
```
### Export SMS History
Export SMS history to different formats:
```python
import pandas as pd
from datetime import datetime
def export_sms_history(client, records=1000, format='csv'):
"""
Export SMS history to file
Args:
client: NotifyAfricaClient instance
records: Number of records to export
format: Export format ('csv', 'excel', 'json')
"""
# Get SMS history
history = client.get_sms_history(records=records)
messages = history.get('data', [])
if not messages:
print("No SMS history found")
return
# Create DataFrame
df = pd.DataFrame(messages)
# Generate filename with timestamp
timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
if format.lower() == 'csv':
filename = f"sms_history_{timestamp}.csv"
df.to_csv(filename, index=False)
elif format.lower() == 'excel':
filename = f"sms_history_{timestamp}.xlsx"
df.to_excel(filename, index=False)
elif format.lower() == 'json':
filename = f"sms_history_{timestamp}.json"
df.to_json(filename, orient='records', indent=2)
print(f"SMS history exported to: {filename}")
return filename
# Usage
export_sms_history(client, records=500, format='excel')
```
### Error Handling for Status Checks
```python
from notify_africa.exceptions import (
AuthenticationError,
NetworkError,
NotifyAfricaException
)
def safe_status_check(client, sms_id):
"""Safely check SMS status with error handling"""
try:
status = client.get_delivery_status(sms_id)
return status
except AuthenticationError:
print("Authentication failed - check your API key")
return None
except NetworkError as e:
print(f"Network error: {e}")
return None
except NotifyAfricaException as e:
print(f"API error: {e}")
return None
except Exception as e:
print(f"Unexpected error: {e}")
return None
def safe_history_check(client, records=50):
"""Safely get SMS history with error handling"""
try:
history = client.get_sms_history(records=records)
return history.get('data', [])
except AuthenticationError:
print("Authentication failed - check your API key")
return []
except NetworkError as e:
print(f"Network error: {e}")
return []
except NotifyAfricaException as e:
print(f"API error: {e}")
return []
except Exception as e:
print(f"Unexpected error: {e}")
return []
# Usage
status = safe_status_check(client, "123")
messages = safe_history_check(client, 100)
```
Raw data
{
"_id": null,
"home_page": "https://github.com/notify-africa/python-sdk",
"name": "notify-africa-sms",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.7",
"maintainer_email": null,
"keywords": "sms, tanzania, api, sdk, notify-africa",
"author": "Notify Africa",
"author_email": "support@notifyafrica.com",
"download_url": "https://files.pythonhosted.org/packages/8a/c8/f7947118c1f83e4cfc604ea52d4dc85bd555d836f9d12e6a9316f7739630/notify_africa_sms-1.0.0.tar.gz",
"platform": null,
"description": "# Notify Africa Python SMS SDK\n\nA Python SDK for integrating with Notify Africa SMS service, allowing developers to easily send SMS messages through their Python applications.\n\n## Features\n\n- \u2705 **Authentication** - API key and sender ID management\n- \ud83d\udce4 **Send Single SMS** - Send SMS to individual recipients\n- \ud83d\udce6 **Send Bulk SMS** - Send SMS to multiple recipients\n- \ud83d\udd52 **Send Scheduled SMS** - Schedule SMS for future delivery\n- \ud83d\udcc1 **Excel Integration** - Send SMS from Excel files\n- \ud83d\udcca **Delivery Reports** - Check SMS delivery status\n- \ud83d\udee0\ufe0f **Developer Friendly** - Type hints, error handling, and comprehensive documentation\n\n## Installation\n\n```bash\npip install notify-africa-sms\n```\n\n## Quick Start\n\n```python\nfrom notify_africa import NotifyAfricaClient\n\n# Initialize client\nclient = NotifyAfricaClient(\n api_key=\"your_api_key_here\",\n sender_id=\"NOTIFYAFRICA\"\n)\n\n# Send a single SMS\nresponse = client.send_sms(\n phone_number=\"255712345678\",\n message=\"Hello from Notify Africa!\"\n)\n\nprint(f\"SMS sent: {response.success}\")\nprint(f\"Message: {response.message}\")\nprint(f\"Balance: {response.balance}\")\n```\n\n## Usage Examples\n\n### Send Single SMS\n\n```python\nresponse = client.send_sms(\n phone_number=\"255712345678\", \n message=\"Hello, this is a test message!\"\n)\n\nif response.success:\n print(f\"SMS sent successfully! ID: {response.sms_id}\")\n print(f\"Credits used: {response.credits_spent}\")\n print(f\"Remaining balance: {response.balance}\")\nelse:\n print(f\"Failed to send SMS: {response.message}\")\n```\n\n### Send Bulk SMS\n\n```python\nphone_numbers = [\n \"255712345678\",\n \"255687654321\", \n \"255756789012\"\n]\n\nresponse = client.send_bulk_sms(\n phone_numbers=phone_numbers,\n message=\"Bulk SMS message to all recipients\"\n)\n\nprint(f\"Total messages: {response.total_messages}\")\nprint(f\"Successful: {response.successful_messages}\")\nprint(f\"Failed: {response.failed_messages}\")\n```\n\n### Send Scheduled SMS\n\n```python\nfrom datetime import datetime, timedelta\n\n# Schedule SMS for tomorrow at 10:00 AM\nschedule_time = datetime.now() + timedelta(days=1)\nschedule_time = schedule_time.replace(hour=10, minute=0, second=0)\n\nresponse = client.send_scheduled_sms(\n phone_numbers=[\"255712345678\"],\n message=\"This is a scheduled message\",\n schedule_time=schedule_time\n)\n\nprint(f\"Scheduled SMS: {response.success}\")\n```\n\n### Send SMS from Excel File\n\nCreate an Excel file with columns: `phone`, `names`, `message` (optional)\n\n```python\n# Using message template with name placeholder\nresponse = client.send_sms_from_excel(\n file_path=\"contacts.xlsx\",\n message_template=\"Hello {names}, welcome to our service!\",\n phone_column=\"phone\",\n names_column=\"names\"\n)\n\n# Or using individual messages from Excel\nresponse = client.send_sms_from_excel(\n file_path=\"contacts.xlsx\",\n message_column=\"message\",\n phone_column=\"phone\"\n)\n\nprint(f\"Sent {response.successful_messages} out of {response.total_messages} SMS\")\n```\n\n### Check SMS History\n\n```python\nhistory = client.get_sms_history(records=50)\nprint(f\"Retrieved {len(history.get('data', []))} SMS records\")\n```\n\n### Get Sender IDs\n\n```python\nsender_ids = client.get_sender_ids()\nfor sender in sender_ids:\n print(f\"Sender ID: {sender.name} - Status: {sender.status}\")\n```\n\n## SMS Status and History Tracking\n\nThe Notify Africa Python SDK provides comprehensive methods to track SMS delivery status and retrieve SMS history.\n\n### Check SMS History\n\nRetrieve your SMS sending history with detailed information about each message:\n\n```python\n# Get recent SMS history (default: 50 records)\nhistory = client.get_sms_history()\n\n# Get specific number of records\nhistory = client.get_sms_history(records=100)\n\n# Process the history data\nmessages = history.get('data', [])\nprint(f\"Total messages retrieved: {len(messages)}\")\n\nfor message in messages:\n print(f\"SMS ID: {message.get('id')}\")\n print(f\"Recipient: {message.get('recipient')}\")\n print(f\"Message: {message.get('sms')}\")\n print(f\"Status: {message.get('status_id')}\")\n print(f\"Status Description: {message.get('status_description')}\")\n print(f\"Credits Used: {message.get('credits')}\")\n print(f\"Sent At: {message.get('created_at')}\")\n print(f\"Sender ID: {message.get('sender_id')}\")\n print(\"-\" * 40)\n```\n\n### Check Individual SMS Status\n\nCheck the delivery status of a specific SMS using its ID:\n\n```python\n# Get SMS ID from send response\nresponse = client.send_sms(\"255712345678\", \"Test message\")\nsms_id = response.sms_id\n\n# Check delivery status\nstatus = client.get_delivery_status(sms_id)\n\nif status:\n print(f\"SMS ID: {status.sms_id}\")\n print(f\"Recipient: {status.recipient}\")\n print(f\"Status: {status.status}\")\n print(f\"Description: {status.status_description}\")\n print(f\"Credits: {status.credits}\")\nelse:\n print(\"SMS not found or status unavailable\")\n```\n\n### SMS Status Codes\n\nThe following status codes are commonly returned:\n\n| Status Code | Description |\n|-------------|-------------|\n| `pending` | SMS is queued for delivery |\n| `sent` | SMS has been sent to the carrier |\n| `delivered` | SMS was successfully delivered |\n| `failed` | SMS delivery failed |\n| `expired` | SMS expired before delivery |\n| `rejected` | SMS was rejected by the carrier |\n\n### Advanced History Filtering\n\n```python\n# Get comprehensive SMS history with filtering\ndef get_filtered_sms_history(client, days_back=7, status_filter=None):\n \"\"\"\n Get filtered SMS history\n \n Args:\n client: NotifyAfricaClient instance\n days_back: Number of days to look back\n status_filter: Filter by specific status (optional)\n \"\"\"\n from datetime import datetime, timedelta\n \n # Get recent history (API typically returns newest first)\n history = client.get_sms_history(records=500)\n messages = history.get('data', [])\n \n # Filter by date range\n cutoff_date = datetime.now() - timedelta(days=days_back)\n filtered_messages = []\n \n for msg in messages:\n try:\n # Parse message date\n msg_date = datetime.fromisoformat(\n msg.get('created_at', '').replace('Z', '+00:00')\n )\n \n # Check if within date range\n if msg_date >= cutoff_date:\n # Apply status filter if specified\n if status_filter is None or msg.get('status_id') == status_filter:\n filtered_messages.append(msg)\n except:\n continue\n \n return filtered_messages\n\n# Usage examples\nrecent_messages = get_filtered_sms_history(client, days_back=7)\nfailed_messages = get_filtered_sms_history(client, days_back=30, status_filter='failed')\ndelivered_messages = get_filtered_sms_history(client, days_back=7, status_filter='delivered')\n\nprint(f\"Recent messages (7 days): {len(recent_messages)}\")\nprint(f\"Failed messages (30 days): {len(failed_messages)}\")\nprint(f\"Delivered messages (7 days): {len(delivered_messages)}\")\n```\n\n### Bulk Status Checking\n\nCheck status for multiple SMS messages:\n\n```python\ndef check_bulk_sms_status(client, sms_ids):\n \"\"\"\n Check status for multiple SMS messages\n \n Args:\n client: NotifyAfricaClient instance\n sms_ids: List of SMS IDs to check\n \"\"\"\n results = []\n \n for sms_id in sms_ids:\n status = client.get_delivery_status(sms_id)\n if status:\n results.append({\n 'sms_id': status.sms_id,\n 'recipient': status.recipient,\n 'status': status.status,\n 'description': status.status_description\n })\n else:\n results.append({\n 'sms_id': sms_id,\n 'status': 'not_found',\n 'description': 'SMS not found in history'\n })\n \n return results\n\n# Usage\nsms_ids = ['123', '124', '125'] # Your SMS IDs\nstatuses = check_bulk_sms_status(client, sms_ids)\n\nfor status in statuses:\n print(f\"SMS {status['sms_id']}: {status['status']} - {status['description']}\")\n```\n\n### Real-time Status Monitoring\n\nMonitor SMS delivery in real-time:\n\n```python\nimport time\nfrom datetime import datetime\n\ndef monitor_sms_delivery(client, sms_id, timeout=300):\n \"\"\"\n Monitor SMS delivery status until delivered or timeout\n \n Args:\n client: NotifyAfricaClient instance\n sms_id: SMS ID to monitor\n timeout: Maximum time to wait in seconds (default: 5 minutes)\n \"\"\"\n start_time = time.time()\n \n while time.time() - start_time < timeout:\n status = client.get_delivery_status(sms_id)\n \n if status:\n print(f\"[{datetime.now().strftime('%H:%M:%S')}] SMS {sms_id}: {status.status}\")\n \n # Check if final status reached\n if status.status in ['delivered', 'failed', 'expired', 'rejected']:\n return status\n \n time.sleep(10) # Wait 10 seconds before checking again\n \n print(f\"Timeout reached for SMS {sms_id}\")\n return None\n\n# Usage\nresponse = client.send_sms(\"255712345678\", \"Test message\")\nif response.success:\n final_status = monitor_sms_delivery(client, response.sms_id)\n if final_status:\n print(f\"Final status: {final_status.status}\")\n```\n\n### Export SMS History\n\nExport SMS history to different formats:\n\n```python\nimport pandas as pd\nfrom datetime import datetime\n\ndef export_sms_history(client, records=1000, format='csv'):\n \"\"\"\n Export SMS history to file\n \n Args:\n client: NotifyAfricaClient instance\n records: Number of records to export\n format: Export format ('csv', 'excel', 'json')\n \"\"\"\n # Get SMS history\n history = client.get_sms_history(records=records)\n messages = history.get('data', [])\n \n if not messages:\n print(\"No SMS history found\")\n return\n \n # Create DataFrame\n df = pd.DataFrame(messages)\n \n # Generate filename with timestamp\n timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')\n \n if format.lower() == 'csv':\n filename = f\"sms_history_{timestamp}.csv\"\n df.to_csv(filename, index=False)\n elif format.lower() == 'excel':\n filename = f\"sms_history_{timestamp}.xlsx\"\n df.to_excel(filename, index=False)\n elif format.lower() == 'json':\n filename = f\"sms_history_{timestamp}.json\"\n df.to_json(filename, orient='records', indent=2)\n \n print(f\"SMS history exported to: {filename}\")\n return filename\n\n# Usage\nexport_sms_history(client, records=500, format='excel')\n```\n\n### Error Handling for Status Checks\n\n```python\nfrom notify_africa.exceptions import (\n AuthenticationError,\n NetworkError,\n NotifyAfricaException\n)\n\ndef safe_status_check(client, sms_id):\n \"\"\"Safely check SMS status with error handling\"\"\"\n try:\n status = client.get_delivery_status(sms_id)\n return status\n except AuthenticationError:\n print(\"Authentication failed - check your API key\")\n return None\n except NetworkError as e:\n print(f\"Network error: {e}\")\n return None\n except NotifyAfricaException as e:\n print(f\"API error: {e}\")\n return None\n except Exception as e:\n print(f\"Unexpected error: {e}\")\n return None\n\ndef safe_history_check(client, records=50):\n \"\"\"Safely get SMS history with error handling\"\"\"\n try:\n history = client.get_sms_history(records=records)\n return history.get('data', [])\n except AuthenticationError:\n print(\"Authentication failed - check your API key\")\n return []\n except NetworkError as e:\n print(f\"Network error: {e}\")\n return []\n except NotifyAfricaException as e:\n print(f\"API error: {e}\")\n return []\n except Exception as e:\n print(f\"Unexpected error: {e}\")\n return []\n\n# Usage\nstatus = safe_status_check(client, \"123\")\nmessages = safe_history_check(client, 100)\n```\n",
"bugtrack_url": null,
"license": null,
"summary": "Python SDK for Notify Africa SMS Service",
"version": "1.0.0",
"project_urls": {
"Bug Reports": "https://github.com/notify-africa/python-sdk/issues",
"Documentation": "https://docs.notifyafrica.com",
"Homepage": "https://github.com/notify-africa/python-sdk",
"Source": "https://github.com/notify-africa/python-sdk"
},
"split_keywords": [
"sms",
" tanzania",
" api",
" sdk",
" notify-africa"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "0e6d2e47df88f89369367b630d42669d2d7c33bcfbe6cf06fc95e508f1b87366",
"md5": "7cd4c4b4e32a038cc8839c808d7cd48d",
"sha256": "daffae32e234b9d9002ca98eed21d5fe8235d5c6893b5907b979e51edc00fec8"
},
"downloads": -1,
"filename": "notify_africa_sms-1.0.0-py3-none-any.whl",
"has_sig": false,
"md5_digest": "7cd4c4b4e32a038cc8839c808d7cd48d",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.7",
"size": 15736,
"upload_time": "2025-07-15T14:53:22",
"upload_time_iso_8601": "2025-07-15T14:53:22.107872Z",
"url": "https://files.pythonhosted.org/packages/0e/6d/2e47df88f89369367b630d42669d2d7c33bcfbe6cf06fc95e508f1b87366/notify_africa_sms-1.0.0-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "8ac8f7947118c1f83e4cfc604ea52d4dc85bd555d836f9d12e6a9316f7739630",
"md5": "0618e2124b12f30ba25d6d6f7b1dbbf4",
"sha256": "51b77cb171939e3921ae6f31068141c72eaaa5554aea40c9e0b5eb47788c039c"
},
"downloads": -1,
"filename": "notify_africa_sms-1.0.0.tar.gz",
"has_sig": false,
"md5_digest": "0618e2124b12f30ba25d6d6f7b1dbbf4",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.7",
"size": 18095,
"upload_time": "2025-07-15T14:53:25",
"upload_time_iso_8601": "2025-07-15T14:53:25.288555Z",
"url": "https://files.pythonhosted.org/packages/8a/c8/f7947118c1f83e4cfc604ea52d4dc85bd555d836f9d12e6a9316f7739630/notify_africa_sms-1.0.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-07-15 14:53:25",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "notify-africa",
"github_project": "python-sdk",
"github_not_found": true,
"lcname": "notify-africa-sms"
}