Electronic Invoicing

POST/v1/api/facturacion

Unified endpoint — issues all 10 electronic document types (FE, NC, ND, DS, NC-DS, Export, Contingency T03/T04, POS, POS Adjustment Note).

Async mode available: Send async: true to receive an immediate 202 Accepted response. The document is processed in background with BullMQ and you can check its status via polling or WebSocket.

Request Body

FieldTypeRequiredDescription
id_tipo_documentointegerYes1=FE, 2=NC, 3=ND, 4=DS, 5=NC-DS, 6=Export, 7=Contingency T03, 8=Contingency T04, 9=POS, 10=POS Adjustment
transmitbooleanNotrue to transmit to DIAN immediately
asyncbooleanNotrue = 202 Accepted response + background processing via BullMQ. false (default) = synchronous.
customerobjectYesCustomer data (see sub-table)
invoice_linesarrayYesDocument lines (FE & DS). For NC use credit_note_lines, for ND use debit_note_lines
legal_monetary_totalsobjectNoMonetary totals
tax_totalsarrayNoTax summary
payment_formobjectNoPayment form
notesstringNoNotes
id_documento_referenciaintegerNoNC/ND only: ID of the original document it applies to
id_concepto_notastringNoNC/ND only: Concept/reason code
referencia_externastringNoUnique reference from your system (e.g., "ORD-001"). Prevents duplicates — if it exists, returns 409

Customer Sub-table

FieldTypeRequiredDescription
identification_numberstringYesCustomer NIT or CC
namestringYesBusiness name
emailstringYesEmail for document delivery
type_document_identification.codestringNo13=CC, 31=NIT, 22=CE, 41=Pasaporte
type_organization.codestringNo1=Legal Entity, 2=Natural Person
addressstringNoAddress
municipality.codestringNoDANE municipality code
municipality.namestringNoMunicipality name

Invoice Lines Sub-table

FieldTypeRequiredDescription
descriptionstringYesProduct/service description
invoiced_quantitynumberYesQuantity
line_extension_amountnumberYesLine subtotal (without taxes)
price_amountnumberYesUnit price
unit_measure.codestringNoUnit of measure code (94=Unit)
tax_totalsarrayNoTaxes for this line

Request Example

JSON
{
  "id_tipo_documento": 1,
  "referencia_externa": "ORD-2026-001",
  "transmit": true,
  "async": false,
  "customer": {
    "identification_number": "900123456",
    "name": "Empresa XYZ SAS",
    "email": "facturacion@xyz.com",
    "type_document_identification": {
      "code": "31"
    },
    "type_organization": {
      "code": "1"
    },
    "address": "Calle 123 #45-67, Bogotá",
    "municipality": {
      "code": "11001",
      "name": "Bogotá D.C."
    }
  },
  "invoice_lines": [
    {
      "description": "Servicio de consultoría",
      "invoiced_quantity": 1,
      "line_extension_amount": 1000000,
      "price_amount": 1000000,
      "unit_measure": {
        "code": "94"
      },
      "tax_totals": [
        {
          "tax_code": "01",
          "tax_name": "IVA",
          "percent": 19,
          "taxable_amount": 1000000,
          "tax_amount": 190000
        }
      ]
    }
  ],
  "legal_monetary_totals": {
    "line_extension_amount": 1000000,
    "tax_exclusive_amount": 1000000,
    "tax_inclusive_amount": 1190000,
    "payable_amount": 1190000
  },
  "tax_totals": [
    {
      "tax_code": "01",
      "tax_name": "IVA",
      "percent": 19,
      "taxable_amount": 1000000,
      "tax_amount": 190000
    }
  ]
}

Sync Response (200)

JSON
{
  "success": true,
  "message": "Factura Electrónica procesado exitosamente",
  "data": {
    "documento": {
      "id": 1,
      "prefijo": "SETT",
      "numero": "001",
      "cufe": "sha384...",
      "total": 1190000
    },
    "xml": "<Invoice>...</Invoice>",
    "cufe": "a1b2c3d4e5f6...",
    "cufe_scheme": "CUFE-SHA384",
    "qr_url": "https://catalogo-vpfe.dian.gov.co/document/searchqr?documentkey=a1b2c3...",
    "transmission": {
      "isValid": true,
      "statusCode": "00",
      "statusDescription": "Procesado Correctamente",
      "errors": [],
      "zipKey": "uuid-track-id",
      "retryable": false
    }
  }
}

Async Response (202)

