npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@nextpyme/sdk

v1.0.0

Published

SDK oficial de Nextpyme para facturación electrónica, nómina y documentos DIAN Colombia

Readme

@nextpyme/sdk

SDK oficial de Nextpyme para facturación electrónica, nómina electrónica, documento soporte y más servicios DIAN en Colombia.

Un solo npm install y tienes todo listo: autenticación, reintentos opcionales, manejo de errores, y acceso a todos los endpoints de la API.


Instalación

npm install @nextpyme/sdk

Compatible con Node.js >= 18 (usa fetch nativo). Funciona con ESM y CommonJS.

// ESM
import { NextpymeClient } from '@nextpyme/sdk';

// CommonJS
const { NextpymeClient } = require('@nextpyme/sdk');

Inicio rápido

import { NextpymeClient } from '@nextpyme/sdk';

const nextpyme = new NextpymeClient({
  token: 'tu-bearer-token-aqui', // Obtenlo en https://nextpyme.plus
});

// Consultar datos de la empresa
const empresa = await nextpyme.reports.company();
console.log(empresa);

// Emitir una factura
const factura = await nextpyme.invoice.create({
  number: 1,
  type_document_id: 1,
  customer: { ... },
  legal_monetary_totals: { ... },
  invoice_lines: [ ... ],
});
console.log(factura);
// { success: true, message: '...', dian: { isValid: true, ... }, cufe: '...', ... }

Configuración

const nextpyme = new NextpymeClient({
  // Requerido
  token: 'eyJhbGciOi...',         // Bearer token (mínimo 50 caracteres)
  // Opcionales
  environment: 'production',       // 'production' | 'custom'
  debug: false,                    // true para ver logs en consola
  timeoutMs: 30000,                // Timeout por petición (ms)
});

| Parámetro | Tipo | Default | Descripción | |---------------|-----------|---------------------|---------------------------------------------------| | token | string | — | Requerido. Bearer token de autenticación | | environment | string | 'production' | Ambiente: production o custom | | baseUrl | string | — | URL base (solo si environment es custom) | | debug | boolean | false | Habilitar logs de debug en consola | | timeoutMs | number | 30000 | Timeout por request en milisegundos | | maxRetries | number | 2 | Máximo de reintentos cuando retry: true | | userAgent | string | '@nextpyme/sdk' | Header User-Agent personalizado |

Ambientes

| Ambiente | URL base | |----------------|---------------------------------------| | production | https://api.nextpyme.plus/api | | custom | La que definas en baseUrl |


Opciones por petición

Todos los métodos que reciben opts aceptan:

| Opción | Tipo | Default | Descripción | |-------------|-----------------------------|---------|------------------------------------------| | retry | boolean | false | Habilitar reintentos (429/5xx/red) | | timeoutMs | number | 30000 | Timeout para esta petición | | headers | Record<string, string> | {} | Headers adicionales |

// Sin reintentos (default)
await nextpyme.invoice.create(body);

// Con reintentos habilitados
await nextpyme.invoice.create(body, { retry: true });

// Con timeout extendido
await nextpyme.invoice.create(body, { retry: true, timeoutMs: 60000 });

Servicios disponibles

