Factu API Documentación

Anulación de la operación

Anula o corrige un comprobante ya emitido sin borrarlo: emite otro documento que lo revierte. Es la vía cuando ya pasó el plazo de la baja: 3 días en una factura, 5 en una boleta.

POSThttps://cpe-dev.facturamovilai.me/v1/emisores/TU_RUC/comprobantes

Cabecera Authorization: Bearer TU_LLAVE. Es la misma llave en pruebas y en producción: lo que cambia es la dirección (cpe-dev o cpe-prod).

Solicitud

curl -X POST "https://cpe-dev.facturamovilai.me/v1/emisores/TU_RUC/comprobantes" \
  -H "Authorization: Bearer TU_LLAVE" \
  -H "Content-Type: application/json" \
  -d '{
  "tipo": "NOTA_CREDITO",
  "serie": "B001",
  "referencia_externa": "anulacion-3101",
  "precios_incluyen_igv": true,
  "nota_credito": {
    "motivo": "ANULACION_DE_LA_OPERACION",
    "sustento": "El cliente devolvio el producto",
    "documento_afectado": {
      "tipo": "BOLETA",
      "serie": "B001",
      "numero": 36
    }
  },
  "cliente": {
    "tipo_documento": "SIN_DOCUMENTO"
  },
  "items": [
    {
      "descripcion": "Fideos",
      "cantidad": "3",
      "valor_unitario": "3.50"
    }
  ]
}'
const respuesta = await fetch("https://cpe-dev.facturamovilai.me/v1/emisores/TU_RUC/comprobantes", {
  method: "POST",
  headers: {
    "Authorization": "Bearer TU_LLAVE",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "tipo": "NOTA_CREDITO",
    "serie": "B001",
    "referencia_externa": "anulacion-3101",
    "precios_incluyen_igv": true,
    "nota_credito": {
      "motivo": "ANULACION_DE_LA_OPERACION",
      "sustento": "El cliente devolvio el producto",
      "documento_afectado": {
        "tipo": "BOLETA",
        "serie": "B001",
        "numero": 36
      }
    },
    "cliente": {
      "tipo_documento": "SIN_DOCUMENTO"
    },
    "items": [
      {
        "descripcion": "Fideos",
        "cantidad": "3",
        "valor_unitario": "3.50"
      }
    ]
  }),
});

console.log(respuesta.status, await respuesta.json());
# pip install requests
import requests

respuesta = requests.post(
    "https://cpe-dev.facturamovilai.me/v1/emisores/TU_RUC/comprobantes",
    headers={"Authorization": "Bearer TU_LLAVE"},
    json={
        "tipo": "NOTA_CREDITO",
        "serie": "B001",
        "referencia_externa": "anulacion-3101",
        "precios_incluyen_igv": True,
        "nota_credito": {
            "motivo": "ANULACION_DE_LA_OPERACION",
            "sustento": "El cliente devolvio el producto",
            "documento_afectado": {
                "tipo": "BOLETA",
                "serie": "B001",
                "numero": 36,
            },
        },
        "cliente": {
            "tipo_documento": "SIN_DOCUMENTO",
        },
        "items": [
            {
                "descripcion": "Fideos",
                "cantidad": "3",
                "valor_unitario": "3.50",
            },
        ],
    },
)

print(respuesta.status_code, respuesta.json())

Campos

