Inicio › Blog › API e integraciones

Tutorial · API · API e integraciones · 5 min de lectura

Tu primera factura electrónica por API en 15 minutos (sandbox gratis)

Si tu empresa tiene un ERP, un CRM o un sistema propio, no necesitas que nadie digite las facturas: un POST con el cliente y las líneas, y la factura sale firmada con tu certificado y validada por la DIAN. Este tutorial va de cero a la primera factura aceptada en sandbox, con los mismos ejemplos de la documentación.

Publicado el 10 de octubre de 2026 · Actualizado el 23 de octubre de 2026 · Equipo miPlata

Documentación completa de la APIQué incluye la APIPreguntas frecuentes

Antes de empezar

Configuración → Claves API: cada llave con sus IP permitidas, límite por minuto, uso diario y vencimiento
Configuración → Claves API: cada llave con sus IP permitidas, límite por minuto, uso diario y vencimientoAsí se ve en una cuenta real. Esta sección no aparece en la demo pública porque maneja credenciales y datos privados de la empresa.

Paso a paso

  1. Crea una llave API

    En tu cuenta, Configuración → Integraciones → Claves API → Crear clave API: nombre (por ejemplo «ERP»), IP o rango permitido (obligatorio) y límite por minuto. La llave se muestra una sola vez; guárdala en tu gestor de secretos. Puedes crear tokens personales (PAT) por integración o colaborador desde la misma llave sin repartir la raíz.

  2. Pon la instancia en Sandbox

    Configuración → Entorno → Sandbox. Los documentos irán a la DIAN de habilitación, sin validez fiscal ni consumo de cupo. GET /company te lo confirma en mode: "TEST" y cada documento lleva environment. En Sandbox hay además un simulador de caída de la DIAN para probar tus reintentos y webhooks.

    curl -sS https://TU-EMPRESA.miplata.co/api/external/company \
      -H "X-API-Key: TU_LLAVE"
    
  3. Emite la factura

    Un POST /invoices con el cliente y las líneas. En la primera emisión a un NIT envías sus datos; en las siguientes basta customer_nit e items, el resto se toma de su ficha. El IVA va por línea en tax_percent.

    curl -sS -X POST https://TU-EMPRESA.miplata.co/api/external/invoices \
      -H "X-API-Key: TU_LLAVE" -H "Content-Type: application/json" \
      -H "Idempotency-Key: ORD-1001" \
      -d '{
      "customer_nit": "900123456",
      "customer_name": "Acme SAS",
      "customer_type_doc": "31",
      "customer_person_type": "1",
      "customer_tax_regime": "48",
      "customer_email": "pagos@acme.co",
      "customer_city_code": "11001",
      "customer_department_code": "11",
      "payment_means_code": "10",
      "order_reference": "ORD-1001",
      "items": [
        { "description": "Consultoría", "quantity": 10, "unit_price": 150000, "tax_percent": 19 }
      ]
    }'
    

    La respuesta (201) trae el documento ya numerado, firmado y enviado a la DIAN. El consecutivo lo pone miPlata: no lo mandas tú. El id es un UUID; guárdalo para consultar, cobrar o corregir:

    {
      "id": "3f2b8c1e-7a4d-4b9e-9c61-2d5f0a8e4b17",
      "environment": "TEST",
      "invoice_number": "SETP990000123",
      "invoice_type": "01",
      "cufe": "a1b2c3d4e5f6...9f",
      "qr_code": "https://catalogo-vpfe-hab.dian.gov.co/document/searchqr?documentkey=a1b2...",
      "dian_status": "SENT",
      "total_amount": "1785000.00",
      "balance": "1785000.00"
    }
    
  4. Espera la aceptación

    dian_status llega como SENT (enviada, esperando la respuesta) o ya como ACCEPTED; si la DIAN no responde, QUEUED y miPlata reintenta sola. La DIAN responde en segundos. Dos formas de saberlo:

    • Webhook: registra una URL con POST /webhooks (eventos invoice.accepted, invoice.rejected, invoice.pending_dian; las notas crédito disparan credit_note.*); cada entrega va firmada con HMAC-SHA256 en X-MiPlata-Signature (y X-MiPlata-Signature-V2 sobre X-MiPlata-Timestamp + cuerpo).
    • Consulta: GET /invoices/{id} hasta que dian_status sea ACCEPTED (o REJECTED, con el código de regla y su explicación).
    curl -sS https://TU-EMPRESA.miplata.co/api/external/invoices/3f2b8c1e-7a4d-4b9e-9c61-2d5f0a8e4b17 \
      -H "X-API-Key: TU_LLAVE"
    
  5. Descarga el PDF y el XML

    GET /invoices/{id}/pdf devuelve la representación gráfica con QR; GET /invoices/{id}/attached-document el AttachedDocument firmado (XML + ApplicationResponse de la DIAN) que el cliente puede exigir.

  6. Corrige con una nota crédito

    Una factura aceptada no se edita: se emite una nota crédito (invoice_type: "91") que referencia el original. Sus webhooks son de la familia credit_note.* (credit_note.accepted, credit_note.rejected…), no invoice.*.

    curl -sS -X POST https://TU-EMPRESA.miplata.co/api/external/invoices \
      -H "X-API-Key: TU_LLAVE" -H "Content-Type: application/json" \
      -d '{
      "invoice_type": "91",
      "correction_invoice_id": "3f2b8c1e-7a4d-4b9e-9c61-2d5f0a8e4b17",
      "correction_concept": "2",
      "correction_reason": "Anulación de la factura",
      "customer_nit": "900123456",
      "items": [
        { "description": "Consultoría", "quantity": 10, "unit_price": 150000, "tax_percent": 19 }
      ]
    }'
    
  7. Pasa a producción

    Configuración → Entorno → Producción. Nada cambia en tu código: misma llave, mismas rutas. Desde ahí cada documento transmitido a la DIAN consume una unidad del cupo del plan (1.000 en el Plan 12 Meses, 250 en el de 3) y las recargas cubren el resto.