| # | Módulo | Método | HTTP | Endpoint | Descripción | |----|---------------------|-------------------------------|------|-----------------------------------------------|----------------------------------------------| | 1 | invoice | create(body, opts?) | POST | /ubl2.1/invoice | Factura electrónica de venta | | 2 | | creditNote(body, opts?) | POST | /ubl2.1/credit-note | Nota crédito | | 3 | | debitNote(body, opts?) | POST | /ubl2.1/debit-note | Nota débito | | 4 | | eqdoc(body, opts?) | POST | /ubl2.1/eqdoc | Factura POS (documento equivalente) | | 5 | | exportInvoice(body, opts?) | POST | /ubl2.1/invoice-export | Factura de exportación | | 6 | | contingency(body, opts?) | POST | /ubl2.1/invoice-contingency | Factura en contingencia | | 7 | | aiu(body, opts?) | POST | /ubl2.1/invoice-aiu | Factura AIU (construcción) | | 8 | | transport(body, opts?) | POST | /ubl2.1/invoice-transport | Factura de transporte | | 9 | | mandate(body, opts?) | POST | /ubl2.1/invoice-mandate | Factura de mandato | | 10 | payroll | create(body, opts?) | POST | /ubl2.1/payroll | Nómina electrónica individual | | 11 | | adjustNote(body, opts?) | POST | /ubl2.1/payroll-adjust-note | Nota de ajuste de nómina | | 12 | supportDocument | create(body, opts?) | POST | /ubl2.1/support-document | Documento soporte | | 13 | | creditNote(body, opts?) | POST | /ubl2.1/sd-credit-note | Nota crédito documento soporte | | 14 | events | sendWithData(body, opts?) | POST | /ubl2.1/send-event-data | Evento RADIAN con datos | | 15 | | sendWithXml(body, opts?) | POST | /ubl2.1/send-event | Evento RADIAN con XML adjunto | | 16 | status | document(uuid) | POST | /ubl2.1/status/document/{uuid} | Estado de documento en DIAN | | 17 | | events(uuid) | POST | /ubl2.1/status/events-document/{uuid} | Eventos de una factura en DIAN | | 18 | | documentInfo(uuid) | POST | /ubl2.1/status/document-info/{uuid} | Documento resumen DIAN | | 19 | reports | software() | GET | /ubl2.1/reports/software | Datos del software en DIAN | | 20 | | company() | GET | /ubl2.1/config/company | Datos de la empresa | | 21 | | resolutions(filters?) | GET | /ubl2.1/reports/resolutions | Resoluciones configuradas | | 22 | | dashboard(body) | POST | /ubl2.1/reports/dashboard | Dashboard de consumos | | 23 | | masterTables(body) | POST | /ubl2.1/reports/master/database | Tablas maestras (municipios, etc.) | | 24 | | certificates(nit) | GET | /ubl2.1/certificates-listing/{nit} | Certificados digitales y vencimiento | | 25 | config | logo(body) | PUT | /ubl2.1/config/logo | Configurar logotipo (base64) | | 26 | | environment(body) | PUT | /ubl2.1/config/environment | Cambiar ambiente facturación/nómina | | 27 | | resolution(body) | PUT | /ubl2.1/config/resolution | Configurar resolución de numeración | | 28 | | changeTemplate(body) | PUT | /ubl2.1/config/change-template | Cambiar plantilla del PDF | | 29 | downloads | download(nit, filename) | GET | /ubl2.1/download/{nit}/{filename} | Descargar cualquier archivo del documento | | 30 | | xmlFromDian(uuid) | POST | /ubl2.1/xml/document/{uuid} | Descargar XML directamente desde la DIAN | | 31 | | joinPdfs(body) | POST | /ubl2.1/join-pdfs | Unir múltiples PDFs en uno | | 32 | email | send(body) | POST | /ubl2.1/send-email | Reenviar email de un documento | | 33 | plans | userInfo() | GET | /ubl2.1/plan/infoplanuser | Folios disponibles del usuario | | 34 | | listPackages() | GET | /ubl2.1/plan/assign-package-user | Paquetes asignados (solo aliados) | | 35 | | assignPackage(body) | PUT | /ubl2.1/plan/assign-package-user | Asignar paquete (solo aliados) | | 36 | dian | statusDocument(trackId) | POST | /ubl2.1/status/document/{trackId} | Estado de documento en DIAN por CUFE/UUID | | 37 | | numberingRange(body) | POST | /ubl2.1/numbering-range | Resoluciones de numeración DIAN | | 38 | | rutRues(body) | POST | /ubl2.1/rut-rues | Consultar RUT/RUES de un tercero | | 39 | | invoiceData(body) | GET | /return-invoice-data | Compras recibidas |


Módulos y ejemplos

nextpyme.invoice — Facturación electrónica

// Factura de venta
const factura = await nextpyme.invoice.create(body);
// { success: true, message: '...', dian: { isValid: true, ... }, cufe: '...' }

// Con reintentos
const factura = await nextpyme.invoice.create(body, { retry: true });

// Nota crédito (requiere billing_reference con CUFE de la factura original)
const nc = await nextpyme.invoice.creditNote(body);

// Nota débito
const nd = await nextpyme.invoice.debitNote(body);

// Factura POS (documento equivalente electrónico)
const pos = await nextpyme.invoice.eqdoc(body);

// Variantes especiales — mismo payload base, URL distinta
const exportacion  = await nextpyme.invoice.exportInvoice(body);
const contingencia = await nextpyme.invoice.contingency(body);
const construccion = await nextpyme.invoice.aiu(body);
const transporte   = await nextpyme.invoice.transport(body);
const mandato      = await nextpyme.invoice.mandate(body);

nextpyme.payroll — Nómina electrónica

// Emitir nómina individual
const nomina = await nextpyme.payroll.create(body);

// Nota de ajuste (reemplazo o eliminación)
const ajuste = await nextpyme.payroll.adjustNote(body);

nextpyme.supportDocument — Documento soporte

// Documento soporte (proveedores no obligados a facturar)
const ds = await nextpyme.supportDocument.create(body);

