
Security News
OWASP 2025 Top 10 Adds Software Supply Chain Failures, Ranked Top Community Concern
OWASP’s 2025 Top 10 introduces Software Supply Chain Failures as a new category, reflecting rising concern over dependency and build system risks.
textbelt-utils
Advanced tools
A lightweight Python package for interacting with the Textbelt SMS API. Send SMS messages, check delivery status, and handle webhook responses with a clean, type-hinted interface.
pip install textbelt-utils
from textbelt_utils import TextbeltClient, SMSRequest
# Initialize client
client = TextbeltClient(api_key="your_api_key")
# Send an SMS
request = SMSRequest(
phone="+1234567890",
message="Hello from textbelt-utils!",
key="your_api_key"
)
response = client.send_sms(request)
print(f"Message sent! ID: {response.text_id}")
from textbelt_utils import TextbeltClient, SMSRequest
client = TextbeltClient(api_key="your_api_key")
# Basic SMS
request = SMSRequest(
phone="+1234567890",
message="Hello!",
key="your_api_key"
)
# SMS with webhook for replies
request_with_webhook = SMSRequest(
phone="+1234567890",
message="Reply to this message!",
key="your_api_key",
reply_webhook_url="https://your-site.com/webhook",
webhook_data="custom_data"
)
# SMS with custom sender name
request_with_sender = SMSRequest(
phone="+1234567890",
message="Message from your company!",
key="your_api_key",
sender="MyCompany" # Set a custom sender name for this message
)
response = client.send_sms(request)
Send multiple SMS messages efficiently with rate limiting and batching:
from textbelt_utils import TextbeltClient, BulkSMSRequest
client = TextbeltClient(api_key="your_api_key")
# Send same message to multiple recipients
request = BulkSMSRequest(
phones=["+1234567890", "+1987654321"],
message="Broadcast message to all recipients!",
batch_size=100, # Process in batches of 100
delay_between_messages=0.1 # 100ms delay between messages
)
# Or send individual messages to each recipient
request = BulkSMSRequest(
phones=["+1234567890", "+1987654321"],
individual_messages={
"+1234567890": "Custom message for recipient 1",
"+1987654321": "Different message for recipient 2"
},
batch_size=100,
delay_between_messages=0.1
)
response = client.send_bulk_sms(request)
print(f"Total messages: {response.total_messages}")
print(f"Successful: {response.successful_messages}")
print(f"Failed: {response.failed_messages}")
# Check individual results
for phone, result in response.results.items():
if result.text_id:
status = client.check_status(result.text_id)
print(f"{phone}: {status.status}")
Send messages concurrently with proper rate limiting:
from textbelt_utils import AsyncTextbeltClient, BulkSMSRequest
import asyncio
async def send_bulk():
async with AsyncTextbeltClient(api_key="your_api_key") as client:
request = BulkSMSRequest(
phones=["+1234567890", "+1987654321"],
message="Async bulk message!",
batch_size=100, # Process 100 messages concurrently
delay_between_messages=0.1
)
response = await client.send_bulk_sms(request)
print(f"Sent: {response.successful_messages}")
print(f"Failed: {response.failed_messages}")
asyncio.run(send_bulk())
You can set a sender name for your SMS messages in two ways:
sender parameter in your SMSRequestThe sender name is used for compliance purposes and helps recipients identify who sent the message. If you don't specify a sender name, Textbelt will automatically append your default sender name to the message (unless it already appears in the message content).
# Example with custom sender name
request = SMSRequest(
phone="+1234567890",
message="Important update!",
key="your_api_key",
sender="MyCompany" # This overrides your account's default sender name
)
Note: The sender name is used strictly for compliance purposes and does not override the "From" number for the SMS sender.
status = client.check_status("text_id")
print(f"Message status: {status.status}") # DELIVERED, SENT, SENDING, etc.
quota = client.check_quota()
print(f"Remaining messages: {quota.quota_remaining}")
# Send a test message (doesn't use quota)
response = client.send_test(request)
from textbelt_utils.utils import verify_webhook
is_valid = verify_webhook(
api_key="your_api_key",
timestamp="webhook_timestamp",
signature="webhook_signature",
payload="webhook_payload"
)
The package provides built-in support for generating and verifying one-time passwords:
from textbelt_utils import AsyncTextbeltClient, OTPGenerateRequest, OTPVerifyRequest
async def handle_otp():
async with AsyncTextbeltClient(api_key="your_api_key") as client:
# Generate and send OTP
generate_request = OTPGenerateRequest(
phone="+1234567890",
userid="user@example.com", # Unique identifier for your user
key="your_api_key",
message="Your verification code is $OTP", # Optional custom message
lifetime=180, # Optional validity duration in seconds (default: 180)
length=6 # Optional code length (default: 6)
)
response = await client.generate_otp(generate_request)
print(f"OTP sent! Message ID: {response.text_id}")
# Later, verify the OTP entered by the user
verify_request = OTPVerifyRequest(
otp="123456", # Code entered by user
userid="user@example.com", # Same userid used in generate
key="your_api_key"
)
verify_response = await client.verify_otp(verify_request)
if verify_response.is_valid_otp:
print("OTP verified successfully!")
else:
print("Invalid OTP")
$OTP placeholder in your message to control where the code appearsThe package provides specific exceptions for different error cases:
from textbelt_utils.exceptions import (
QuotaExceededError,
InvalidRequestError,
WebhookVerificationError,
APIError
)
try:
response = client.send_sms(request)
except QuotaExceededError:
print("Out of quota!")
except InvalidRequestError as e:
print(f"Invalid request: {e}")
except WebhookVerificationError:
print("Webhook verification failed")
except APIError as e:
print(f"API error: {e}")
from textbelt_utils import AsyncTextbeltClient, SMSRequest
import asyncio
async def main():
async with AsyncTextbeltClient(api_key="your_api_key") as client:
# Send SMS
request = SMSRequest(
phone="+1234567890",
message="Async hello!",
key="your_api_key"
)
response = await client.send_sms(request)
# Check status
status = await client.check_status(response.text_id)
# Check quota
quota = await client.check_quota()
if __name__ == "__main__":
asyncio.run(main())
from textbelt_utils import TextbeltClient, AsyncTextbeltClient, SMSRequest
# Synchronous
sync_client = TextbeltClient(api_key="your_api_key")
sync_response = sync_client.send_sms(request)
# Asynchronous
async def send_async():
async with AsyncTextbeltClient(api_key="your_api_key") as client:
async_response = await client.send_sms(request)
cp .env.template .env
.env with your configuration:# Textbelt API Configuration
TEXTBELT_API_KEY=your_api_key_here
# Test Phone Numbers (E.164 format)
TEXTBELT_TEST_PHONE=your_test_phone_here
TEXTBELT_TEST_PHONE2=your_second_test_phone_here
The package automatically loads environment variables from your .env file on import. You can also explicitly load or reload configuration:
from textbelt_utils import load_config, get_env_var
# Load default .env file
load_config()
# Load specific env file
load_config(".env.test")
# Get environment variables with helpful error messages
api_key = get_env_var('TEXTBELT_API_KEY')
test_phone = get_env_var('TEXTBELT_TEST_PHONE')
# Get with default value
debug_mode = get_env_var('DEBUG', 'false')
For testing, you can use .env.test which contains safe test values:
# Use test environment
cp .env.test .env
# Or specify a different env file in code
load_config(".env.test")
poetry run python -m unittest discover tests
The package includes test scripts in the scripts directory to help you verify your Textbelt integration. To use them:
export TEXTBELT_API_KEY=your_api_key_here
export TEXTBELT_TEST_PHONE=your_phone_number_here # E.164 format, e.g., +1234567890
# Test basic SMS
poetry run python scripts/test_send.py
# Test async SMS
poetry run python scripts/test_send_async.py
# Test bulk SMS
poetry run python scripts/test_bulk_send.py
The scripts will:
The package also includes an OTP test script:
# Using environment variables
poetry run python scripts/test_otp.py
# Or provide values directly
poetry run python scripts/test_otp.py --phone +1234567890 --key your_api_key
.gitignore if you modify them with any sensitive datagit checkout -b feature/amazing-feature)git commit -m 'Add amazing feature')git push origin feature/amazing-feature)FAQs
A lightweight Python package for interacting with the Textbelt SMS API
We found that textbelt-utils demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
OWASP’s 2025 Top 10 introduces Software Supply Chain Failures as a new category, reflecting rising concern over dependency and build system risks.

Research
/Security News
Socket researchers discovered nine malicious NuGet packages that use time-delayed payloads to crash applications and corrupt industrial control systems.

Security News
Socket CTO Ahmad Nassri discusses why supply chain attacks now target developer machines and what AI means for the future of enterprise security.