JSON
{
  "success": true,
  "status": 202,
  "message": "Factura Electrónica en cola de transmisión",
  "data": {
    "documento": { "id": 1, "prefijo": "SETT", "numero": "001" },
    "cufe": "a1b2c3d4e5f6...",
    "cufe_scheme": "CUFE-SHA384",
    "qr_url": "https://catalogo-vpfe.dian.gov.co/...",
    "job_id": "bull-456",
    "poll_url": "/v1/api/facturacion/1/status?id_empresa=5"
  }
}
Code Examples
curl -X POST https://api.jcflow.com.co/v1/api/facturacion \
  -H "X-Api-Key: sk_test_tu_api_key_aqui" \
  -H "Content-Type: application/json" \
  -d '{"id_tipo_documento":1,"referencia_externa":"ORD-2026-001","transmit":true,"async":false,"customer":{"identification_number":"900123456","name":"Empresa XYZ SAS","email":"facturacion@xyz.com","type_document_identification":{"code":"31"},"type_organization":{"code":"1"},"address":"Calle 123 #45-67, Bogotá","municipality":{"code":"11001","name":"Bogotá D.C."}},"invoice_lines":[{"description":"Servicio de consultoría","invoiced_quantity":1,"line_extension_amount":1000000,"price_amount":1000000,"unit_measure":{"code":"94"},"tax_totals":[{"tax_code":"01","tax_name":"IVA","percent":19,"taxable_amount":1000000,"tax_amount":190000}]}],"legal_monetary_totals":{"line_extension_amount":1000000,"tax_exclusive_amount":1000000,"tax_inclusive_amount":1190000,"payable_amount":1190000},"tax_totals":[{"tax_code":"01","tax_name":"IVA","percent":19,"taxable_amount":1000000,"tax_amount":190000}]}'
Try EndpointPOST /facturacion
⚙️ Automatic Rules in Production (DIAN Annex 1.8):
  • Synchronous Transmission: In the production environment (or when using production API keys sk_live_...), document transmission is always processed synchronously (SendBillSync) to prevent rejections due to lack of authorization for asynchronous batch processing.
  • Suppression of Empty Taxes: To avoid restrictive warnings (such as FAX05 and FAX14 notifications) on the DIAN portal, the system dynamically suppresses empty ICA (03) and INC (04) blocks with base/percentage at 0.00 when operating in production.
  • Date and Signature Alignment: The emission date and time in the XML document are automatically synchronized in real-time with the digital signature timestamp (using Colombia time zone -05:00), completely eliminating rejections caused by rule FAD09e.
  • Transactional Recalculation of CUFE/CUDE: The CUFE/CUDE code is dynamically recalculated and injected, integrating the official time offset of -05:00 in both the mathematical calculation and the IssueTime tag of the XML, ensuring exact consistency.
✅ CUFE/CUDE (Verified): Generated with SHA-384 per DIAN Technical Annex v1.8, Ch. 11.1.2. Verified byte-by-byte against the official DIAN example (CUFE: 8bb918b1...). CUFE for Invoices (resolution technical key), CUDE for Notes and Contingency (software PIN).
ℹ️ QR Code: The DIAN verification URL is generated automatically based on the environment (testing/production).
ℹ️ Pre-emission Validation: The system automatically validates company, DIAN software, resolution (validity + range), digital certificate, customer, and totals before generating the XML.
ℹ️ Email: The document is automatically sent via email to the customer with the XML attached.

Check Status (Polling)

GET/v1/api/facturacion/:id/status

Check the current status of a document. Useful for polling when using async mode.

Query Parameters

FieldTypeRequiredDescription
id_empresaintegerYesCompany ID (query param)
check_dianbooleanNotrue = Query DIAN GetStatus live if doc is In Queue
ambientestringNo1=Production, 2=Testing (default: 2)

Document States

CodeStateDescription
1BorradorSaved, not transmitted
2Enviado/AceptadoDIAN accepted the document
3En ColaProcessing in background (async mode)
4RechazadoDIAN rejected the document
5Waiting DIANCircuit Breaker open — DIAN unavailable. Will be resent automatically.
6Dead LetterExhausted 5 retries. Recovery Cron will re-queue automatically when DIAN is back.
JSON
{
  "success": true,
  "data": {
    "id": 1,
    "prefijo": "SETT",
    "numero": "001",
    "id_tipo_documento": 1,
    "id_estado_documento": 2,
    "estado": "Enviado/Aceptado",
    "cufe": "a1b2c3d4e5f6...",
    "qr_url": "https://catalogo-vpfe.dian.gov.co/...",
    "dian_track_id": "uuid-zip-key",
    "dian_response": {
      "isValid": true,
      "statusCode": "00",
      "statusDescription": "Procesado Correctamente"
    },
    "total": 1190000,
    "fecha_emision": "2026-04-24",
    "created_at": "2026-04-24T10:30:00Z",
    "updated_at": "2026-04-24T10:30:05Z"
  }
}

Contingency Batch Send

POST/v1/api/facturacion/contingencia/enviar

Sends all pending contingency documents (T03/T04) to DIAN. Documents are queued in BullMQ for async processing.

Request Body

FieldTypeRequiredDescription
id_empresaintegerYesCompany ID
documento_idsarrayNoSpecific IDs to send. If empty, sends ALL pending.
JSON
{
  "success": true,
  "message": "15 documento(s) encolado(s) para transmisión.",
  "data": {
    "total_pendientes": 15,
    "total_encolados": 15,
    "total_errores": 0,
    "documentos": [
      { "id": 10, "prefijo": "SETT", "numero": "100", "job_id": "bull-789" },
      { "id": 11, "prefijo": "SETT", "numero": "101", "job_id": "bull-790" }
    ]
  }
}