// Nota crédito de documento soporte
const ncds = await nextpyme.supportDocument.creditNote(body);

nextpyme.events — Eventos RADIAN

// Evento con datos (sin XML)
const evento = await nextpyme.events.sendWithData({
  event_id: 1,
  type_rejection_id: null,
  document_reference: { cufe: 'abc123...' },
});

// Evento con XML adjunto
const eventoXml = await nextpyme.events.sendWithXml({
  event_id: 1,
  base64_attacheddocument_name: 'documento.xml',
  base64_attacheddocument: 'PD94bWwg...',
});

IDs de eventos RADIAN

| event_id | Código DIAN | Evento | |:----------:|:-----------:|--------| | 1 | 030 | Acuse de recibo de Factura Electrónica de Venta | | 2 | 031 | Reclamo de la Factura Electrónica de Venta | | 3 | 032 | Recibo del bien y/o prestación del servicio | | 4 | 033 | Aceptación expresa | | 5 | 034 | Aceptación tácita | | 6 | 02 | Documento validado por la DIAN | | 7 | 04 | Documento rechazado por la DIAN |

nextpyme.status — Consultas de estado DIAN

// Validar estado de un documento
const estado = await nextpyme.status.document('uuid-del-documento');

// Ver eventos de una factura
const eventos = await nextpyme.status.events('uuid-del-documento');

// Documento resumen DIAN
const info = await nextpyme.status.documentInfo('uuid-del-documento');

nextpyme.reports — Reportes y consultas

// Datos del software registrado en DIAN
const sw = await nextpyme.reports.software();

// Datos de la empresa
const empresa = await nextpyme.reports.company();

// Resoluciones configuradas (con filtros opcionales)
const todas = await nextpyme.reports.resolutions();
const filtradas = await nextpyme.reports.resolutions({
  prefix: 'SETP',
  type_document_id: 1,
  resolution: '18760000001',
});

// Dashboard de consumos por rango de fechas
const dashboard = await nextpyme.reports.dashboard({
  date_between: true,
  start_date: '2025-01-01 00:00:00',
  end_date: '2025-12-31 23:59:59',
});

// Tablas maestras (municipios, departamentos, etc.)
const tablas = await nextpyme.reports.masterTables({
  tables: [{ table: 'municipalities' }, { table: 'departments' }],
});

// Certificados digitales y vencimiento
const certs = await nextpyme.reports.certificates('900123456');

nextpyme.config — Configuración de la empresa

// Configurar logotipo (solo JPG, base64 sin prefijo)
await nextpyme.config.logo({ logo: '/9j/4AAQSkZJRg...' });

// Cambiar ambiente de facturas (1=Producción, 2=Pruebas)
await nextpyme.config.environment({ type_environment_id: 2 });

// Cambiar ambiente de factura POS (1=Producción, 2=Pruebas)
await nextpyme.config.environment({ eqdocs_type_environment_id: 2 });

// Cambiar ambiente de nómina (1=Pruebas, 2=Producción)
await nextpyme.config.environment({ payroll_type_environment_id: 2 });

// Configurar resolución de numeración
await nextpyme.config.resolution({
  type_document_id: 1,
  prefix: 'SETP',
  resolution: '18764000001',
  resolution_date: '2019-01-19',
  technical_key: 'fc8e...',
  from: 990000000,
  to: 995000000,
  date_from: '2019-01-19',
  date_to: '2030-01-19',
});

// Cambiar plantilla del PDF ("2", "one", "two", "four")
await nextpyme.config.changeTemplate({ template_name: 'one' });

nextpyme.downloads — Descargas de archivos

El nombre del archivo sigue convenciones según su tipo:

| Archivo | Patrón | Ejemplo | |---------|--------|---------| | PDF | {DOC_PREFIX}-{prefix}{number}.pdf | FES-SETP990000001.pdf | | XML Invoice (UBL) | {DOC_PREFIX}-{prefix}{number}.xml | FES-SETP990000001.xml | | XML AttachedDocument | Attachment-{prefix}{number}.xml | Attachment-SETP990000001.xml | | ZIP (PDF + Attached) | ZipAttachm-{prefix}{number}.zip | ZipAttachm-SETP990000001.zip | | Respuesta DIAN SOAP | RptaFE-{prefix}{number}.xml | RptaFE-SETP990000001.xml |

Donde DOC_PREFIX es: FES, NCS, NDS, DSS, POSS, NIS, NAS.

const nit = '900123456';

// Formato nativo (default)
await nextpyme.downloads.download(nit, 'FES-SETP990000001.pdf');

