Files
sms-api-wrapper/sms
chelsea db5bde0a70 first commit
Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-04 04:39:53 +00:00
..
2026-07-04 04:39:53 +00:00
2026-07-04 04:39:53 +00:00
2026-07-04 04:39:53 +00:00
2026-07-04 04:39:53 +00:00
2026-07-04 04:39:53 +00:00
2026-07-04 04:39:53 +00:00
2026-07-04 04:39:53 +00:00
2026-07-04 04:39:53 +00:00
2026-07-04 04:39:53 +00:00
2026-07-04 04:39:53 +00:00

sms — voip.ms SMS/MMS API façade

A small FastAPI service that wraps the voip.ms SMS/MMS REST API (https://voip.ms/api/v1/rest.php) behind typed Python + REST endpoints, with a per-day outbound send guard.

Files

File Purpose
config.py Settings (env-loaded creds, dialing mode, daily limit, timeout)
exceptions.py VoipMsError hierarchy (Auth, Api, RateLimit)
models.py Pydantic request/response models
client.py VoipMsSMSClient — async httpx wrappers for the 7 methods
guard.py DailySendCounter — UTC-day counter + send logging
app.py FastAPI app exposing the operations as REST endpoints
requirements.txt Dependencies

voip.ms prerequisites

  1. Enable the REST API and set an API password in the portal: Main Menu → SOAP / REST API → API Security.
  2. Whitelist this machine's public IP in the same API Security page.
  3. The DID you send from must have SMS enabled (Manage DIDs → Edit DID).
  4. Sending is capped at 100 SMS/MMS per day via the API. Pricing: $0.0075/SMS, $0.02/MMS, each direction.

Configure

export VOIPMS_API_USERNAME=...
export VOIPMS_API_PASSWORD=...
# optional overrides:
# export VOIPMS_BASE_URL=https://voip.ms/api/v1/rest.php
# export VOIPMS_DIALING_MODE=nanpa   # or e164
# export VOIPMS_DAILY_LIMIT=100
# export VOIPMS_TIMEOUT=30

(Settings also reads a .env file in the working directory.)

Run

pip install -r sms/requirements.txt
uvicorn sms.app:app --reload

Open http://127.0.0.1:8000/docs for the Swagger UI.

Endpoints

Method Path Upstream Guarded
POST /sms/send sendSMS
POST /mms/send sendMMS
GET /sms getSMS
GET /mms getMMS
GET /mms/{id}/media getMediaMMS
DELETE /sms/{id} deleteSMS
DELETE /mms/{id} deleteMMS
GET /health

Query params for GET /sms / GET /mms

from, to (YYYY-MM-DD), type (1=received / 0=sent), did, contact, limit, timezone (-12..13), all_messages (1=SMS+MMS combined, 0=single type; the message id must be 0 when set). For /sms the id query param is sms; for /mms it is id.

Error mapping

Condition HTTP Body
Daily limit exceeded 429 {detail, limit, used_today}
voip.ms returns non-success status 502 upstream message
Auth / IP-whitelist failure 500 upstream authentication failure (details logged server-side)

Notes & limitations

  • The daily counter is per-process. For multiple instances, swap DailySendCounter for a shared store (Redis, etc.).
  • Use https://voip.ms (not www.voip.ms) — the www host 302-redirects and drops POST bodies, producing missing_method errors.
  • Dialing mode normalizes did/dst on send: nanpa → 10 digits, e164+1 + 10 digits.
  • No markSMSRead method exists in the voip.ms API; read state is not manageable via REST.
  • Inbound URL Callback receiver is not included here; it can be added as a separate route set that replies with the literal ok and persists {TO}/{FROM}/{MESSAGE}/{ID}/{TIMESTAMP}/{MEDIA}.