Skip to main content

SDK oficial Python para a API de SMS da SMSGo — envie SMS, OTP e campanhas no Brasil em minutos.

Project description

smsgo (Python)

PyPI Python CI license

SDK oficial Python para a SMSGo — a API de SMS simples para o Brasil. Envie OTP/2FA, alertas transacionais e campanhas com poucas linhas.

  • Integra em minutos — autenticação cuidada pra você (sem ritual de token manual).
  • 💸 Sem mensalidade — créditos pré-pagos que não expiram, preço em real.
  • 🇧🇷 Brasil-first — entrega para todas as operadoras, LGPD nativo.
  • 🟢 Zero dependências — usa só a biblioteca padrão. Tipado (py.typed).
  • 🎁 R$ 10 grátis ao criar a conta — dá pra testar sem cartão.

Nova conta e chave em smsgo.com.br → painel → Minha conta → API.

Paridade total com o SDK oficial Node.js: mesmos métodos, mapeamentos de campo, autenticação e erros.

Instalação

pip install smsgo

Requer Python 3.8+.

Começo rápido

import os
from smsgo import SMSGo

smsgo = SMSGo(api_key=os.environ["SMSGO_KEY"])

result = smsgo.send(
    phone="+5511999990000",
    message="Olá do SMSGo 👋",
)

print(result.id, result.status)  # -> "a1b2c3...", "queued"

Você passa só a api_key. O SDK troca a chave por um token Bearer (válido 48h), guarda em cache e renova sozinho quando expira ou retorna 401.

Enviar um OTP (2FA)

import random
from smsgo import SMSGo, SMSGoError

smsgo = SMSGo(api_key="...")
code = f"{random.randint(0, 999999):06d}"  # 6 dígitos

try:
    smsgo.send(phone="+5511999990000", message=f"Seu código SMSGo é {code}. Válido por 5 minutos.")
    # guarde `code` com TTL (ex.: Redis) e compare na verificação
except SMSGoError as err:
    print(err.status, err.code, err.message)

Envio em massa

smsgo.send_bulk(
    messages=[
        {"phone": "+5511999990000", "message": "Oi, Ana!"},
        {"phone": "+5521988887777", "message": "Oi, Bruno!"},
    ],
    url_callback="https://seuapp.com/webhooks/smsgo",  # status de entrega (opcional)
)

Consultar envios

page = smsgo.list(page=1)                 # Paginated(meta, data=[SendListItem, ...])
detail = smsgo.get("a1b2c3-...")          # SendDetail com summary de acompanhamento
print(detail.summary.delivered, detail.summary.done)

# Números de um envio, filtrando por bucket de status:
nums = smsgo.get_numbers("a1b2c3-...", status="failed", page=1)  # delivered|failed|in_progress

Modo de teste (sandbox)

Use a chave de teste (prefixo test_, no painel → Minha conta → API) como api_key. Nada muda no código: os envios não debitam saldo nem são despachados de verdade, as respostas são idênticas às de produção (com test=True) e os webhooks disparam com o mesmo flag.

sandbox = SMSGo(api_key=os.environ["SMSGO_TEST_KEY"])
print(sandbox.resolve_mode())  # 'test'  (ou use a propriedade `sandbox.mode`)
r = sandbox.send(phone="+5511999990000", message="teste")
print(r.test)  # True

mode retorna None antes da 1ª chamada autenticada; resolve_mode() força a resolução.

Saldo e catálogo

balance = smsgo.get_balance()
print(balance.balance, balance.currency)          # 42.50 'BRL'
print(balance.company["name"])

for t in smsgo.get_sms_types():                   # catálogo (id vai em sms_type_id)
    print(t.id, t.name, t.sale or t.price)

Comprar créditos + recarga automática

billing.purchase cobra um cartão salvo off-session. Informe quantity ou plan_id; sem card_id, usa o cartão padrão.

⚠️ Não é idempotente: cada chamada gera uma cobrança nova. Em timeout, consulte smsgo.billing.invoices() antes de repetir — não faça retry cego.

