SMS API in Python: Full Integration Tutorial
Most Python SMS guides rank because they answer fast: import requests, requests.post, done. This tutorial covers everything those pages skip.
What breaks real Python SMS integrations:
No default timeout in requests A stalled socket blocks a Gunicorn worker or Celery process forever. Always pass timeout=(connect, read).
json= versus data= The SMSGatewayCenter endpoint expects application/x-www-form-urlencoded. Passing json= sets the wrong Content-Type and fails like an auth error.
statusCode type instability Quoted string on SMSApi/send, integer on WAApi/send. Use pydantic models at the boundary.
urllib3 Retry on POST Automatic retries on non-idempotent POST double-sends and double-bills.
asyncio.gather pitfalls Unbounded fan-out plus first-exception cancellation discards successful results.
Celery acks_late without idempotency Worker crash redelivers tasks and sends duplicate OTPs.
Form-encoded webhooks in FastAPI Pydantic JSON body models do not apply to form-encoded DLR pushes.
GSM-7 vs UCS-2 One curly apostrophe can triple SMS cost. Count segments before send.
India DLT Mandatory for Indian A2P traffic. Positional variable substitution in one pass, not chained str.replace.
Four-layer architecture:
Configuration and credentials (.env, apiKey)
HTTP client (httpx or requests Session with timeouts)
Typed responses (pydantic)
Celery for production async sending
Also covered: OTP sending, failure classification before retry, DLR polling, official Python SDK, security checklist, pytest with respx.
Prerequisites: Python 3.11+, approved sender ID, DLT registration for India.
pip install httpx pydantic tenacity celery redis fastapi uvicorn python-dotenv
Full walkthrough with copy-paste code: https://www.smsgatewaycenter.com/blog/sms-api-python-integration-tutorial/













