Skip to main content

DGMaxClient

Python SDK for the DGMax API — electronic fiscal document (e-CF) processing for the Dominican Republic.

Build, validate, and submit e-CF payloads (E31–E47) against DGII's schema with typed Pydantic models, automatic retries, and a clean resource-oriented API. Skip the XSD, the hand-built JSON, and the DGII error decoding.

Installation

pip install dgmaxclient

Quick Start

from dgmaxclient import (
    DGMaxClient,
    DocumentCreateRequest,
    CompanyRef,
    ECFPayload,
    ECFEncabezado,
    ECFIdDoc,
    ECFEmisor,
    ECFComprador,
    ECFTotales,
    ECFDetallesItems,
    ECFItem,
)

# Initialize the client
client = DGMaxClient(api_key="dgmax_xxx")

# List companies
companies = client.companies.list()
for company in companies.results:
    print(f"{company.name} ({company.rnc})")

# Create an invoice (E32) — fully typed with IDE autocomplete
invoice = client.invoices.create(
    DocumentCreateRequest(
        company=CompanyRef(id="your-company-uuid"),
        ecf=ECFPayload(
            encabezado=ECFEncabezado(
                id_doc=ECFIdDoc(tipo_ecf=32, e_ncf="E320000000001"),
                emisor=ECFEmisor(
                    rnc_emisor="123456789",
                    razon_social_emisor="Mi Empresa SRL",
                    fecha_emision="15-01-2026",
                ),
                comprador=ECFComprador(
                    razon_social_comprador="Cliente Final",
                ),
                totales=ECFTotales(
                    monto_gravado_i1="847.46",
                    itbis1="18",
                    total_itbis1="152.54",
                    total_itbis="152.54",
                    monto_gravado_total="847.46",
                    monto_total="1000.00",
                ),
            ),
            detalles_items=ECFDetallesItems(item=[
                ECFItem(
                    numero_linea="1",
                    indicador_facturacion=1,
                    nombre_item="Servicio de consultoría",
                    cantidad_item="1",
                    precio_unitario_item="847.46",
                    monto_item="847.46",
                ),
            ]),
        ),
    )
)

print(f"Invoice created: {invoice.encf}")
print(f"Status: {invoice.status}")  # DocumentStatus.REGISTERED → PROCESSING → COMPLETED

Architecture

DGMaxClient uses the Facade Pattern with Composition to provide a clean, namespaced API. The main client acts as a single entry point that composes multiple resource objects, each responsible for a specific API domain.

┌─────────────────┐
│   DGMaxClient   │ ◄── Facade (single entry point)
├─────────────────┤
│ .companies      │───► CompaniesResource
│ .invoices       │───► InvoicesResource
│ .purchases      │───► PurchasesResource
│ .credit_notes   │───► CreditNotesResource
│ ...             │───► (other resources)
└─────────────────┘
         │
         ▼
   HTTP/Auth layer (shared)

This pattern enables:

  • Clean API: client.companies.list(), client.invoices.create({...})
  • Shared configuration: All resources use the same authentication and settings
  • Separation of concerns: Each resource handles its own domain logic
  • Discoverability: IDE autocomplete works seamlessly

Features

Document Types (E31-E47)

The SDK supports all Dominican Republic electronic fiscal document types:

Type Resource Description
E31 client.fiscal_invoices Factura de Crédito Fiscal Electrónica
E32 client.invoices Factura de Consumo Electrónica
E33 client.debit_notes Nota de Débito Electrónica
E34 client.credit_notes Nota de Crédito Electrónica
E41 client.purchases Comprobante Electrónico de Compras
E43 client.minor_expenses Comprobante Electrónico para Gastos Menores
E44 client.special_regimes Comprobante Electrónico para Regímenes Especiales
E45 client.governmental Comprobante Electrónico Gubernamental
E46 client.exports Comprobante Electrónico para Exportaciones
E47 client.payments_abroad Comprobante Electrónico para Pagos al Exterior

