Skip to main content

Overview

DIAN (Dirección de Impuestos y Aduanas Nacionales) extensions are required for Colombian electronic invoicing. The UBL Builder library provides automatic generation and management of DIAN-specific extensions including:
  • Invoice control and authorization
  • Software provider information
  • Software security codes
  • QR codes for invoice verification
  • CUFE (Código Único de Factura Electrónica)

DIAN Extension Structure

DIAN extensions are added to the UBL document through the UBLExtensions element:
<ext:UBLExtensions>
  <ext:UBLExtension>
    <ext:ExtensionContent>
      <sts:DianExtensions>
        <sts:InvoiceControl>...</sts:InvoiceControl>
        <sts:InvoiceSource>...</sts:InvoiceSource>
        <sts:SoftwareProvider>...</sts:SoftwareProvider>
        <sts:SoftwareSecurityCode>...</sts:SoftwareSecurityCode>
        <sts:AuthorizationProvider>...</sts:AuthorizationProvider>
        <sts:QRCode>...</sts:QRCode>
      </sts:DianExtensions>
    </ext:ExtensionContent>
  </ext:UBLExtension>
</ext:UBLExtensions>

Automatic Extension Generation

1

Configure Invoice Options

Provide DIAN configuration when creating the invoice:
import { Invoice } from 'ubl-builder';

const invoice = new Invoice('SETP990000001', {
  timestamp: Date.now(),
  enviroment: '2', // '1' = production, '2' = testing
  issuer: {
    resolutionNumber: '18764003560527',
    technicalKey: 'fc8eac425c29d8c3fc8eac420b26cf00668ea99812ab8',
    prefix: 'SETP',
    startRange: '990000000',
    endRange: '995000000',
    startDate: '2019-01-19',
    endDate: '2030-01-19'
  },
  software: {
    id: '0d2e2883-eb8e-4e48-9d89-9e1a87a9e413',
    pin: '12345',
    providerNit: '900123456'
  }
});
  • Environment: ‘1’ for production invoices sent to DIAN, ‘2’ for testing
  • Resolution Number: DIAN authorization number for electronic invoicing
  • Technical Key: Unique key assigned by DIAN to the issuer
  • Prefix: Invoice prefix authorized by DIAN (e.g., SETP, SETT)
  • Range: Authorized invoice number range (from-to)
  • Software ID: UUID assigned by DIAN for your software
  • Pin: Software PIN provided by DIAN
2

Generate DIAN Extensions

Call calculateDianExtension() to generate the extension structure:
// This automatically creates all DIAN extension components
invoice.calculateDianExtension();
This method creates:
  • InvoiceControl: Authorization details and number range
  • InvoiceSource: Country identification (CO for Colombia)
  • SoftwareProvider: Technology provider NIT and software ID
  • SoftwareSecurityCode: SHA-384 hash of software ID + PIN + invoice number
  • AuthorizationProvider: DIAN NIT (800197268)
3

Finalize Document

Call finalizeDocument() to generate CUFE and QR code:
// This calculates CUFE and QR code
invoice.finalizeDocument();

// Retrieve the QR code
const qrCode = invoice.getQRCode();
console.log('QR Code:', qrCode);
Always call finalizeDocument() after setting all invoice data and before generating XML. This ensures the CUFE and QR code include all invoice information.

DIAN Extension Components

Invoice Control

Contains authorization and numbering information:
import { 
  InvoiceControl, 
  PeriodType, 
  AuthorizedInvoices 
} from 'ubl-builder';

const invoiceControl = new InvoiceControl({
  invoiceAuthorization: '18764003560527',
  authorizationPeriod: new PeriodType({
    startDate: '2019-01-19',
    endDate: '2030-01-19'
  }),
  authorizedInvoices: new AuthorizedInvoices({
    prefix: 'SETP',
    from: '990000000',
    to: '995000000'
  })
});

Invoice Source

Identifies the country of origin:
import { InvoiceSource } from 'ubl-builder';

const invoiceSource = new InvoiceSource({
  identificationCode: {
    content: 'CO',
    attributes: {
      listAgencyID: '6',
      listAgencyName: 'United Nations Economic Commission for Europe',
      listSchemeURI: 'urn:oasis:names:specification:ubl:codelist:gc:CountryIdentificationCode-2.1'
    }
  }
});

Software Provider

Identifies the technology provider and software:
import { SoftwareProvider, UdtIdentifier } from 'ubl-builder';

const softwareProvider = new SoftwareProvider({
  // Technology provider's NIT
  providerID: new UdtIdentifier('900123456', {
    schemeAgencyID: '195',
    schemeAgencyName: 'CO, DIAN (Dirección de Impuestos y Aduanas Nacionales)',
    schemeID: '9', // NIT verification digit
    schemeName: '31' // Document type: NIT
  }),
  // Software UUID assigned by DIAN
  softwareID: new UdtIdentifier('0d2e2883-eb8e-4e48-9d89-9e1a87a9e413', {
    schemeAgencyID: '195',
    schemeAgencyName: 'CO, DIAN (Dirección de Impuestos y Aduanas Nacionales)'
  })
});