plans = smsgo.billing.plans()      # pacotes (tiers)
cards = smsgo.billing.cards()      # cartões salvos (4 últimos dígitos)

receipt = smsgo.billing.purchase(quantity=1000, card_id=cards[0].id)
print(receipt.status)   # 'succeeded' já creditou o saldo | 'processing' confirma via webhook
print(receipt.invoice_uuid, receipt.total)

# Recarga automática + alerta de saldo:
smsgo.set_auto_recharge(
    enabled=True,
    threshold=10,          # recarrega quando o saldo <= R$ 10
    plan_quantity=1000,    # compra 1000 créditos a cada recarga
    card_id=cards[0].id,   # obrigatório p/ ligar
    alert_enabled=True,
    alert_threshold=15,    # e-mail quando o saldo <= R$ 15
)
cfg = smsgo.get_auto_recharge()

Webhooks de saída (DLR + respostas)

# Define a URL que recebe `sms.status` (DLR) e `sms.reply` (resposta). Guarde o secret.
cfg = smsgo.set_webhook(url="https://seuapp.com/webhooks/smsgo")
print(cfg.url, cfg.secret)

smsgo.set_webhook(rotate_secret=True)   # gira o segredo
smsgo.set_webhook(url="")               # desativa

Cada requisição traz X-SMSGo-Signature: sha256=<hmac> — o HMAC-SHA256 do corpo bruto com o seu secret. Valide sempre com o helper embutido (comparação em tempo constante, nunca levanta exceção):

from smsgo import verify_webhook_signature

# raw_body: bytes/str exatamente como recebido (NÃO reparseie antes de validar)
ok = verify_webhook_signature(raw_body, request.headers["X-SMSGo-Signature"], secret)
if not ok:
    return "invalid signature", 401

Servidor completo em examples/receive_dlr_webhook.py.

Contatos e listas

list_id = smsgo.lists.create(name="Clientes VIP").id
contact_id = smsgo.contacts.create(
    full_name="Ana Souza",
    phone="+5511999990000",
    email="ana@exemplo.com",
    lists=[list_id],
)

smsgo.contacts.list(page=1, search="ana")   # Paginated(meta, data)
smsgo.contacts.update(contact_id, full_name="Ana S.", phone="+5511999990000")
smsgo.contacts.delete(contact_id)

Tratamento de erros

Toda resposta não-2xx vira um SMSGoError com status e um code estável:

from smsgo import SMSGo, SMSGoError

try:
    smsgo.send(phone="+5511999990000", message="Olá")
except SMSGoError as err:
    if err.code == "insufficient_balance":  # 402 — sem saldo
        ...
    elif err.code == "rate_limited":        # 429 — muitas requisições
        ...
    elif err.code == "validation_error":    # 422 — detalhe por campo
        for fe in err.errors or []:
            print(fe.field, fe.message)
    else:
        print(err.status, err.code, err.message)
code HTTP Significado
bad_request 400 Requisição malformada
unauthorized 401 Chave/token inválido
insufficient_balance 402 Saldo insuficiente
provider_out_of_stock 409 Estoque do provedor indisponível
validation_error 422 Dados do request inválidos
rate_limited 429 Limite de envios atingido
payment_unavailable 503 Pagamento temporariamente fora
network_error 0 Falha de rede/transporte

Referência

SMSGo(api_key, *, base_url=..., timeout=30.0)

Parâmetro Tipo Default Descrição
api_key str Obrigatório. Sua SMSGo-key.
base_url str https://api.smsgo.com.br Não precisa mexer; só se a SMSGo orientar.
timeout float 30.0 Timeout das requisições (s).