Tres cosas que evitan dolores de cabeza

Configuración → Webhooks: URL, eventos suscritos y último estado de entrega; el secreto se muestra una sola vez
Configuración → Webhooks: URL, eventos suscritos y último estado de entrega; el secreto se muestra una sola vezAsí se ve en una cuenta real. Esta sección no aparece en la demo pública porque maneja credenciales y datos privados de la empresa.

Preguntas frecuentes

¿Hay un entorno de pruebas separado con otra URL?

No. Sandbox es un estado de toda la instancia, no un host ni una llave distinta. Eso evita el error clásico de apuntar producción al sandbox: cambias el interruptor y listo.

¿Qué pasa si envío un cliente que ya existe con datos distintos?

Los campos que envíes actualizan su ficha; los que omitas se conservan. Si solo mandas customer_nit, se usa la ficha tal como está.

¿Puedo emitir muchas facturas de golpe?

Sí: POST /invoices/bulk acepta un lote con client_reference por ítem y GET /invoices/bulk/{batch_id} devuelve el estado de cada una.

¿Cómo cobro la factura desde la API?

POST /invoices/{id}/pay-link genera el enlace de pago (Bre-B, Nequi, Daviplata o PayPal); el webhook invoice.paid avisa cuando el cliente paga. Guía: cobrar con Bre-B y Nequi.

¿Y la nómina y el documento soporte?

Mismo esquema: POST /payroll para documentos 102/103 e invoice_type: "05" / "95" para documento soporte y su nota de ajuste. Todo en la documentación.

¿Qué lenguaje debo usar?

Cualquiera con cliente HTTP y JSON. La documentación muestra cURL, Node.js y Python; la colección Postman cubre todos los endpoints públicos.

Lo mismo, en producción, con un interruptor

Cambia la instancia a Producción en Configuración → Entorno. Misma llave, mismas rutas; el cupo de documentos del plan empieza a contar ahí.

¿Falta algo en esta guía? Escríbenos a hola@miplata.co. Versión en texto plano: primera-factura-por-api.md.