// Contenido en base64
await nextpyme.downloads.download(nit, 'FES-SETP990000001.pdf', { base64: true });

// XML Invoice
await nextpyme.downloads.download(nit, 'FES-SETP990000001.xml');

// XML AttachedDocument
await nextpyme.downloads.download(nit, 'Attachment-SETP990000001.xml');

// ZIP
await nextpyme.downloads.download(nit, 'ZipAttachm-SETP990000001.zip');

// Respuesta DIAN SOAP
await nextpyme.downloads.download(nit, 'RptaFE-SETP990000001.xml');

// XML directamente desde la DIAN por UUID/CUFE
await nextpyme.downloads.xmlFromDian('67cf0488234...');

// Unir múltiples PDFs en uno
const joined = await nextpyme.downloads.joinPdfs({
  name_joined_pdfs: 'reporte-mensual',
  pdfs: [
    { type_document_id: 1, prefix: 'SETP', number: '990000001' },
    { type_document_id: 1, prefix: 'SETP', number: '990000002' },
  ],
});

nextpyme.email — Envío de emails

await nextpyme.email.send({
  prefix: 'SETP',
  number: '990000001',
  alternate_email: '[email protected]',
  showacceptrejectbuttons: true,
  email_cc_list: [{ email: '[email protected]' }],
  send_email_cc_list_as_email_cc: true,
});

nextpyme.plans — Planes y recargas

// Consultar folios disponibles
const info = await nextpyme.plans.userInfo();

// Ver paquetes asignados (solo aliados)
const paquetes = await nextpyme.plans.listPackages();

// Asignar paquete de documentos (solo aliados)
await nextpyme.plans.assignPackage({
  user_identification_number: 900123456,
  absolut_start_plan_date: '2025-01-01',
  absolut_documents: 1000,
});

nextpyme.dian — Consultas directas DIAN

// Consultar estado de un documento en DIAN por CUFE/UUID
const estado = await nextpyme.dian.statusDocument('002515775b03ae7674b470788f07...');
// {
//   success: true,
//   message: 'Consulta generada con éxito',
//   dian: {
//     isValid: true,
//     statusCode: '00',
//     statusDescription: 'Procesado Correctamente.',
//     statusMessage: 'La Factura electrónica FE212, ha sido autorizada.',
//     errorMessage: [],
//   },
//   cufecude: '002515775b03ae7674b470...',
//   ...
// }

// Consultar resoluciones de numeración en DIAN
const rangos = await nextpyme.dian.numberingRange({
  IDSoftware: 'tu-id-software',
});
// {
//   success: true,
//   message: 'Acción completada OK.',
//   resolutions: [
//     {
//       prefix: 'SETP',
//       resolution: '18764000001',
//       resolution_date: '2021-08-25',
//       technical_key: 'fc8e...',
//       from: 990000000,
//       to: 995000000,
//       date_from: '2019-01-19',
//       date_to: '2030-01-19',
//     },
//   ],
// }

// Usar la resolución directamente en config:
const { resolutions } = await nextpyme.dian.numberingRange({ IDSoftware: '...' });
if (resolutions.length > 0) {
  await nextpyme.config.resolution({
    type_document_id: 1,
    ...resolutions[0],
  });
}

// Consultar RUT/RUES de un tercero
const rut = await nextpyme.dian.rutRues({
  identification_number: 900123456,
  type_document_identification_id: 3,  // 1=CC, 2=CE, 3=NIT, etc.
  rues: true,
});

// Ver compras recibidas
const compras = await nextpyme.dian.invoiceData();

Formato de respuestas

Módulos de emisión (invoice, payroll, supportDocument, events)

Devuelven la respuesta de la API con el campo dian normalizado:

{
  "success": true,
  "message": "Factura generada exitosamente.",
  "dian": {
    "isValid": true,
    "statusCode": "00",
    "statusDescription": "Procesado Correctamente.",
    "statusMessage": "La Factura electrónica FE001, ha sido autorizada.",
    "errorMessage": []
  },
  "cufe": "abc123...",
  "urlinvoicepdf": "FES-SETP990000001.pdf",
  "urlinvoicexml": "FES-SETP990000001.xml"
}

Módulo reports (respuesta formateada)

{
  ok: true,       // Booleano basado en success de la API
  message: '...',
  data: { ... },  // Datos extraídos automáticamente
  raw: { ... },   // Respuesta cruda completa
}

Módulo dian.numberingRange() (respuesta normalizada)

{
  success: true,
  message: '...',
  resolutions: [ ... ],  // Siempre array (vacío si no hay datos)
  raw: { ... },
}

Manejo de errores