Métodos (cliente)

  • send(phone, message, *, schedule=None, reference=None, sender=None, sms_type_id=None)SendResult
  • send_bulk(messages, *, url_callback=None, flash_sms=None, sms_type_id=None)SendResult
  • list(page=1)Paginated[SendListItem]
  • get(id)SendDetail
  • get_numbers(id, *, status=None, page=None)Paginated[SendNumberItem]
  • get_sms_types()list[SmsTypeItem]
  • get_balance()Balance
  • get_auto_recharge()AutoRechargeConfig
  • set_auto_recharge(*, enabled=None, threshold=None, plan_quantity=None, card_id=None, alert_enabled=None, alert_threshold=None)AutoRechargeConfig
  • get_webhook() / set_webhook(*, url=None, rotate_secret=None)WebhookConfig
  • resolve_mode()'live' | 'test' · propriedade mode'live' | 'test' | None

sender é mapeado para o campo from da API (palavra reservada em Python).

smsgo.contacts

  • list(*, page, per_page=None, search=None, title=None)Paginated
  • create(*, full_name, phone, email=None, lists=None)str (UUID)
  • get(id)ContactDetail · update(id, *, full_name, phone, email=None, lists=None)str · delete(id)dict

smsgo.lists

  • list(*, page, per_page=None, title=None)Paginated
  • create(*, name) / get(id) / update(id, *, name)ListResult · delete(id)dict

smsgo.billing

  • plans()list[Plan] · cards()list[Card]
  • invoices(*, page=None, per_page=None)Paginated[InvoiceItem]
  • purchase(*, quantity=None, plan_id=None, card_id=None, coupon=None)PurchaseResult (não idempotente)

Módulo

  • verify_webhook_signature(raw_body, signature_header, secret)bool — valida X-SMSGo-Signature em tempo constante.

Exemplos

Na pasta examples/:

SMSGO_KEY=suachave python examples/send_sms.py +5511999990000
SMSGO_KEY=suachave python examples/send_otp.py +5511999990000
SMSGO_KEY=suachave python examples/check_status.py
SMSGO_KEY=suachave python examples/check_balance.py
SMSGO_KEY=suachave python examples/buy_credits.py
SMSGO_KEY=suachave python examples/configure_webhook.py https://seuapp.com/webhooks/smsgo
SMSGO_WEBHOOK_SECRET=whsec_... python examples/receive_dlr_webhook.py

Migrando da TotalVoice / Twilio?

SMSGo foca em DX simples e preço em real. Sem cadastro de remetente pra começar, sem cobrança em dólar, créditos que não expiram. Há também o SDK oficial Node.js.

Licença

MIT © SMSGo

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

smsgo-0.3.0.tar.gz (22.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

smsgo-0.3.0-py3-none-any.whl (15.7 kB view details)

Uploaded Python 3

File details

Details for the file smsgo-0.3.0.tar.gz.

File metadata

  • Download URL: smsgo-0.3.0.tar.gz
  • Upload date:
  • Size: 22.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for smsgo-0.3.0.tar.gz
Algorithm Hash digest
SHA256 d59d9acfcbe210f4eace6b4f8c1aa853382ffa3f89b067d3d1d450bb23ceee42
MD5 e247c8ea1f83b016fe48f189689d59c6
BLAKE2b-256 6643c11490d2b0fa15cc0cd0436113a5b777067b9c6fb61cdbad39b32e025f2f

See more details on using hashes here.

Provenance

The following attestation bundles were made for smsgo-0.3.0.tar.gz:

Publisher: publish.yml on sms-go/smsgo-sdk-python

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file smsgo-0.3.0-py3-none-any.whl.

File metadata

  • Download URL: smsgo-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 15.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for smsgo-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 948ad4bf473bd43973f66fc09bf1ceb910119e9f8d5471e18e478c730621f337
MD5 fe2b3f5b66447a6709125744e1f1d46f
BLAKE2b-256 dd85f1f83d238227f8a2db08fb65fdb891eef2cd4fb80de93f4b9752c8f3489b

See more details on using hashes here.

Provenance

The following attestation bundles were made for smsgo-0.3.0-py3-none-any.whl:

Publisher: publish.yml on sms-go/smsgo-sdk-python

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page