Software Security Code

SHA-384 hash for software validation:
import { SHA384 } from 'ubl-builder';
import { UdtIdentifier } from 'ubl-builder';

// Calculate hash: softwareID + pin + invoiceNumber
const securityCodeInput = 
  options.software.id + 
  options.software.pin + 
  invoice.getID();

const securityCodeHash = new SHA384().getHash(
  securityCodeInput,
  'binary',
  'hex'
);

const softwareSecurityCode = new UdtIdentifier(securityCodeHash, {
  schemeAgencyID: '195',
  schemeAgencyName: 'CO, DIAN (Dirección de Impuestos y Aduanas Nacionales)'
});

Authorization Provider

Always DIAN for Colombian invoices:
import { AuthorizationProvider, UdtIdentifier } from 'ubl-builder';

const authorizationProvider = new AuthorizationProvider({
  authorizationProviderID: new UdtIdentifier('800197268', {
    schemeAgencyID: '195',
    schemeAgencyName: 'CO, DIAN (Dirección de Impuestos y Aduanas Nacionales)',
    schemeID: '4', // Verification digit
    schemeName: '31' // NIT
  })
});

CUFE Calculation

The CUFE (Código Único de Factura Electrónica) is a unique identifier calculated using SHA-384:
// CUFE components (in order):
// 1. Invoice number (prefix + number)
// 2. Issue date
// 3. Issue time
// 4. Line extension amount (before taxes)
// 5. Tax code 01 (IVA)
// 6. IVA amount
// 7. Tax code 04 (INC)
// 8. INC amount
// 9. Tax code 03 (ICA)
// 10. ICA amount
// 11. Payable amount
// 12. Supplier NIT
// 13. Customer NIT
// 14. Technical key (or software PIN for contingency)
// 15. Environment (1 or 2)

const cufeComponents = [
  'SETP990000001',
  '2024-03-06',
  '10:30:45-05:00',
  '1000000.00',
  '01',
  '190000.00',
  '04',
  '0.00',
  '03',
  '0.00',
  '1190000.00',
  '900123456',
  '800123456',
  'fc8eac425c29d8c3fc8eac420b26cf00668ea99812ab8',
  '2'
].join('');

const cufe = new SHA384().getHash(cufeComponents, 'binary', 'hex');

// Set as invoice UUID
invoice.setUUID(cufe, {
  schemeName: 'CUFE-SHA384',
  schemeID: '2' // Environment
});
For contingency invoices (type code ‘03’), the software PIN is used instead of the technical key in the CUFE calculation.

QR Code Generation

The QR code is a SHA-384 hash of the DIAN verification URL:
import { SHA384 } from 'ubl-builder';

// Get CUFE from invoice
const cufe = invoice.children.uuid.content;

// Generate QR code URL
const qrUrl = `https://catalogovpfe.dian.gov.co/document/searchqr?documentkey=${cufe}`;

// Calculate QR code hash
const qrCode = new SHA384().getHash(qrUrl, 'binary', 'hex');

// Set in DIAN extensions
invoice.children.UBLExtensions
  .getDianUblExtension()
  .getExtensionContent()
  .getDianExtensionsContent()
  .setQRCode(qrCode);

// Retrieve later
const retrievedQR = invoice.getQRCode();

Manual Extension Creation

For advanced use cases, create extensions manually:
import {
  UBLExtensions,
  UBLExtensionType,
  DianExtensions,
  DianExtensionsContent,
  InvoiceControl,
  InvoiceSource,
  SoftwareProvider,
  AuthorizationProvider,
  PeriodType,
  AuthorizedInvoices,
  UdtIdentifier
} from 'ubl-builder';

const ublExtensions = new UBLExtensions();

ublExtensions.addUBLExtension(
  new UBLExtensionType({
    extensionContent: new DianExtensions({
      dianExtensions: new DianExtensionsContent({
        invoiceControl: new InvoiceControl({
          invoiceAuthorization: '18764003560527',
          authorizationPeriod: new PeriodType({
            startDate: '2019-01-19',
            endDate: '2030-01-19'
          }),
          authorizedInvoices: new AuthorizedInvoices({
            prefix: 'SETP',
            from: '990000000',
            to: '995000000'
          })
        }),
        invoiceSource: new InvoiceSource({
          identificationCode: {
            content: 'CO',
            attributes: {
              listAgencyID: '6',
              listAgencyName: 'United Nations Economic Commission for Europe',
              listSchemeURI: 'urn:oasis:names:specification:ubl:codelist:gc:CountryIdentificationCode-2.1'
            }
          }
        }),
        softwareProvider: new SoftwareProvider({
          providerID: new UdtIdentifier('900123456', {
            schemeAgencyID: '195',
            schemeAgencyName: 'CO, DIAN (Dirección de Impuestos y Aduanas Nacionales)',
            schemeID: '9',
            schemeName: '31'
          }),
          softwareID: new UdtIdentifier('0d2e2883-eb8e-4e48-9d89-9e1a87a9e413', {
            schemeAgencyID: '195',
            schemeAgencyName: 'CO, DIAN (Dirección de Impuestos y Aduanas Nacionales)'
          })
        }),
        softwareSecurityCode: new UdtIdentifier('calculated_hash', {
          schemeAgencyID: '195',
          schemeAgencyName: 'CO, DIAN (Dirección de Impuestos y Aduanas Nacionales)'
        }),
        authorizationProvider: new AuthorizationProvider({
          authorizationProviderID: new UdtIdentifier('800197268', {
            schemeAgencyID: '195',
            schemeAgencyName: 'CO, DIAN (Dirección de Impuestos y Aduanas Nacionales)',
            schemeID: '4',
            schemeName: '31'
          })
        }),
        QRCode: 'calculated_qr_hash'
      })
    })
  })
);