Utility endpoints

POST/v1/api/facturacion/reenviar/:id

Resend a draft or failed document to DIAN. Regenerates XML, signs and transmits.

GET/v1/api/facturacion/consecutivo/:tipo

Gets the next available consecutive number for a document type.

GET/v1/api/facturacion/suscripcion

Checks subscription status: documents used, available, and limit.

🌐 Export Invoices (Multi-currency & Incoterms)

To issue export invoices (Type 02 / Operation 10), specify the foreign currency (USD, EUR), daily TRM exchange rate and Incoterms (CIF, FOB, EXW, FCA, etc.):

JSON
{
  "id_tipo_documento": 2,
  "id_tipo_operacion": "10",
  "id_tipo_moneda": 149,
  "exchange_rate": {
    "source_currency": "USD",
    "target_currency": "COP",
    "calculation_rate": 4150.50,
    "date": "2026-08-29"
  },
  "delivery": {
    "delivery_terms": "FOB"
  },
  "customer": {
    "name": "Global Tech Logistics LLC",
    "identification_number": "US99887766",
    "country_code": "US",
    "type_document_identification": { "code": "41" },
    "type_organization": { "code": "1" },
    "email": "invoices@globaltech.us"
  },
  "invoice_lines": [
    {
      "description": "Exportación de Café Especial Colombiano (Sacos 70kg)",
      "invoiced_quantity": 50,
      "price_amount": 280.00,
      "line_extension_amount": 14000.00,
      "unit_measure": { "code": "KGM" }
    }
  ],
  "legal_monetary_totals": {
    "line_extension_amount": 14000.00,
    "tax_exclusive_amount": 14000.00,
    "tax_inclusive_amount": 14000.00,
    "payable_amount": 14000.00
  },
  "transmit": true
}

🏥 Sectoral Invoicing (Health RIPS, Transport RNDC, Fuels)

Health Sector (RIPS)

Operation 11. Validates MinSalud sectoral fields, provider code, copays and moderator fees.

Cargo Transport (RNDC)

Operation 12. Integrates cargo dispatch and official MinTransporte cargo manifest.

Fuels & Gas Stations

Automatic support for Fuel Tax (24), Surcharge (25) and Sordicom (26).

WebSocket Events (Real-time)

facturacion:updateDocument accepted/rejected by DIAN (status, errors, zipKey)

facturacion:errorMax retries exhausted. Document will be marked as recoverable and resent automatically.

contingencia:batchContingency batch send started

Rooms: empresa_{id}, user_{id}

🛡️ DIAN Resilience Engine

The system protects against DIAN Web Service outages with multiple resilience layers. No document is lost — all are automatically resent.
LayerMechanismDetail
Circuit BreakerOutage detection5 consecutive failures → pause sends 60s → automatic test → resume if DIAN responds
Exponential BackoffProgressive retries5 attempts: 10s → 20s → 40s → 80s → 160s
Dead Letter QueueFailed queueAfter 5 attempts → state 6 (automatically recoverable)
Recovery CronAuto recoveryEvery 5 min searches for state 5/6 docs and re-queues them if DIAN is available
Rate LimiterSpeed controlMax 10 req/sec to DIAN WS, 3 concurrent workers

Circuit Breaker

CLOSED ──(5 failures)──▸ OPEN ──(60s)──▸ HALF_OPEN ──(2 successes)──▸ CLOSED
                         ▲                 │ fail
                         └─────────────────┘ (escalating timeout: 60s → 120s → 5min)

Document States

StateIDDescription
Borrador1Generated, not transmitted to DIAN
Accepted2DIAN accepted and validated the document
In Queue3Processing via BullMQ (async mode)
Rejected4DIAN rejected the document (business error)
Waiting DIAN5Circuit Breaker open — will be resent automatically
Dead Letter6Exhausted 5 retries — Recovery Cron will re-queue
No document loss: States 5 and 6 are recoverable. The Recovery Cron (every 5 min) automatically re-queues all pending documents when DIAN becomes available again.

📊 Performance (Benchmark)

Stress test results on a local server with 500 electronic invoices burst-processed with 25 concurrent connections (without DIAN transmission).

100%
Success Rate
281req/s
Throughput
75ms
Median Latency
162ms
P95 Latency

Latency Distribution

< 100ms87%
100–200ms13%
> 200ms0%
MetricValue
Total requests500
Concurrency25
Total time1.78s
Throughput281 req/s
Avg Latency82ms
Median (P50)75ms
P95162ms
P99178ms
Max179ms
⚠️ Note: In production with transmit=true, DIAN transmission latency (1-5s) is processed in background via BullMQ. The client response remains ~150ms (202 Accepted).