Skip to main content

contadb-sdk

PyPI version Python versions License: MIT

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 + .key del 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.typed para inferencia perfecta en IDEs y mypy --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

  1. Crea cuenta en contadb.mx.
  2. Ve a Facturación → API Tokens y genera uno.
  3. Compra una bolsa de timbres (desde 100 timbres / $200 MXN).
  4. Usa el token con este SDK.

Licencia

MIT — ver LICENSE.

Metadata

Release files for contadb-sdk 1.1.4

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for contadb-sdk 1.1.4
File Size Uploaded Provenance
contadb_sdk-1.1.4.tar.gz 94.6 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for contadb-sdk 1.1.4
File Interpreter ABI Platform
contadb_sdk-1.1.4-py3-none-any.whl Python 3 none any Details

Total release size: 166.4 kB

Release files / contadb_sdk-1.1.4.tar.gz

Download URL contadb_sdk-1.1.4.tar.gz
Size 94.6 kB
Tags Source
SHA-256 checksum
How to use checksums
bb2cd432a13584b7c9f76acac501b0d1d421570d84dbc5552c9a0183e14ff270
BLAKE2b-256 checksum
How to use checksums
f3f4068e66220bb0d826587a0384b21099e4487f35c4812572c3ee71c76b105a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.10.12

Release files / contadb_sdk-1.1.4-py3-none-any.whl

Download URL contadb_sdk-1.1.4-py3-none-any.whl
Size 71.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
b89858b69107f7c5c85fb0a1fac289f37298ee86b11cc361c93ecf79c12886a0
BLAKE2b-256 checksum
How to use checksums
26b0bb0db6f8aea55659b50fbbbcf4fb997c8d5588cb651aed26a09926df6288
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.10.12

Security for contadb-sdk 1.1.4

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page