invoice.setUBLExtensions(ublExtensions);

Invoice Type Codes

DIAN defines specific invoice types:
  • 01: Standard invoice (Factura de venta)
  • 02: Export invoice (Factura de exportación)
  • 03: Contingency invoice (Factura de contingencia)
  • 91: Credit note (Nota crédito)
  • 92: Debit note (Nota débito)
// Standard invoice
invoice.setInvoiceTypeCode('01');

// Contingency invoice (uses software PIN instead of technical key)
invoice.setInvoiceTypeCode('03');

Testing Environments

const invoice = new Invoice('SETT990000001', {
  enviroment: '2', // Testing
  issuer: {
    resolutionNumber: '18764003560527',
    technicalKey: 'test_technical_key',
    prefix: 'SETT', // Test prefix
    startRange: '990000000',
    endRange: '995000000',
    startDate: '2019-01-19',
    endDate: '2030-01-19'
  },
  software: {
    id: 'test-software-uuid',
    pin: '12345',
    providerNit: '900123456'
  }
});

invoice.setProfileExecutionID('2'); // Testing environment
Use different prefixes and configurations for testing vs. production. Never send test invoices to the production environment.

Complete Example

import { Invoice } from 'ubl-builder';

// Create invoice with DIAN configuration
const invoice = new Invoice('SETP990000001', {
  timestamp: Date.now(),
  enviroment: '2',
  issuer: {
    resolutionNumber: '18764003560527',
    technicalKey: 'fc8eac425c29d8c3fc8eac420b26cf00668ea99812ab8',
    prefix: 'SETP',
    startRange: '990000000',
    endRange: '995000000',
    startDate: '2019-01-19',
    endDate: '2030-01-19'
  },
  software: {
    id: '0d2e2883-eb8e-4e48-9d89-9e1a87a9e413',
    pin: '12345',
    providerNit: '900123456'
  }
});

// Set basic properties
invoice.setDefaultProperties();
invoice.setUBLVersionID('UBL 2.1');
invoice.setProfileID('DIAN 2.1');
invoice.setProfileExecutionID('2');
invoice.setIssueDate('2024-03-06');
invoice.setIssueTime('10:30:45-05:00');
invoice.setInvoiceTypeCode('01');
invoice.setDocumentCurrencyCode('COP');

// Add parties, lines, taxes, etc.
// ... (see other guides)

// Generate DIAN extensions
invoice.calculateDianExtension();

// Finalize (calculates CUFE and QR code)
invoice.finalizeDocument();

// Get QR code
const qrCode = invoice.getQRCode();
console.log('QR Code:', qrCode);

// Generate XML
const xml = invoice.getXml(true, false);

Best Practices

Configuration Management

  • Store DIAN credentials securely (environment variables, secrets manager)
  • Use different prefixes for test and production
  • Validate resolution number and date ranges
  • Keep software ID and PIN confidential
  • Rotate technical keys periodically

CUFE and QR Codes

  • Always call calculateDianExtension() before finalizeDocument()
  • Never modify invoice data after calling finalizeDocument()
  • Store CUFE with invoice for later reference
  • Include QR code in printed/PDF invoices
  • Test CUFE generation with known values

Compliance

  • Follow DIAN technical specifications v1.9 or later
  • Use correct invoice type codes
  • Include all required DIAN extensions
  • Test in DIAN testing environment before production
  • Keep authorization documents and resolution numbers current

Troubleshooting

CUFE Mismatch

If DIAN rejects the CUFE:
  1. Verify all amounts have exactly 2 decimal places
  2. Check tax amounts match tax totals exactly
  3. Ensure supplier and customer NITs are correct
  4. Verify technical key is correct
  5. Confirm environment setting matches

Extension Validation Errors

If DIAN validation fails:
  1. Ensure calculateDianExtension() was called
  2. Verify software ID is a valid UUID
  3. Check resolution number format
  4. Confirm authorization dates are valid
  5. Validate NIT format and verification digits

QR Code Issues

If QR code doesn’t verify:
  1. Confirm finalizeDocument() was called
  2. Check CUFE was calculated correctly
  3. Verify QR code URL format
  4. Test with DIAN’s QR code validator

Next Steps

Creating Invoices

Complete guide to invoice creation

Tax Calculations

Colombian tax configuration

DIAN Documentation

Official DIAN resources (external)

API Reference

Explore extension classes

Build docs developers (and LLMs) love