Company Management

from dgmaxclient import CompanyCreate, CertificateCreate

# List companies
companies = client.companies.list()

# Get a specific company
company = client.companies.get("company-uuid")

# Create a company with certificate
company = client.companies.create(CompanyCreate(
    name="Mi Empresa SRL",
    trade_name="Mi Empresa",
    rnc="123456789",
    address="Calle Principal #123",
    certificate=CertificateCreate(
        name="certificate",
        extension="p12",
        content="base64-encoded-certificate",
        password="certificate-password"
    )
))

# Update a company
company = client.companies.update("company-uuid", {
    "phone": "809-555-1234",
    "email": "info@miempresa.com"
})

Document Operations

from dgmaxclient import DocumentFilters, DocumentStatus, PaginationParams

# List documents with pagination
invoices = client.invoices.list(
    params=PaginationParams(limit=50, offset=0)
)

# List documents with filters
invoices = client.invoices.list(
    filters=DocumentFilters(
        status=DocumentStatus.COMPLETED,
        date_from="2024-01-01",
        date_to="2024-12-31",
        search="123456789"  # Search by RNC or eNCF
    )
)

# Get a specific document
invoice = client.invoices.get("document-uuid")

# Create a document (see Quick Start for typed payload example)
invoice = client.invoices.create(payload)

Received Documents (Receptor Module)

# List received documents
received = client.received_documents.list()

# List with filters
from dgmaxclient import ReceivedDocumentFilters

received = client.received_documents.list(
    filters=ReceivedDocumentFilters(
        status="PENDING",
        date_from="2024-01-01",
    )
)

# Approve a received document
response = client.received_documents.approve("document-uuid")
if response.success:
    print(f"Document approved: {response.approval_id}")

# Reject a received document
response = client.received_documents.reject(
    "document-uuid",
    rejection_reason="Invoice amount does not match purchase order"
)

# List commercial approvals received
approvals = client.received_documents.list_commercial_approvals()

Error Handling

The SDK provides a comprehensive exception hierarchy:

from dgmaxclient import (
    DGMaxError,
    DGMaxAuthenticationError,
    DGMaxValidationError,
    DGMaxRequestError,
    DGMaxServerError,
    DGMaxTimeoutError,
    DGMaxConnectionError,
    DGMaxRateLimitError,
)

try:
    invoice = client.invoices.create(payload)
except DGMaxAuthenticationError as e:
    print(f"Authentication failed: {e.message}")
    print(f"Status code: {e.status_code}")
except DGMaxValidationError as e:
    print(f"Validation error: {e.message}")
    if e.response:
        print(f"Details: {e.response}")
except DGMaxServerError as e:
    print(f"Server error (will retry): {e.message}")
except DGMaxTimeoutError:
    print("Request timed out")
except DGMaxConnectionError:
    print("Connection error - check your network")
except DGMaxRateLimitError as e:
    print(f"Rate limited. Retry after: {e.retry_after}s")
except DGMaxError as e:
    print(f"General error: {e.message}")

Configuration

# Custom base URL (e.g. dev environment)
client = DGMaxClient(
    api_key="dgmax_xxx",
    base_url="https://dev.dgmax.do",
)

# Custom timeout (default: 30 seconds)
client = DGMaxClient(
    api_key="dgmax_xxx",
    timeout=60,
)

Automatic Retries

The SDK automatically retries requests on:

  • Server errors (5xx)
  • Connection errors
  • Timeout errors

Retries use exponential backoff with jitter (max 3 attempts).

Type Safety

All responses are validated with Pydantic models:

from dgmaxclient import ElectronicDocument, DocumentStatus

invoice: ElectronicDocument = client.invoices.get("uuid")

# Type-safe access
print(invoice.id)
print(invoice.encf)
print(invoice.status)  # DocumentStatus enum

if invoice.status == DocumentStatus.COMPLETED:
    print("Document processed successfully")