CampoTipoObligatorioDescripción
tipoopciónSíBOLETA, FACTURA o NOTA_CREDITO. Es lo único que cambia entre los tres casos
Valores: FACTURA · BOLETA · NOTA_CREDITO
serietextoSíCuatro caracteres: una boleta empieza con B (B001) y una factura con F (F001). En una nota de crédito es la serie del documento que anula, no una propia
nota_credito.motivoopciónSíPor qué se emite (catálogo 09 de SUNAT)
Valores: ANULACION_DE_LA_OPERACION · ANULACION_POR_ERROR_EN_EL_RUC · CORRECCION_POR_ERROR_EN_LA_DESCRIPCION · DESCUENTO_GLOBAL · DESCUENTO_POR_ITEM · DEVOLUCION_TOTAL · DEVOLUCION_POR_ITEM
nota_credito.sustentotextoSíExplicación libre del motivo, por ejemplo «El cliente devolvió el producto»
nota_credito.documento_afectado.tipoopciónSíTipo del comprobante que se anula o corrige: BOLETA o FACTURA
Valores: FACTURA · BOLETA · NOTA_CREDITO
nota_credito.documento_afectado.serietextoSíSerie del comprobante original, por ejemplo B001
nota_credito.documento_afectado.numeroenteroSíNúmero del comprobante original, sin ceros a la izquierda: 6, no 000006
cliente.tipo_documentoopciónSíCómo se identifica el comprador: DNI, RUC o SIN_DOCUMENTO. SIN_DOCUMENTO solo vale en una boleta de hasta S/ 700; una factura exige RUC
Valores: RUC · DNI · SIN_DOCUMENTO
items[].descripciontextoSíNombre del producto o servicio, tal como debe verse en el comprobante
items[].cantidaddecimalSíCuántas unidades se venden, en la unidad indicada. Admite decimales (2.5 kg). Debe ser mayor que cero
items[].valor_unitariodecimalSíPrecio de una unidad. Con precios_incluyen_igv: true es el precio de vitrina, con IGV; con false, el valor neto. No puede ser negativo
items[].unidadopciónNoEn qué se vende esto (catálogo 03 de SUNAT). UNIDAD por defecto, que es vender de a una. Usa KILOGRAMO, LITRO, BOLSA, CAJA, DOCENA y demás cuando corresponda: va declarado en el comprobante, así que vender 2 kg de lentejas como 2 UNIDAD declara algo distinto de lo que vendiste. SERVICIO para lo que no es un bien
Lista completa: GET /v1/unidades
Por defecto: UNIDAD
items[].afectacionopciónNoQué dice la ley del IGV de este producto. GRAVADO (18%) por defecto. EXONERADO para lo que no paga IGV -menestras, arroz, verduras, libros- e INAFECTO para exportaciones. Una bodega puede vender los dos en la misma boleta. Si lo marcas mal, el total igual cuadra pero declaras IGV que no debes
Valores: GRAVADO · EXONERADO · INAFECTO
Por defecto: GRAVADO
referencia_externatextoNoEl id de esta venta en TU sistema. Mándalo siempre: es lo único que evita emitir dos comprobantes si reintentas. Repetirlo con los mismos datos devuelve el comprobante ya emitido; repetirlo con datos distintos responde 409
precios_incluyen_igvbooleanoNotrue si mandas precios de vitrina -lo que cobra la caja- y nosotros quitamos el IGV con 6 decimales. false si mandas valores netos. Un item EXONERADO no se convierte: no hay IGV que quitarle
Por defecto: false

Respuestas

{
  "id": "NOTA_CREDITO-B001-3",
  "emisor": "TU_RUC",
  "ambiente": "dev",
  "tipo": "NOTA_CREDITO",
  "serie": "B001",
  "numero": 3,
  "estado": "ACEPTADO",
  "mensaje": "El documento fue enviado correctamente y aceptado por SUNAT.",
  "total": "10.50",
  "referencia_externa": "anulacion-3101",
  "pdf_factuapi_a4_url": "https://cpe-dev.facturamovilai.me/v1/pdf/<token>",
  "desglose": {
    "gravado": "8.90",
    "exonerado": "0.00",
    "inafecto": "0.00",
    "igv": "1.60",
    "total": "10.50",
    "items": [
      {
        "descripcion": "Fideos",
        "valor_unitario": "2.966102",
        "igv": "1.60",
        "total": "10.50"
      }
    ]
  }
}

El mismo pedido sin el campo nota_credito

{
  "error": "DatosInvalidos",
  "mensaje": "Una nota de credito debe indicar motivo y documento afectado"
}

Con una llave que no existe

{
  "detail": "Credencial invalida"
}

Con un RUC que no es de tu cuenta

{
  "error": "EmisorNoAutorizado",
  "mensaje": "El emisor 20999999999 no pertenece a esta cuenta"
}
estado Significa
ACEPTADO el comprobante existe ante SUNAT
RECHAZADO SUNAT lo procesó y lo rechazó. Llega con 201, no con un error: lee mensaje
PENDIENTE SUNAT sigue procesando. Consúltalo más tarde

La respuesta puede traer campos adicionales a los que ves aquí: usa los de estos ejemplos.

La serie es la del documento que anula (B001 para una boleta), no una propia. Aun así, cada tipo lleva su propio correlativo, como exige SUNAT: el número de la nota de crédito no tiene relación con el de la boleta que anula.