mupag-sdk
SDK oficial Python para integrar backends, automacoes, scripts e notebooks com a API publica da MuPag.
Ele foi desenhado para deixar o caminho feliz curto: instala, cria um cliente com sk_test_*, chama mupag.charges.create(...) e recebe um objeto tipado. Sem montar httpx na mao, sem decorar header de idempotencia, sem parsing manual de erro, sem validar webhook no improviso.
Por que integrar com a SDK é simples
- API com cara de produto:
mupag.charges.create(...),mupag.subscriptions.cancel(..., mode="immediate")emupag.webhooks.construct_event(...). - Tipos Pydantic v2 para validar request/response cedo, ainda no seu codigo.
- Cliente sync e async com a mesma ergonomia.
- Idempotencia automatica em operacoes mutaveis e chave explicita para identificar a operacao de negocio.
- Retry interno com a mesma chave para 429/5xx,
Retry-Afterlimitado e backoff curto. - Erros tipados com
code,suggestion,documentation_urlerequest_id, prontos para log/suporte. - Webhook HMAC-SHA256 em tempo constante, com janela anti-replay padrao de 5 minutos.
O resultado esperado para quem integra e: poucas linhas para receber um PIX de teste e informacoes suficientes para resolver erro sem abrir ticket.
Instalação
pip install mupag-sdk
Migração da SDK MuPay
Substitua pip install mupay-sdk por pip install mupag-sdk e atualize os imports de
from mupay_sdk para from mupag_sdk. A API pública permanece a mesma nesta migração.
Requisitos:
- Python 3.10 ou superior.
- Uma API key
sk_test_*ousk_prd_*. - Dependencias runtime pequenas:
httpx,pydanticv2 etenacity.
Quickstart
from mupag_sdk import MuPagClient
mupag = MuPagClient(api_key="sk_test_...", environment="test")
charge = mupag.charges.create(
amount_cents=12000,
payment_method="pix",
customer={
"id": "22222222-2222-4222-8222-222222222222",
"name": "Ana Silva",
"email": "ana@example.com",
"tax_id": "12345678901",
},
idempotency_key="order_123_charge_1",
)
print(charge.pix_emv_code)
Cliente async
from mupag_sdk import AsyncMuPagClient
async def main() -> None:
async with AsyncMuPagClient(api_key="sk_test_...", environment="test") as mupag:
charge = await mupag.charges.create(
amount_cents=12000,
payment_method="pix",
customer={
"id": "22222222-2222-4222-8222-222222222222",
"name": "Ana Silva",
"email": "ana@example.com",
"tax_id": "12345678901",
},
)
print(charge.charge_id)
Erros tipados
Erros HTTP da API viram MuPagAPIError. O erro preserva status_code, code, suggestion, documentation_url e request_id quando a API envia Problem Details.
A chave automatica e reutilizada apenas nos retries internos da mesma invocacao. Se uma mutacao
puder ter sido aceita e a resposta final se perder, o SDK levanta MuPagOutcomeUnknownError com
outcome_unknown=True e a idempotency_key efetivamente enviada. Persista essa chave e reconcilie
ou repita exatamente o mesmo payload. Para pagamentos, prefira uma chave derivada do ID imutavel da
operacao de negocio desde a primeira chamada.
Retries limitados cobrem transporte, 408, 425, 429, 5xx e
409/idempotency_in_progress, sempre com a mesma chave, backoff exponencial com jitter e
Retry-After limitado. 409/idempotency_outcome_unknown gera unknown imediatamente;
fingerprint_conflict e os demais 4xx nao classificados como ambiguos so sao definitivos quando
nenhuma tentativa anterior ficou ambigua. A ambiguidade e sticky: apenas um 2xx parseavel e economicamente valido confirma a
mutacao; um 4xx, 409 ou 429 posterior nao a apaga.
from mupag_sdk import MuPagClient
from mupag_sdk.errors import MuPagAPIError, MuPagOutcomeUnknownError
mupag = MuPagClient(api_key="sk_test_...", environment="test")
try:
mupag.charges.create(
amount_cents=12000,
payment_method="credit_card",
card_token="tok_test",
payer_ip="203.0.113.10",
customer={
"id": "22222222-2222-4222-8222-222222222222",
"name": "Ana Silva",
"email": "ana@example.com",
"tax_id": "12345678901",
},
)
except MuPagOutcomeUnknownError as exc:
persist_for_reconciliation(exc.idempotency_key)
except MuPagAPIError as exc:
print(exc.code, exc.request_id, exc.suggestion)
Em cartão, payer_ip é o IP literal do pagador observado no checkout e atestado pelo merchant,
nunca o IP do servidor que chama a MuPag. O contrato atual aceita uma parcela, rejeita
soft_descriptor e falha fechado quando o merchant exige 3DS.
Webhooks
Valide a assinatura antes de confiar no payload. O helper usa HMAC-SHA256 em tempo constante e bloqueia replay fora da janela configurada.
from mupag_sdk.webhooks import construct_event
event = construct_event(
request_body,
request_headers["mupag-signature"],
"whsec_...",
)
print(event.type)
O header canonico e MuPag-Signature, e o corpo validado segue { "id": string, "type": string, "data": object }.
Cancelamento de assinatura
O SDK envia o mesmo payload exigido pela API publica: mode é obrigatório e reason é opcional.
from mupag_sdk import MuPagClient
mupag = MuPagClient(api_key="sk_test_...", environment="test")
subscription = mupag.subscriptions.cancel(
"sub_123",
mode="immediate",
reason="cliente pediu cancelamento",
)
print(subscription.status)
Fluxo completo em menos de 5 minutos
- Instale o pacote:
pip install mupag-sdk. - Crie uma API key sandbox no dashboard da MuPag.
- Exporte a chave:
set MUPAG_API_KEY=sk_test_...no Windows ouexport MUPAG_API_KEY=sk_test_...no Linux/macOS. - Rode
python examples/create_pix_charge.py. - Copie o
pix_emv_coderetornado para simular pagamento no sandbox.
Essa e a experiencia que a SDK precisa proteger: o integrador nao deve precisar conhecer headers internos, formato exato de Problem Details ou detalhes de retry para criar a primeira cobranca.
Exemplos completos
examples/create_pix_charge.pyexamples/async_create_charge.pyexamples/verify_webhook.py
Desenvolvimento local
python -m pip install -e .[dev]
python -m pytest
python -m coverage run -m pytest
python -m coverage report
python -m mypy .
python -m ruff check .
Publicação PyPI manual
Este PR não adiciona build/publicação automática no GitHub Actions. A publicação pública inicial deve ser manual para evitar release acidental enquanto o contrato da API ainda está amadurecendo.
Para publicar publicamente:
- Crie conta e verifique email em PyPI e TestPyPI.
- Garanta que o nome
mupag-sdkestá disponível ou que a organização MuPag controla esse nome. - Atualize
versionempyproject.tomlusando versionamento semântico. - Rode a validação local:
python -m pip install -e .[dev]
python -m ruff check .
python -m mypy .
python -m coverage run -m pytest
python -m coverage report
uv build
- Publique primeiro no TestPyPI:
python -m pip install twine
python -m twine upload --repository testpypi dist/*
- Instale em ambiente limpo e rode um smoke test:
python -m pip install --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple/ mupag-sdk
python -c "from mupag_sdk import MuPagClient; print(MuPagClient)"
- Se o smoke test passar, publique no PyPI:
python -m twine upload dist/*
Use token de API com escopo limitado ao projeto mupag-sdk quando o projeto já existir. Nunca coloque token PyPI em código, README, commit ou workflow.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file mupag_sdk-0.2.0.tar.gz.
File metadata
- Download URL: mupag_sdk-0.2.0.tar.gz
- Upload date:
- Size: 37.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e97c857bb086805374abc8865c39003b653293d9580c94662e8a8d5dc4f5bc12
|
|
| MD5 |
16cbb6812ebc9b7af33ae8d5e8c6fb0e
|
|
| BLAKE2b-256 |
300477a0d8c8575e7d4ce65115ce8eda78a7f2eea26ea5be8e910a01a8b6ff42
|
File details
Details for the file mupag_sdk-0.2.0-py3-none-any.whl.
File metadata
- Download URL: mupag_sdk-0.2.0-py3-none-any.whl
- Upload date:
- Size: 20.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
07e85a6779b76be5dbbec6f10c35434a4caf168ee041179a320d0ded2151c2ee
|
|
| MD5 |
6708b777690716dd6e55b6651eefc1c6
|
|
| BLAKE2b-256 |
738f01acb202e1c3114690fa7cb7e1d96b0f1a036243323632e87867fe75fdad
|