Python SDK para construir, firmar y timbrar CFDI 4.0 contra el API de ContaDB
Project description
contadb-sdk
SDK oficial de Python para construir, firmar y timbrar CFDI 4.0 contra el API público de ContaDB.
Consume timbres de tu bolsa prepagada usando un API token. Sin pagos por uso, sin contratos mensuales — solo timbra cuando lo necesites.
Instalación
pip install contadb-sdk
Requiere Python 3.10+.
Quickstart
from decimal import Decimal
from contadb_sdk import (
ContaDBClient,
CFDIBuilder,
Certificado,
Emisor,
Receptor,
Concepto,
)
# 1. Carga tu CSD (Certificado de Sello Digital del SAT)
cert = Certificado.cargar(
cer_path="emisor.cer",
key_path="emisor.key",
password="MI_PASSWORD",
)
# 2. Construye el CFDI
cfdi_xml = (
CFDIBuilder(
emisor=Emisor(
rfc="EKU9003173C9",
nombre="ESCUELA KEMPER URGATE",
regimen_fiscal="601",
),
receptor=Receptor(
rfc="URE180429TM6",
nombre="UNIVERSIDAD ROBOTICA ESPAÑOLA",
uso_cfdi="G03",
domicilio_fiscal_receptor="65000",
regimen_fiscal_receptor="601",
),
serie="A",
folio="1001",
forma_pago="03", # Transferencia electrónica
metodo_pago="PUE", # Pago en una sola exhibición
lugar_expedicion="64000",
)
.agregar_concepto(
Concepto(
clave_prod_serv="43232408",
clave_unidad="E48",
descripcion="Servicios de consultoría en sistemas",
cantidad=Decimal("1"),
valor_unitario=Decimal("1000.00"),
objeto_imp="02",
tasa_iva=Decimal("0.16"),
)
)
.construir_y_firmar(cert)
)
# 3. Timbra contra ContaDB
with ContaDBClient(api_token="cdb_TU_TOKEN_AQUI") as client:
resultado = client.timbrar(cfdi_xml)
print(f"UUID: {resultado.uuid}")
print(f"Saldo restante: {resultado.saldo_restante} timbres")
print(f"XML timbrado: {len(resultado.xml_timbrado)} chars")
Características
- ✅ Construcción CFDI 4.0 — Builder con API fluida, validación Pydantic, cálculo automático de impuestos.
- ✅ Firma RSA-SHA256 — Carga
.cer+.keydel SAT, firma cadena original generada con XSLT oficial. - ✅ Cliente HTTP tipado — Errores mapeados a excepciones específicas (
SaldoInsuficienteError,TokenRevocadoError, etc.). - ✅ Reintentos automáticos — Backoff exponencial con jitter en errores 429/5xx/red. Honra
Retry-After. Idempotency-Key resiste duplicados. - ✅ CFDI relacionados — Emite bloques
cfdi:CfdiRelacionados(sustitución, nota de crédito, devolución, etc.). - ✅ Complementos oficiales — Recepción de Pagos 2.0 y Carta Porte 3.1.
- ✅ Cancelación —
client.cancelar(uuid_cfdi, motivo, certificado, folio_sustitucion=...)con motivos SAT 01–04. - ✅ 100% tipado — Marcador
py.typedpara inferencia perfecta en IDEs ymypy --strict. - ✅ Cero dependencias mágicas — Solo
pydantic,httpx,cryptography,lxml.
Manejo de errores
from contadb_sdk import (
ContaDBClient,
SaldoInsuficienteError,
RateLimitError,
TokenRevocadoError,
)
try:
resultado = client.timbrar(xml)
except SaldoInsuficienteError:
# Comprar más timbres en https://contadb.mx/facturacion
...
except RateLimitError as e:
# El SDK ya reintentó automáticamente; aquí solo llegas si agotó los intentos.
# e.retry_after trae los segundos sugeridos por el servidor.
...
except TokenRevocadoError:
# Generar un nuevo token
...
Reintentos automáticos
El cliente reintenta solo en errores transitorios (HTTP 429, 500, 502, 503, 504 y fallos de red) con backoff exponencial + jitter. Cada reintento reusa el mismo Idempotency-Key, así que es seguro.
from contadb_sdk import ContaDBClient, RetryPolicy, RETRY_POLICY_NINGUNO
# Default: 3 intentos, backoff_factor=0.5, backoff_max=30s, honra Retry-After.
client = ContaDBClient(api_token="cdb_xxx")
# Personalizado:
client = ContaDBClient(
api_token="cdb_xxx",
retry_policy=RetryPolicy(max_intentos=5, backoff_factor=1.0, backoff_max=60.0),
)
# Sin reintentos (comportamiento de v1.0):
client = ContaDBClient(api_token="cdb_xxx", retry_policy=RETRY_POLICY_NINGUNO)
CFDI sustituto / nota de crédito / devolución
Para emitir un CFDI que referencia uno o varios CFDIs previos (sustitución tras cancelar con motivo 01, nota de crédito, devolución, etc.):
from contadb_sdk import CFDIBuilder, CfdiRelacionados
builder = CFDIBuilder(...).agregar_cfdi_relacionado(
tipo_relacion="04", # 04 = Sustitución de los CFDI previos
uuids=["550e8400-e29b-41d4-a716-446655440000"],
)
Catálogo c_TipoRelacion SAT: "01" nota de crédito, "02" nota de débito, "03" devolución, "04" sustitución, "05"–"07" traslados/anticipos.
Logging
El SDK emite eventos vía el logger estándar contadb_sdk (request, status, decisiones de reintento). Nunca loguea token, llave privada, contraseña ni XML.
import logging
logging.getLogger("contadb_sdk").setLevel(logging.INFO)
Configuración
Por defecto el cliente apunta a https://api.contadb.mx. Puedes cambiarlo:
client = ContaDBClient(
api_token="cdb_xxx",
base_url="https://staging.contadb.mx", # o env var CONTADB_BASE_URL
timeout=60.0,
)
Documentación
Cómo obtener un API token
- Crea cuenta en contadb.mx.
- Ve a Facturación → API Tokens y genera uno.
- Compra una bolsa de timbres (desde 100 timbres / $200 MXN).
- Usa el token con este SDK.
Licencia
MIT — ver LICENSE.
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
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 contadb_sdk-1.1.2.tar.gz.
File metadata
- Download URL: contadb_sdk-1.1.2.tar.gz
- Upload date:
- Size: 94.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c344bc3a1e0931f06d8e16b6d6582d014ca99ef123394c8bb9dcf4db28bd0bdf
|
|
| MD5 |
948c6bcba47d0ac8211afcf15d1ba9fb
|
|
| BLAKE2b-256 |
62f2012a4f253f0f11346c3a0c421241cc35dd6be9bca82311ad83cd29d70c41
|
File details
Details for the file contadb_sdk-1.1.2-py3-none-any.whl.
File metadata
- Download URL: contadb_sdk-1.1.2-py3-none-any.whl
- Upload date:
- Size: 71.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
80b9a2b1bb962821072de721648e1182790189a59e6a77f52317fe08b6c7a547
|
|
| MD5 |
ee1efe765b0b6369f11895c2e06905c5
|
|
| BLAKE2b-256 |
ab6b7ffcfa8ebdd4c4c4b378051a7afc0ebf46f24ad0c2649438b9e51c9d5f8d
|