emite.do SDK — Python
SDK oficial para api.emite.do. El mismo POST /api/v1/ecf cubre E31–E47.
Docs: https://docs.emite.do
Instalación
pip install ecfservice
Inicio rápido
from datetime import date
from ecfservice import ECFClient
with ECFClient(api_key="...") as client:
doc = client.ecf.create(
idempotency_key="INV-2026-0001",
ecf_type="31",
environment="TesteCF",
payload={
"Encabezado": {
"Version": "1.0",
"IdDoc": {
"TipoeCF": "31",
"eNCF": "E310000000001",
"FechaVencimientoSecuencia": "31-12-2028",
"IndicadorMontoGravado": 0,
"TipoIngresos": "01",
"TipoPago": "1",
},
"Emisor": {
"RNCEmisor": "130478031",
"RazonSocialEmisor": "Mi Empresa SRL",
"DireccionEmisor": "AV. DEMO 1",
"FechaEmision": date.today().strftime("%d-%m-%Y"),
},
"Comprador": {
"RNCComprador": "131098193",
"RazonSocialComprador": "Cliente SRL",
},
"Totales": {
"MontoGravadoTotal": 10000.0,
"MontoGravadoI1": 10000.0,
"ITBIS1": 18,
"TotalITBIS": 1800.0,
"TotalITBIS1": 1800.0,
"MontoTotal": 11800.0,
},
},
"DetallesItems": {
"Item": [
{
"NumeroLinea": 1,
"IndicadorFacturacion": 1,
"NombreItem": "SERVICIO DEMO",
"IndicadorBienoServicio": 2,
"CantidadItem": 1.0,
"UnidadMedida": "43",
"PrecioUnitarioItem": 10000.0,
"MontoItem": 10000.0,
}
]
},
},
)
print(doc.public_id, doc.status) # received — el veredicto fiscal llega después
doc = client.ecf.get(doc.public_id)
xml = client.ecf.download_xml(doc.public_id)
ecf_type acepta 31 32 33 34 41 43 44 45 46 47. Cambia TipoeCF y el e-NCF (E32…, E47…) al tipo.
Misma idempotency_key → 200 del original (el payload no se compara).
Builder
from ecfservice import ECFPayloadBuilder
payload = (
ECFPayloadBuilder(ecf_type="31")
.id_doc(eNCF="E310000000001", FechaVencimientoSecuencia="31-12-2028")
.emisor(RNCEmisor="130478031", RazonSocialEmisor="Mi Empresa SRL", FechaEmision="15-08-2026")
.comprador(RNCComprador="131098193", RazonSocialComprador="Cliente SRL")
.totales(MontoTotal=11800.0, TotalITBIS=1800.0)
.add_item({"NumeroLinea": 1, "NombreItem": "Servicio", "MontoItem": 10000.0})
.build()
)
Pone TipoeCF (no TipoEcf). FechaEmision va en Emisor.
Empresa, rangos, inbox
profile = client.client.company()
seqs = client.client.sequences(active_only=True)
inbox = client.client.inbox(acked=False)
client.client.ack_inbox(inbox.items[0].public_id)
Los rangos se listan; no se crean por API.
ACECF y ANECF
client.ecf.submit_acecf(
idempotency_key="ac-001",
encf="E310000000001",
rnc_emisor="130478031",
rnc_comprador="131098193",
fecha_emision="15-08-2026",
monto_total="11800.00",
estado="1",
)
client.ecf.cancel_sequences(
idempotency_key="an-001",
cancellations=[{
"ecf_type": "31",
"sequence_from": "E310000000010",
"sequence_to": "E310000000012",
"quantity": 3,
}],
)
Webhooks
Hoy el service notifica accepted, conditionally_accepted y rejected.
wh = client.client.create_webhook(
url="https://mi-app.example/webhooks/ecf",
events=["accepted", "conditionally_accepted", "rejected"],
)
from ecfservice.webhook import verify_webhook_signature
ok = verify_webhook_signature(request_body, request.headers["X-ECF-Signature"], wh.secret)
Salud y padrón (sin API key)
client = ECFClient() # key opcional
print(client.health().status)
print(client.dgii.rnc("130478031").razon_social)
Errores
El service responde { "detail": "..." } (FastAPI).
from ecfservice import ECFAuthError, ECFValidationError, ECFConflictError, ECFNotFoundError
401→ECFAuthError404→ECFNotFoundError409e-NCF usado →ECFConflictError422payload / rango / P12 / header faltante →ECFValidationError
Licencia
MIT
Release files for ecfservice 0.3.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| ecfservice-0.3.0.tar.gz | 11.6 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| ecfservice-0.3.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 25.2 kB
Release files / ecfservice-0.3.0.tar.gz
| Download URL | ecfservice-0.3.0.tar.gz |
|---|---|
| Size | 11.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
002f9fba7e6d8b0d4125556e5883f77ccb0398d241aa7a2e1373476895b9f1b9
|
|
BLAKE2b-256 checksum How to use checksums |
50f81c34ce2d9711c48e9b40c2d991e23046d77fb1371e2d26ad8d5043f514d3
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.7
|
Release files / ecfservice-0.3.0-py3-none-any.whl
| Download URL | ecfservice-0.3.0-py3-none-any.whl |
|---|---|
| Size | 13.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
9c5d03b1cf8c8a7c68ac294162f172602a7ab7c30f02037ff8a1823ebad351d6
|
|
BLAKE2b-256 checksum How to use checksums |
26240fa83acae6821f97a6f654067f66985b01123c03a90c6471ecfbf79cb434
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.7
|