Cómo emitir tu primer e-CF con la API de Bisnia
De la API key al comprobante aceptado por la DGII, en cuatro pasos. Con ejemplos reales en curl y Python que puedes copiar, pegar y correr hoy mismo.
Emitir un comprobante fiscal electrónico suena pesado hasta que lo haces una vez. Con la API de Bisnia el flujo es una sola llamada HTTP: tú mandas la operación en JSON, y nosotros validamos, firmamos con el certificado, transmitimos a la DGII y te devolvemos el e-NCF y su estado. Vamos a emitir un tipo 31 (crédito fiscal) de punta a punta.
Todo lo que sigue apunta a la base https://ecf.bisnia.com/v1. Las llamadas se autentican con un token Bearer y hablan JSON en ambos sentidos.
Antes de empezar necesitas una cuenta en Bisnia y tu certificado digital cargado en el panel. Con eso, la firma ocurre del lado de Bisnia: tu código nunca toca el certificado ni arma XML a mano.
01 Consigue tu API key
Entra al panel en ecf.bisnia.com, ve a Ajustes → API keys y genera una clave. Vas a ver dos ambientes:
bisnia_test_…— apunta al ambiente de pruebas con simulador de la DGII. Emites sin consecuencias fiscales.bisnia_live_…— apunta a producción. Lo que emitas aquí va de verdad a la DGII.
Guarda la clave como variable de entorno; nunca la pongas en el código ni la subas al repositorio:
export BISNIA_API_KEY="bisnia_test_a1b2c3…"
02 Emite el e-CF
La emisión es un POST a /v1/ecf. El cuerpo describe la operación: tipo, comprador e ítems. Bisnia calcula los impuestos, arma y firma el XML, y lo transmite.
# POST /v1/ecf — emite una factura de crédito fiscal (tipo 31) curl https://ecf.bisnia.com/v1/ecf \ -H "Authorization: Bearer $BISNIA_API_KEY" \ -H "Content-Type: application/json" \ -H "Idempotency-Key: fact-2026-000187" \ -d '{ "tipo": 31, "comprador": { "rnc": "131880681", "razon_social": "Cliente SRL" }, "items": [ { "desc": "Consultoría", "cantidad": 1, "precio": 42500 } ] }'
# pip install bisnia import os from bisnia import Bisnia client = Bisnia(api_key=os.environ["BISNIA_API_KEY"]) ecf = client.ecf.emitir( tipo=31, comprador={"rnc": "131880681", "razon_social": "Cliente SRL"}, items=[{"desc": "Consultoría", "cantidad": 1, "precio": 42500}], idempotency_key="fact-2026-000187", ) print(ecf.encf, ecf.estado)
La Idempotency-Key te protege. Si la red se cae y reintentas con la misma clave, Bisnia devuelve el e-CF que ya creó en vez de emitir uno duplicado. Usa un identificador propio y estable por cada factura.
03 Lee la respuesta
La API responde con el comprobante creado. Los campos que te importan:
{
"id": "ecf_9F2c…",
"encf": "E310000012847",
"tipo": 31,
"estado": "en_proceso",
"total": 50150,
"itbis": 7650,
"representacion_impresa": "https://ecf.bisnia.com/r/E310000012847"
}
El encf es tu e-NCF definitivo. El estado arranca normalmente en en_proceso: la DGII aún no ha respondido su validación. No te quedes haciendo polling a ciegas; para eso están los estados y los webhooks.
| Estado | Qué significa |
|---|---|
| en_proceso | Firmado y enviado; esperando validación de la DGII |
| aceptado | La DGII lo validó y aprobó. Comprobante con validez plena |
| rechazado | La DGII lo rechazó; revisa el detalle del error y reemite |
| aceptado_cond | Aceptado condicionalmente; válido con observaciones |
04 Entérate del resultado con webhooks
En lugar de consultar el estado en bucle, registra un webhook y deja que Bisnia te avise cuando la DGII responde. Cada evento va firmado, así verificas que vino de nosotros:
from bisnia import verify_webhook def handler(request): evento = verify_webhook( payload=request.body, signature=request.headers["Bisnia-Signature"], secret=os.environ["BISNIA_WEBHOOK_SECRET"], ) if evento.tipo == "ecf.aceptado": marcar_pagada(evento.data.encf) # E310000012847 return "ok", 200
Prueba en test primero. Emite con tu clave bisnia_test_… hasta que domines el flujo. Cuando pases a bisnia_live_…, cada e-CF cuenta ante la DGII.
Lo que acabas de lograr
Con una sola llamada emitiste un e-CF firmado, lo transmitiste a la DGII y quedaste listo para reaccionar a su respuesta. No armaste XML, no manejaste el certificado, no montaste colas de reintento. Eso ta' resuelto.
Desde aquí, el mismo patrón te sirve para los otros 9 tipos de e-CF: cambia el campo tipo y ajusta el cuerpo. La referencia completa de endpoints, campos y errores está en la documentación de la API.
Emite tu primer e-CF de prueba
Crea tu cuenta, genera una API key de test y corre el ejemplo de arriba en minutos. Sin tarjeta.
Crear cuenta gratis