Factu API Documentación

Factura simple

Venta a una empresa. Exige un comprador con RUC.

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": "FACTURA",
  "serie": "F001",
  "referencia_externa": "venta-3104",
  "cliente": {
    "tipo_documento": "RUC",
    "numero_documento": "20123456789",
    "nombre": "Distribuidora Lima SAC",
    "direccion": "Av. Republica de Panama 3055"
  },
  "items": [
    {
      "descripcion": "Consultoria",
      "cantidad": "1",
      "valor_unitario": "1500.00",
      "unidad": "SERVICIO"
    }
  ]
}'
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": "FACTURA",
    "serie": "F001",
    "referencia_externa": "venta-3104",
    "cliente": {
      "tipo_documento": "RUC",
      "numero_documento": "20123456789",
      "nombre": "Distribuidora Lima SAC",
      "direccion": "Av. Republica de Panama 3055"
    },
    "items": [
      {
        "descripcion": "Consultoria",
        "cantidad": "1",
        "valor_unitario": "1500.00",
        "unidad": "SERVICIO"
      }
    ]
  }),
});

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": "FACTURA",
        "serie": "F001",
        "referencia_externa": "venta-3104",
        "cliente": {
            "tipo_documento": "RUC",
            "numero_documento": "20123456789",
            "nombre": "Distribuidora Lima SAC",
            "direccion": "Av. Republica de Panama 3055",
        },
        "items": [
            {
                "descripcion": "Consultoria",
                "cantidad": "1",
                "valor_unitario": "1500.00",
                "unidad": "SERVICIO",
            },
        ],
    },
)

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
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
cliente.numero_documentotextoSí8 dígitos si es DNI, 11 si es RUC. No se manda con SIN_DOCUMENTO
cliente.nombretextoSíNombre o razón social. Obligatorio cuando el comprador tiene documento
cliente.direcciontextoNoDirección del comprador. Opcional: si no la mandas, el comprobante la declara con un guion
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
total_esperadodecimalNoDígito de control opcional: lo que tu caja dice que suma. Si no coincide con lo calculado, se rechaza con 422 y no se emite nada
fecha_emisionfechaNoPor defecto, hoy en hora de Perú. Se admite hasta 5 días atrás en una boleta y 3 en una factura; una fecha más vieja responde 422

Respuestas

{
  "id": "FACTURA-F001-5",
  "emisor": "TU_RUC",
  "ambiente": "dev",
  "tipo": "FACTURA",
  "serie": "F001",
  "numero": 5,
  "estado": "ACEPTADO",
  "mensaje": "El documento fue enviado correctamente y aceptado por SUNAT.",
  "total": "1770.00",
  "referencia_externa": "venta-3104",
  "pdf_factuapi_a4_url": "https://cpe-dev.facturamovilai.me/v1/pdf/<token>",
  "desglose": {
    "gravado": "1500.00",
    "exonerado": "0.00",
    "inafecto": "0.00",
    "igv": "270.00",
    "total": "1770.00",
    "items": [
      {
        "descripcion": "Consultoria",
        "valor_unitario": "1500.00",
        "igv": "270.00",
        "total": "1770.00"
      }
    ]
  }
}

El mismo pedido con "tipo_documento": "SIN_DOCUMENTO"

{
  "error": "DatosInvalidos",
  "mensaje": "Una factura y sus notas de credito requieren un cliente con RUC"
}

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"
}

Repetir venta-3101 con otros productos

{
  "error": "ReferenciaReutilizada",
  "mensaje": "La referencia 'venta-3101' ya se uso para un comprobante con otros datos"
}
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.