Ejemplos de uso
Los siguientes ejemplos asumen que el servidor está corriendo en http://localhost:8000. El primer ejemplo usa httpx, pero puedes reemplazarlo por requests sin cambiar la lógica.
Crear y firmar una factura
Sección titulada «Crear y firmar una factura»import osimport httpx
from openubl.models import Invoice, Proveedor, Cliente, DocumentoVentaDetalle
BASE_URL = "http://localhost:8000"
invoice = Invoice( serie="F001", numero=1, proveedor=Proveedor( ruc="20100111111", razonSocial="Mi Empresa S.A.C.", ), cliente=Cliente( nombre="Juan Perez", numeroDocumentoIdentidad="12345678", tipoDocumentoIdentidad="1", ), detalles=[ DocumentoVentaDetalle( descripcion="Producto A", cantidad=2, precio=100.00, ) ], moneda="PEN",)
request_body = { "documento": invoice.model_dump(mode="json"), "firmar": True, "validar_sunat": True, "credenciales": { "cert_pem": os.getenv("CERT_PEM", ""), "key_pem": os.getenv("KEY_PEM", ""), }, "signature_id": "SignSUNAT",}
def main(): with httpx.Client(base_url=BASE_URL) as client: r = client.post("/api/v1/invoice/create", json=request_body) r.raise_for_status() data = r.json() print("XML firmado:", data["xml"]) print("Validado SUNAT:", data["validado_sunat"], data["valid"])
if __name__ == "__main__": main()import { createInvoice } from "@openubl/sdk";import { zInvoiceCreateRequest } from "@openubl/sdk/zod.gen";
const request = zInvoiceCreateRequest.parse({documento: { serie: "F001", numero: 1, tipoOperacion: "0101", moneda: "PEN", 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.00, unidadMedida: "NIU", tipoAfectacionIGV: "10", }, ],},firmar: true,validar_sunat: true,credenciales: { cert_pem: process.env.CERT_PEM, key_pem: process.env.KEY_PEM,},signature_id: "SignSUNAT",});
const { data, error } = await createInvoice({ body: request });if (error) throw new Error(JSON.stringify(error));console.log(data.xml);console.log(data.firmado, data.validado_sunat, data.valid, data.errors);curl -X POST "http://localhost:8000/api/v1/invoice/create" \-d '{ "documento": { "serie": "F001", "numero": 1, "tipoOperacion": "0101", "moneda": "PEN", "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.00, "unidadMedida": "NIU", "tipoAfectacionIGV": "10" } ] }, "firmar": true, "validar_sunat": true, "credenciales": { "cert_pem": "$CERT_PEM", "key_pem": "$KEY_PEM" }, "signature_id": "SignSUNAT"}'Usar requests
Sección titulada «Usar requests»import requests
from openubl.models import Invoice, Proveedor, Cliente, DocumentoVentaDetalle
invoice = Invoice( serie="F001", numero=1, proveedor=Proveedor( ruc="20100111111", razonSocial="Mi Empresa S.A.C.", ), cliente=Cliente( nombre="Juan Perez", numeroDocumentoIdentidad="12345678", tipoDocumentoIdentidad="1", ), detalles=[ DocumentoVentaDetalle( descripcion="Producto A", cantidad=2, precio=100.00, ) ], moneda="PEN",)
with requests.Session() as s: r = s.post( "http://localhost:8000/api/v1/invoice/create", json={ "documento": invoice.model_dump(mode="json"), "firmar": False, "validar_sunat": True, }, ) r.raise_for_status() data = r.json() print(data["xml"]) print(data["firmado"], data["validado_sunat"], data["valid"], data["errors"])import { createInvoice } from "@openubl/sdk";import { zInvoiceCreateRequest } from "@openubl/sdk/zod.gen";
const request = zInvoiceCreateRequest.parse({documento: { serie: "F001", numero: 1, tipoOperacion: "0101", moneda: "PEN", 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.00, unidadMedida: "NIU", tipoAfectacionIGV: "10" }],},firmar: false,validar_sunat: true,});
const { data, error } = await createInvoice({ body: request });if (error) throw new Error(JSON.stringify(error));console.log(data.xml, data.firmado, data.validado_sunat, data.valid, data.errors);curl -X POST http://localhost:8000/api/v1/invoice/create \-H "Content-Type: application/json" \-d '{ "documento": { "serie": "F001", "numero": 1, "tipoOperacion": "0101", "moneda": "PEN", "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.00, "unidadMedida": "NIU", "tipoAfectacionIGV": "10" }] }, "firmar": false, "validar_sunat": true}'Nota de crédito
Sección titulada «Nota de crédito»import httpx
from openubl.models import CreditNote, Proveedor, Cliente, DocumentoVentaDetalle
BASE_URL = "http://localhost:8000"
proveedor = Proveedor( ruc="20100111111", razonSocial="Mi Empresa S.A.C.",)cliente = Cliente( nombre="Juan Perez", numeroDocumentoIdentidad="12345678", tipoDocumentoIdentidad="1",)detalles = [ DocumentoVentaDetalle( descripcion="Producto A", cantidad=2, precio=100.00, )]
credit_note = CreditNote( serie="BC01", numero=1, comprobanteAfectadoSerieNumero="F001-1", sustentoDescripcion="Anulación de venta", proveedor=proveedor, cliente=cliente, detalles=detalles, moneda="PEN",)
with httpx.Client(base_url=BASE_URL) as client: r = client.post( "/api/v1/credit-note/create", json={ "documento": credit_note.model_dump(mode="json"), "firmar": False, "validar_sunat": True, }, ) r.raise_for_status() print(r.json()["xml"])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", moneda: "PEN", 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.00, unidadMedida: "NIU", tipoAfectacionIGV: "10" }],},firmar: false,validar_sunat: true,});
const { data, error } = await createCreditNote({ body: request });if (error) throw new Error(JSON.stringify(error));console.log(data.xml);curl -X POST http://localhost:8000/api/v1/credit-note/create \-H "Content-Type: application/json" \-d '{ "documento": { "serie": "BC01", "numero": 1, "comprobanteAfectadoSerieNumero": "F001-1", "sustentoDescripcion": "Anulación de venta", "moneda": "PEN", "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.00, "unidadMedida": "NIU", "tipoAfectacionIGV": "10" }] }, "firmar": false, "validar_sunat": true}'Comunicación de baja
Sección titulada «Comunicación de baja»import httpx
from openubl.models import VoidedDocuments, VoidedDocumentsItem, Proveedorfrom datetime import date
BASE_URL = "http://localhost:8000"
proveedor = Proveedor( ruc="20100111111", razonSocial="Mi Empresa S.A.C.",)
voided = VoidedDocuments( numero=1, fechaEmisionComprobantes=date(2024, 1, 15), proveedor=proveedor, comprobantes=[ VoidedDocumentsItem( serie="F001", numero=1, tipoComprobante="01", descripcionSustento="Error en datos del cliente", ) ],)
with httpx.Client(base_url=BASE_URL) as client: r = client.post( "/api/v1/voided-documents/create", json={ "documento": voided.model_dump(mode="json"), "firmar": False, "validar_sunat": True, }, ) r.raise_for_status() print(r.json()["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 new Error(JSON.stringify(error));console.log(data.xml);curl -X POST http://localhost:8000/api/v1/voided-documents/create \-H "Content-Type: application/json" \-d '{ "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}'Nota de débito
Sección titulada «Nota de débito»import httpx
from openubl.models import DebitNote, Proveedor, Cliente, DocumentoVentaDetalle
BASE_URL = "http://localhost:8000"
debit_note = DebitNote( serie="BD01", numero=1, comprobanteAfectadoSerieNumero="F001-1", sustentoDescripcion="Intereses moratorios", proveedor=Proveedor(ruc="20100111111", razonSocial="Mi Empresa S.A.C."), cliente=Cliente(nombre="Juan Perez", numeroDocumentoIdentidad="12345678", tipoDocumentoIdentidad="1"), detalles=[DocumentoVentaDetalle(descripcion="Producto A", cantidad=2, precio=100.00)], moneda="PEN",)
with httpx.Client(base_url=BASE_URL) as client: r = client.post( "/api/v1/debit-note/create", json={ "documento": debit_note.model_dump(mode="json"), "firmar": False, "validar_sunat": True, }, ) r.raise_for_status() print(r.json()["xml"])import { createDebitNote } from "@openubl/sdk";import { zDebitNoteCreateRequest } from "@openubl/sdk/zod.gen";
const request = zDebitNoteCreateRequest.parse({documento: { serie: "BD01", numero: 1, comprobanteAfectadoSerieNumero: "F001-1", sustentoDescripcion: "Intereses moratorios", moneda: "PEN", 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.00, unidadMedida: "NIU", tipoAfectacionIGV: "10" }],},firmar: false,validar_sunat: true,});
const { data, error } = await createDebitNote({ body: request });if (error) throw new Error(JSON.stringify(error));console.log(data.xml);curl -X POST http://localhost:8000/api/v1/debit-note/create \-H "Content-Type: application/json" \-d '{ "documento": { "serie": "BD01", "numero": 1, "comprobanteAfectadoSerieNumero": "F001-1", "sustentoDescripcion": "Intereses moratorios", "moneda": "PEN", "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.00, "unidadMedida": "NIU", "tipoAfectacionIGV": "10" }] }, "firmar": false, "validar_sunat": true}'Resumen diario
Sección titulada «Resumen diario»import httpxfrom datetime import date
from openubl.models import ( SummaryDocuments, SummaryDocumentsItem, Comprobante, ComprobanteImpuestos, ComprobanteValorVenta, Proveedor, Cliente)
BASE_URL = "http://localhost:8000"
summary = SummaryDocuments( numero=1, fechaEmisionComprobantes=date(2024, 1, 15), proveedor=Proveedor(ruc="20100111111", razonSocial="Mi Empresa S.A.C."), comprobantes=[ SummaryDocumentsItem( tipoOperacion="1", comprobante=Comprobante( tipoComprobante="03", serieNumero="B001-1", cliente=Cliente(nombre="Juan Perez", numeroDocumentoIdentidad="12345678", tipoDocumentoIdentidad="1"), impuestos=ComprobanteImpuestos(igv=18.00), valorVenta=ComprobanteValorVenta(importeTotal=118.00), ), ) ],)
with httpx.Client(base_url=BASE_URL) as client: r = client.post( "/api/v1/summary-documents/create", json={ "documento": summary.model_dump(mode="json"), "firmar": False, "validar_sunat": True, }, ) r.raise_for_status() print(r.json()["xml"])import { createSummaryDocuments } from "@openubl/sdk";import { zSummaryDocumentsCreateRequest } from "@openubl/sdk/zod.gen";
const request = zSummaryDocumentsCreateRequest.parse({documento: { numero: 1, fechaEmisionComprobantes: "2024-01-15", proveedor: { ruc: "20100111111", razonSocial: "Mi Empresa S.A.C." }, comprobantes: [{ tipoOperacion: "1", comprobante: { tipoComprobante: "03", serieNumero: "B001-1", cliente: { nombre: "Juan Perez", numeroDocumentoIdentidad: "12345678", tipoDocumentoIdentidad: "1" }, impuestos: { igv: 18.00 }, valorVenta: { importeTotal: 118.00 }, }, }],},firmar: false,validar_sunat: true,});
const { data, error } = await createSummaryDocuments({ body: request });if (error) throw new Error(JSON.stringify(error));console.log(data.xml);curl -X POST http://localhost:8000/api/v1/summary-documents/create \-H "Content-Type: application/json" \-d '{ "documento": { "numero": 1, "fechaEmisionComprobantes": "2024-01-15", "proveedor": { "ruc": "20100111111", "razonSocial": "Mi Empresa S.A.C." }, "comprobantes": [{ "tipoOperacion": "1", "comprobante": { "tipoComprobante": "03", "serieNumero": "B001-1", "cliente": { "nombre": "Juan Perez", "numeroDocumentoIdentidad": "12345678", "tipoDocumentoIdentidad": "1" }, "impuestos": { "igv": 18.00 }, "valorVenta": { "importeTotal": 118.00 } } }] }, "firmar": false, "validar_sunat": true}'Percepción
Sección titulada «Percepción»import httpxfrom datetime import datefrom decimal import Decimal
from openubl.models import ( Perception, PercepcionRetencionOperacion, ComprobanteAfectado, Proveedor, Cliente)
BASE_URL = "http://localhost:8000"
perception = Perception( serie="P001", numero=1, fechaEmision=date(2024, 1, 15), proveedor=Proveedor(ruc="20100111111", razonSocial="Mi Empresa S.A.C."), cliente=Cliente(nombre="Juan Perez", numeroDocumentoIdentidad="12345678", tipoDocumentoIdentidad="1"), importeTotalPercibido=Decimal("2.00"), importeTotalCobrado=Decimal("102.00"), tipoRegimen="01", tipoRegimenPorcentaje=Decimal("2.00"), operaciones=[ PercepcionRetencionOperacion( numeroOperacion=1, fechaOperacion=date(2024, 1, 15), importeOperacion=Decimal("100.00"), comprobante=ComprobanteAfectado( tipoComprobante="01", serieNumero="F001-1", fechaEmision=date(2024, 1, 15), importeTotal=Decimal("100.00"), moneda="PEN", ), ) ],)
with httpx.Client(base_url=BASE_URL) as client: r = client.post( "/api/v1/perception/create", json={ "documento": perception.model_dump(mode="json"), "firmar": False, "validar_sunat": True, }, ) r.raise_for_status() print(r.json()["xml"])import { createPerception } from "@openubl/sdk";import { zPerceptionCreateRequest } from "@openubl/sdk/zod.gen";
const request = zPerceptionCreateRequest.parse({documento: { serie: "P001", numero: 1, fechaEmision: "2024-01-15", proveedor: { ruc: "20100111111", razonSocial: "Mi Empresa S.A.C." }, cliente: { nombre: "Juan Perez", numeroDocumentoIdentidad: "12345678", tipoDocumentoIdentidad: "1" }, importeTotalPercibido: 2.00, importeTotalCobrado: 102.00, tipoRegimen: "01", tipoRegimenPorcentaje: 2.00, operaciones: [{ numeroOperacion: 1, fechaOperacion: "2024-01-15", importeOperacion: 100.00, comprobante: { tipoComprobante: "01", serieNumero: "F001-1", fechaEmision: "2024-01-15", importeTotal: 100.00, moneda: "PEN", }, }],},firmar: false,validar_sunat: true,});
const { data, error } = await createPerception({ body: request });if (error) throw new Error(JSON.stringify(error));console.log(data.xml);curl -X POST http://localhost:8000/api/v1/perception/create \-H "Content-Type: application/json" \-d '{ "documento": { "serie": "P001", "numero": 1, "fechaEmision": "2024-01-15", "proveedor": { "ruc": "20100111111", "razonSocial": "Mi Empresa S.A.C." }, "cliente": { "nombre": "Juan Perez", "numeroDocumentoIdentidad": "12345678", "tipoDocumentoIdentidad": "1" }, "importeTotalPercibido": 2.00, "importeTotalCobrado": 102.00, "tipoRegimen": "01", "tipoRegimenPorcentaje": 2.00, "operaciones": [{ "numeroOperacion": 1, "fechaOperacion": "2024-01-15", "importeOperacion": 100.00, "comprobante": { "tipoComprobante": "01", "serieNumero": "F001-1", "fechaEmision": "2024-01-15", "importeTotal": 100.00, "moneda": "PEN" } }] }, "firmar": false, "validar_sunat": true}'Retención
Sección titulada «Retención»import httpxfrom datetime import datefrom decimal import Decimal
from openubl.models import ( Retention, PercepcionRetencionOperacion, ComprobanteAfectado, Proveedor, Cliente)
BASE_URL = "http://localhost:8000"
retention = Retention( serie="R001", numero=1, fechaEmision=date(2024, 1, 15), proveedor=Proveedor(ruc="20100111111", razonSocial="Mi Empresa S.A.C."), cliente=Cliente(nombre="Juan Perez", numeroDocumentoIdentidad="12345678", tipoDocumentoIdentidad="1"), importeTotalRetenido=Decimal("3.00"), importeTotalPagado=Decimal("97.00"), tipoRegimen="01", tipoRegimenPorcentaje=Decimal("3.00"), operaciones=[ PercepcionRetencionOperacion( numeroOperacion=1, fechaOperacion=date(2024, 1, 15), importeOperacion=Decimal("100.00"), comprobante=ComprobanteAfectado( tipoComprobante="01", serieNumero="F001-1", fechaEmision=date(2024, 1, 15), importeTotal=Decimal("100.00"), moneda="PEN", ), ) ],)
with httpx.Client(base_url=BASE_URL) as client: r = client.post( "/api/v1/retention/create", json={ "documento": retention.model_dump(mode="json"), "firmar": False, "validar_sunat": True, }, ) r.raise_for_status() print(r.json()["xml"])import { createRetention } from "@openubl/sdk";import { zRetentionCreateRequest } from "@openubl/sdk/zod.gen";
const request = zRetentionCreateRequest.parse({documento: { serie: "R001", numero: 1, fechaEmision: "2024-01-15", proveedor: { ruc: "20100111111", razonSocial: "Mi Empresa S.A.C." }, cliente: { nombre: "Juan Perez", numeroDocumentoIdentidad: "12345678", tipoDocumentoIdentidad: "1" }, importeTotalRetenido: 3.00, importeTotalPagado: 97.00, tipoRegimen: "01", tipoRegimenPorcentaje: 3.00, operaciones: [{ numeroOperacion: 1, fechaOperacion: "2024-01-15", importeOperacion: 100.00, comprobante: { tipoComprobante: "01", serieNumero: "F001-1", fechaEmision: "2024-01-15", importeTotal: 100.00, moneda: "PEN", }, }],},firmar: false,validar_sunat: true,});
const { data, error } = await createRetention({ body: request });if (error) throw new Error(JSON.stringify(error));console.log(data.xml);curl -X POST http://localhost:8000/api/v1/retention/create \-H "Content-Type: application/json" \-d '{ "documento": { "serie": "R001", "numero": 1, "fechaEmision": "2024-01-15", "proveedor": { "ruc": "20100111111", "razonSocial": "Mi Empresa S.A.C." }, "cliente": { "nombre": "Juan Perez", "numeroDocumentoIdentidad": "12345678", "tipoDocumentoIdentidad": "1" }, "importeTotalRetenido": 3.00, "importeTotalPagado": 97.00, "tipoRegimen": "01", "tipoRegimenPorcentaje": 3.00, "operaciones": [{ "numeroOperacion": 1, "fechaOperacion": "2024-01-15", "importeOperacion": 100.00, "comprobante": { "tipoComprobante": "01", "serieNumero": "F001-1", "fechaEmision": "2024-01-15", "importeTotal": 100.00, "moneda": "PEN" } }] }, "firmar": false, "validar_sunat": true}'