Ejemplo en TypeScript
Este ejemplo usa el SDK @openubl/sdk con validación runtime mediante los schemas Zod generados desde OpenAPI.
Crear y firmar una factura
Sección titulada «Crear y firmar una factura»import { createInvoice } from "@openubl/sdk";import { zInvoiceCreateRequest } from "@openubl/sdk/zod.gen";
const request = zInvoiceCreateRequest.parse({ documento: { serie: "F001", numero: 1, proveedor: { ruc: "20100111111", razonSocial: "Mi Empresa S.A.C.", }, cliente: { nombre: "Juan Perez", numeroDocumentoIdentidad: "12345678", tipoDocumentoIdentidad: "1", }, detalles: [ { descripcion: "Producto A", cantidad: 2, precio: 100.0, }, ], moneda: "PEN", }, firmar: true, validar_sunat: true, credenciales: { cert_pem: process.env.CERT_PEM ?? "", key_pem: process.env.KEY_PEM ?? "", },});
async function createAndSign() { const { data, error } = await createInvoice({ body: request });
if (error) { throw new Error(`Error al crear factura: ${JSON.stringify(error)}`); }
console.log("XML firmado:\n", data.xml); console.log("Validado SUNAT:", data.validado_sunat, data.valid);}
createAndSign();Variantes rápidas
Sección titulada «Variantes rápidas»Nota de crédito
Sección titulada «Nota de crédito»import { createCreditNote } from "@openubl/sdk";import { zCreditNoteCreateRequest } from "@openubl/sdk/zod.gen";
const request = zCreditNoteCreateRequest.parse({ documento: { serie: "BC01", numero: 1, comprobanteAfectadoSerieNumero: "F001-1", sustentoDescripcion: "Anulación de venta", proveedor: { ruc: "20100111111", razonSocial: "Mi Empresa S.A.C." }, cliente: { nombre: "Juan Perez", numeroDocumentoIdentidad: "12345678", tipoDocumentoIdentidad: "1" }, detalles: [{ descripcion: "Producto A", cantidad: 2, precio: 100 }], moneda: "PEN", }, firmar: false, validar_sunat: true,});
const { data, error } = await createCreditNote({ body: request });if (error) throw error;console.log(data.xml);Comunicación de baja
Sección titulada «Comunicación de baja»import { createVoidedDocuments } from "@openubl/sdk";import { zVoidedDocumentsCreateRequest } from "@openubl/sdk/zod.gen";
const request = zVoidedDocumentsCreateRequest.parse({ documento: { numero: 1, fechaEmisionComprobantes: "2024-01-15", proveedor: { ruc: "20100111111", razonSocial: "Mi Empresa S.A.C." }, comprobantes: [ { serie: "F001", numero: 1, tipoComprobante: "01", descripcionSustento: "Error en datos del cliente", }, ], }, firmar: false, validar_sunat: true,});
const { data, error } = await createVoidedDocuments({ body: request });if (error) throw error;console.log(data.xml);Con fetch nativo
Sección titulada «Con fetch nativo»Si prefieres no usar el SDK, puedes llamar a la API directamente con fetch:
const BASE_URL = "http://localhost:8000";
const createRes = await fetch(`${BASE_URL}/api/v1/invoice/create`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ documento: { /* ... */ }, firmar: false, validar_sunat: true, }),});
if (!createRes.ok) { const err = await createRes.json(); throw new Error(`Error: ${JSON.stringify(err.detail)}`);}
const { xml, firmado, validado_sunat, valid, errors } = await createRes.json();Nota sobre alcance
Sección titulada «Nota sobre alcance»openUBL Server devuelve el XML técnico. El empaquetado ZIP, envío a SUNAT y procesamiento del CDR son responsabilidad del cliente operativo.