Comunicación de Baja
La Comunicación de Baja (tipo RA) informa a SUNAT la anulación de facturas o boletas antes de que sean declaradas. Solo aplica para comprobantes que aún no han sido comunicados en un resumen diario.
Campos requeridos
Sección titulada «Campos requeridos»| Campo | Tipo | Descripción | Validación |
|---|---|---|---|
numero | integer | Correlativo del documento de baja | Ej: 1 genera RA-YYYYMMDD-001. Mayor a 0. |
fechaEmisionComprobantes | date | Fecha de emisión de los comprobantes que se dan de baja | YYYY-MM-DD. |
proveedor | Proveedor | Datos del emisor | ruc de 11 dígitos y razonSocial obligatorios. |
comprobantes | VoidedDocumentsItem[] | Lista de comprobantes a dar de baja | Al menos un ítem. |
Campos opcionales
Sección titulada «Campos opcionales»| Campo | Tipo | Default | Descripción |
|---|---|---|---|
fechaEmision | date | hoy | Fecha de emisión del documento de baja. ContentEnricher la asigna automáticamente si no se indica. |
Ítem de baja (VoidedDocumentsItem)
Sección titulada «Ítem de baja (VoidedDocumentsItem)»| Campo | Tipo | Descripción | Validación |
|---|---|---|---|
serie | string | Serie del comprobante | Ej: F001, B001. |
numero | integer | Número del comprobante | Mayor a 0. |
tipoComprobante | string | Tipo de comprobante | Catálogo N.° 01: 01 Factura, 03 Boleta. |
descripcionSustento | string | Motivo de la baja | Texto libre. |
Reglas SUNAT aplicables
Sección titulada «Reglas SUNAT aplicables»| Código / Regla | Descripción |
|---|---|
2074 (Voided) | UBLVersionID debe ser 2.0. |
2072 (Voided) | CustomizationID debe ser 1.0. |
| Identificador | RA-YYYYMMDD-NNNN. |
| Plazo | Se debe enviar dentro de los 7 días calendario siguientes a la fecha de emisión del comprobante. |
| Restricción | No se puede dar de baja un comprobante ya incluido en un Resumen Diario aceptado. |
| Tipos permitidos | 01 Factura y 03 Boleta. |
Ejemplo completo
Sección titulada «Ejemplo completo»from openubl.models import ( VoidedDocuments, VoidedDocumentsItem, Proveedor,)from openubl.renderer import render_voided_documentsfrom openubl.validator import SunatValidatorfrom datetime import date
voided = VoidedDocuments( numero=1, fechaEmisionComprobantes=date(2025, 6, 10), proveedor=Proveedor( ruc="20100100100", razonSocial="Mi Empresa S.A.C.", ), comprobantes=[ VoidedDocumentsItem( serie="F001", numero=45, tipoComprobante="01", descripcionSustento="Error en datos del cliente", ), ],)
xml = render_voided_documents(voided)errors = SunatValidator().validate_voided_documents(xml)assert errors == []print(xml)import { createVoidedDocuments } from "@openubl/sdk";import { zVoidedDocuments } from "@openubl/sdk/zod.gen";
const voided = zVoidedDocuments.parse({ numero: 1, fechaEmisionComprobantes: "2025-06-10", proveedor: { ruc: "20100100100", razonSocial: "Mi Empresa S.A.C.", }, comprobantes: [ { serie: "F001", numero: 45, tipoComprobante: "01", descripcionSustento: "Error en datos del cliente", }, ],});
const { data, error } = await createVoidedDocuments({ query: { validate: true }, body: voided });
if (error) { throw new Error(JSON.stringify(error));}
console.log(data.xml);curl -X POST "http://localhost:8000/api/v1/voided-documents/create?validate=true" \ -H "Content-Type: application/json" \ -d '{ "numero": 1, "fechaEmisionComprobantes": "2025-06-10", "proveedor": { "ruc": "20100100100", "razonSocial": "Mi Empresa S.A.C." }, "comprobantes": [{ "serie": "F001", "numero": 45, "tipoComprobante": "01", "descripcionSustento": "Error en datos del cliente" }] }'Ejemplo con ContentEnricher
Sección titulada «Ejemplo con ContentEnricher»from openubl.enricher import ContentEnricherfrom openubl.models import VoidedDocuments, VoidedDocumentsItem, Proveedorfrom openubl.renderer import render_voided_documentsfrom openubl.validator import SunatValidatorfrom datetime import date
voided = VoidedDocuments( numero=1, fechaEmisionComprobantes=date(2025, 6, 10), proveedor=Proveedor( ruc="20100100100", razonSocial="Mi Empresa S.A.C.", ), comprobantes=[ VoidedDocumentsItem( serie="F001", numero=45, tipoComprobante="01", descripcionSustento="Error en datos del cliente", ), ],)
ContentEnricher().enrich(voided) # Asigna fechaEmision si faltaxml = render_voided_documents(voided)errors = SunatValidator().validate_voided_documents(xml)assert errors == [], errorsprint(xml)import { createVoidedDocuments } from "@openubl/sdk";import { zVoidedDocuments } from "@openubl/sdk/zod.gen";
const voided = zVoidedDocuments.parse({ numero: 1, fechaEmisionComprobantes: "2025-06-10", proveedor: { ruc: "20100100100", razonSocial: "Mi Empresa S.A.C." }, comprobantes: [ { serie: "F001", numero: 45, tipoComprobante: "01", descripcionSustento: "Error en datos del cliente", }, ],});
const { data, error } = await createVoidedDocuments({ body: voided });
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 '{ "numero": 1, "fechaEmisionComprobantes": "2025-06-10", "proveedor": { "ruc": "20100100100", "razonSocial": "Mi Empresa S.A.C." }, "comprobantes": [{ "serie": "F001", "numero": 45, "tipoComprobante": "01", "descripcionSustento": "Error en datos del cliente" }] }'Endpoint
Sección titulada «Endpoint»from openubl.models import ( VoidedDocuments, VoidedDocumentsItem, Proveedor,)from openubl.renderer import render_voided_documentsfrom datetime import date
voided = VoidedDocuments( numero=1, fechaEmisionComprobantes=date(2025, 6, 10), proveedor=Proveedor( ruc="20100100100", razonSocial="Mi Empresa S.A.C.", ), comprobantes=[ VoidedDocumentsItem( serie="F001", numero=45, tipoComprobante="01", descripcionSustento="Error en datos del cliente", ), ],)
xml = render_voided_documents(voided)print(xml)import { createVoidedDocuments } from "@openubl/sdk";import { zVoidedDocuments } from "@openubl/sdk/zod.gen";
const voided = zVoidedDocuments.parse({ numero: 1, fechaEmisionComprobantes: "2025-06-10", proveedor: { ruc: "20100100100", razonSocial: "Mi Empresa S.A.C.", }, comprobantes: [ { serie: "F001", numero: 45, tipoComprobante: "01", descripcionSustento: "Error en datos del cliente", }, ],});
const { data, error } = await createVoidedDocuments({ body: voided });
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 '{ "numero": 1, "fechaEmisionComprobantes": "2025-06-10", "proveedor": { "ruc": "20100100100", "razonSocial": "Mi Empresa S.A.C." }, "comprobantes": [{ "serie": "F001", "numero": 45, "tipoComprobante": "01", "descripcionSustento": "Error en datos del cliente" }] }'Casos especiales
Sección titulada «Casos especiales»Baja de múltiples comprobantes
Sección titulada «Baja de múltiples comprobantes»Una misma comunicación de baja puede anular varios comprobantes emitidos el mismo día.
from openubl.models import ( VoidedDocuments, VoidedDocumentsItem, Proveedor,)from openubl.renderer import render_voided_documentsfrom openubl.validator import SunatValidatorfrom datetime import date
voided = VoidedDocuments( numero=2, fechaEmisionComprobantes=date(2025, 6, 10), proveedor=Proveedor(ruc="20100100100", razonSocial="Mi Empresa S.A.C."), comprobantes=[ VoidedDocumentsItem( serie="F001", numero=10, tipoComprobante="01", descripcionSustento="Error en datos del cliente", ), VoidedDocumentsItem( serie="B001", numero=20, tipoComprobante="03", descripcionSustento="Duplicidad de emisión", ), ],)
xml = render_voided_documents(voided)errors = SunatValidator().validate_voided_documents(xml)assert errors == [], errorsprint(xml)import { createVoidedDocuments } from "@openubl/sdk";import { zVoidedDocuments } from "@openubl/sdk/zod.gen";
const voided = zVoidedDocuments.parse({ numero: 2, fechaEmisionComprobantes: "2025-06-10", proveedor: { ruc: "20100100100", razonSocial: "Mi Empresa S.A.C." }, comprobantes: [ { serie: "F001", numero: 10, tipoComprobante: "01", descripcionSustento: "Error en datos del cliente", }, { serie: "B001", numero: 20, tipoComprobante: "03", descripcionSustento: "Duplicidad de emisión", }, ],});
const { data, error } = await createVoidedDocuments({ body: voided });
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 '{ "numero": 2, "fechaEmisionComprobantes": "2025-06-10", "proveedor": { "ruc": "20100100100", "razonSocial": "Mi Empresa S.A.C." }, "comprobantes": [ { "serie": "F001", "numero": 10, "tipoComprobante": "01", "descripcionSustento": "Error en datos del cliente" }, { "serie": "B001", "numero": 20, "tipoComprobante": "03", "descripcionSustento": "Duplicidad de emisión" } ] }'Respuesta esperada
Sección titulada «Respuesta esperada»{ "xml": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>..."}Si validate=true y el cuerpo no cumple las reglas, la API devuelve un error 422 con el detalle de la validación.