Ir al contenido

Ejemplo en TypeScript

Este ejemplo usa el SDK @openubl/sdk con validación runtime mediante los schemas Zod generados desde OpenAPI.

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();
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);
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);

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();

openUBL Server devuelve el XML técnico. El empaquetado ZIP, envío a SUNAT y procesamiento del CDR son responsabilidad del cliente operativo.