Typed ECF submodels

Nested ECF fields — tabla_sub_descuento, otra_moneda_detalle, retencion, otra_moneda, transporte, informaciones_adicionales, subtotales, descuentos_o_recargos, paginacion, tabla_formas_pago, tabla_impuesto_adicional, tabla_telefono_emisor, mineria — are strongly typed. Typos, wrong nesting, and shape errors raise ValidationError at construction time instead of reaching DGII.

Dict-in still works. Build sub-objects as plain dicts — the SDK coerces them into the typed classes on the way in, so existing call sites get validation without changes:

ECFItem(
    numero_linea="1",
    indicador_facturacion=1,
    nombre_item="Servicio",
    monto_item="1800.00",
    tabla_sub_descuento={
        "sub_descuento": [
            {"tipo_sub_descuento": "%", "sub_descuento_porcentaje": "10.00"},
        ],
    },
    otra_moneda_detalle={
        "precio_otra_moneda": "100.00",
        "descuento_otra_moneda": "10.00",
        "monto_item_otra_moneda": "90.00",
    },
)

# Typos and wrong shapes now fail fast:
ECFItem(..., tabla_sub_descuento=[{"sub_descuento_porcentaje": 10.0}])
# → ValidationError: tabla_sub_descuento must be a dict with sub_descuento key

Numeric inputs are coerced. Money fields (monto_item, itbis1, monto_total, precio_unitario_item, ...) and line numbers accept int, float, Decimal, or str, and serialize to the DGII-compliant string pattern automatically:

from decimal import Decimal

ECFTotales(monto_total=1000, itbis1=Decimal("152.54"))
# → monto_total="1000.00", itbis1="152.54"

ECFItem(numero_linea=1, ...)  # → numero_linea="1"

Requirements

  • Python 3.10+
  • api-client >= 1.3.1
  • pydantic >= 2.0
  • tenacity >= 8.0
  • requests >= 2.28.0

License

MIT License - see LICENSE file for details.

Download files

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

Source Distribution

dgmaxclient-1.7.0.tar.gz (76.7 kB view details)

Uploaded Source

Built Distribution

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

dgmaxclient-1.7.0-py3-none-any.whl (64.6 kB view details)

Uploaded Python 3

File details

Details for the file dgmaxclient-1.7.0.tar.gz.

File metadata

  • Download URL: dgmaxclient-1.7.0.tar.gz
  • Upload date:
  • Size: 76.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.0

File hashes

Hashes for dgmaxclient-1.7.0.tar.gz
Algorithm Hash digest
SHA256 83e8eeff28294b130e8e714e4e15eeef0b50a2deba83af97e31fa7c9d2c32b1e
MD5 0eaa7c2d0e62b9a30e433e70725b0a10
BLAKE2b-256 0f6056e0d830a4fdcbfe4eff845b9153dbac83b077a53366c29653ba07f1a97e

See more details on using hashes here.

File details

Details for the file dgmaxclient-1.7.0-py3-none-any.whl.

File metadata

File hashes

Hashes for dgmaxclient-1.7.0-py3-none-any.whl
Algorithm Hash digest
SHA256 b82ce51e95d1922bc8bf7bbdad45e9289014b0adab1af9d47214d294b0bb5c58
MD5 f5407e051c045ccb98b4c0080e9f66be
BLAKE2b-256 350759e549e7e578589d76be880caafa20a2f7b7482fedafc301780e63387256

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

1.7.0 This release

2 files

1.6.0

2 files

1.5.1

2 files

1.5.0

2 files

1.4.2

2 files

1.4.1

2 files

1.4.0

2 files

1.3.6

2 files

1.3.5

2 files

1.3.4

2 files

1.3.2

2 files

1.3.1

2 files

1.3.0

2 files

1.2.0

2 files

1.1.2

2 files

1.1.1

2 files

1.1.0

2 files

1.0.3

2 files

1.0.2

2 files

1.0.1

2 files

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