import { NextpymeClient, NextpymeError, AuthError, ValidationError, ServerError } from '@nextpyme/sdk';

try {
  const factura = await nextpyme.invoice.create(body);
} catch (err) {
  if (err instanceof ValidationError) {
    // 422 — Campos inválidos
    console.log(err.code);       // 'VALIDATION_FAILED'
    console.log(err.status);     // 422
    console.log(err.details);    // { success: false, errors: { campo: ['...'] } }
  }

  if (err instanceof AuthError) {
    // 401/403 — Token inválido o expirado
    console.log(err.code);       // 'AUTH_INVALID'
  }

  if (err instanceof ServerError) {
    // 500-504 — Error del servidor
    console.log(err.code);       // 'SERVER_ERROR'
  }

  if (err instanceof NextpymeError) {
    // Cualquier error del SDK
    console.log(err.toJSON());
  }
}

Códigos de error

| Código | Clase | HTTP | Descripción | |---------------------|-------------------|---------|-----------------------------------------| | AUTH_INVALID | AuthError | 401/403 | Token inválido, expirado o sin permisos | | VALIDATION_FAILED | ValidationError | 422 | Campos requeridos o datos inválidos | | SERVER_ERROR | ServerError | 500-504 | Error interno del servidor | | HTTP_ERROR | NextpymeError | Otros | Cualquier otro error HTTP | | TIMEOUT | NextpymeError | — | La petición excedió el timeout | | NETWORK_ERROR | NextpymeError | — | Sin conexión o DNS no resuelto |

Estructura uniforme (toJSON())

app.post('/factura', async (req, res) => {
  try {
    const result = await nextpyme.invoice.create(req.body);
    res.json(result);
  } catch (err) {
    res.status(err.status || 500).json(err); // toJSON() se aplica automáticamente
  }
});
{
  "success": false,
  "message": "Error de validación.",
  "code": "VALIDATION_FAILED",
  "status": 422,
  "method": "POST",
  "path": "/ubl2.1/invoice",
  "errors": { "campo": ["El campo es requerido."] }
}

Reintentos

Los reintentos están desactivados por defecto. Se habilitan por petición con { retry: true }:

// Sin reintentos (default)
await nextpyme.invoice.create(body);

// Con reintentos
await nextpyme.invoice.create(body, { retry: true });

| Se reintenta | No se reintenta | |---------------------------|---------------------------| | HTTP 429 (rate limiting) | HTTP 401/403 (auth) | | HTTP 500-504 (servidor) | HTTP 422 (validación) | | Errores de red | HTTP 404 (no encontrado) |

Espera entre reintentos (backoff exponencial): 500ms → 1s → 2s → 4s...

El máximo de reintentos se configura globalmente con maxRetries (default: 2).


Modo debug

const nextpyme = new NextpymeClient({
  token: '...',
  debug: true,
});
[NEXTPYME SDK] POST /ubl2.1/invoice → request { body: { ... } }
[NEXTPYME SDK] POST /ubl2.1/invoice ← 200 (432ms)

Middlewares personalizados

nextpyme.http.useMiddleware(async (ctx, next) => {
  ctx.headers['X-Custom-Header'] = 'valor';
  const response = await next();
  console.log(`Response status: ${response.status}`);
  return response;
});

Plugins

const miPlugin = {
  name: 'mi-plugin',
  setup({ client, http }) {
    http.useMiddleware(async (ctx, next) => {
      return next();
    });

    client.miModulo = {
      async miMetodo() {
        const res = await http.get('/mi-endpoint');
        return res.json;
      },
    };
  },
};

const nextpyme = new NextpymeClient({ token: '...' });
nextpyme.use(miPlugin);

Ejemplo completo: Express + SDK

import express from 'express';
import { NextpymeClient, ValidationError, AuthError } from '@nextpyme/sdk';

const app = express();
app.use(express.json());

const nextpyme = new NextpymeClient({
  token: process.env.NEXTPYME_TOKEN,
  environment: 'production',
});

// Emitir factura
app.post('/api/facturas', async (req, res) => {
  try {
    const result = await nextpyme.invoice.create(req.body);
    res.json(result);
  } catch (err) {
    if (err instanceof ValidationError) {
      return res.status(422).json(err);
    }
    if (err instanceof AuthError) {
      return res.status(401).json(err);
    }
    res.status(500).json({ success: false, message: err.message });
  }
});

// Consultar estado
app.get('/api/facturas/:uuid/estado', async (req, res) => {
  try {
    const estado = await nextpyme.status.document(req.params.uuid);
    res.json(estado);
  } catch (err) {
    res.status(err.status || 500).json(err);
  }
});

app.listen(3000);

Licencia

MIT