← Inicio

📚 Documentación de la API

Facturación electrónica SUNAT (SEE — Del Contribuyente) como servicio. Emisión de boletas, facturas y notas con firma digital XML-DSig, envío directo a SUNAT y CDR, en una API REST. Base URL: https://factura.loyfixds.com/api/v1.

🚀 Inicio rápido

  1. Alta del emisor: el administrador registra tu RUC con tu certificado digital (.pfx) y usuario secundario SOL, y te entrega tu API key (fk_…, se muestra una sola vez).
  2. Probá en beta: tu cuenta arranca en el ambiente de homologación de SUNAT — emisiones reales de punta a punta pero sin validez tributaria.
  3. Emití tu primer comprobante (abajo el ejemplo) o usá el portal web sin escribir código.
  4. Pasá a producción: cuando tu integración esté lista, el administrador cambia tu ambiente y tus comprobantes pasan a tener validez legal.

🔑 Autenticación

Todas las llamadas llevan tu API key en el header Authorization:

Authorization: Bearer fk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

La key identifica a tu empresa (RUC emisor): no necesitás mandar tu RUC ni certificados en cada request — el servicio custodia tu certificado cifrado (AES-256-GCM) y firma por vos. Verificá tu cuenta con GET /api/v1/me.

🧾 Emitir boleta o factura

POST /api/v1/comprobantes — el envío a SUNAT es inmediato; la respuesta incluye el CDR.

curl -X POST https://factura.loyfixds.com/api/v1/comprobantes \
  -H "Authorization: Bearer TU_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "tipoDoc": "03",              // 03=boleta, 01=factura
    "serie": "B001",              // B*** para boletas, F*** para facturas
    "moneda": "PEN",
    "cliente": {
      "tipoDoc": "1",             // 1=DNI, 6=RUC (obligatorio en facturas), 0=sin doc
      "numDoc": "12345678",
      "nombre": "JUAN PEREZ"
    },
    "lineas": [{
      "descripcion": "Producto de ejemplo",
      "cantidad": 1,
      "valorUnitario": 8.47,      // precio SIN IGV
      "precioUnitario": 10.00,    // precio CON IGV
      "valorVenta": 8.47,         // valorUnitario × cantidad
      "igv": 1.53,
      "tasaIgv": 18,
      "afectacion": "gravado"
    }],
    "totalGravadas": 8.47,
    "totalIgv": 1.53,
    "totalDescuentos": 0,
    "importeTotal": 10.00
  }'

Respuesta:

{
  "fullNumber": "B001-00000005",
  "correlativo": 5,               // lo asigna el servicio (correlativo transaccional)
  "estado": "aceptado",
  "hash": "2cd5a302c6c7…",        // resumen del XML firmado
  "observaciones": ["La Boleta numero B001-00000005, ha sido aceptada"],
  "cdrBase64": "UEsDBBQ…"         // constancia de recepción de SUNAT (zip)
}

📝 Notas de crédito (07) y débito (08)

Mismo endpoint, agregando el documento afectado y el motivo:

{
  "tipoDoc": "07",                       // 07=NC, 08=ND
  "serie": "BC01",                       // BC/FC para NC, BD/FD para ND
  "motivoCodigo": "01",                  // catálogo 09 (NC) o 10 (ND) — ver abajo
  "motivoDescripcion": "Anulación de la operación",
  "ref": { "tipoDoc": "03", "serie": "B001", "correlativo": 4 },
  "cliente": { … }, "lineas": [ … ],     // igual que una emisión normal
  "totalGravadas": …, "totalIgv": …, "importeTotal": …
}

🗑 Anular comprobantes

POST /api/v1/comprobantes/:id/baja con { "motivo": "…" }. El servicio elige el mecanismo correcto según SUNAT:

DocumentoMecanismoQué pasa
Factura (01)Comunicación de baja (RA)Se envía por ticket; en segundos SUNAT confirma y el comprobante queda "anulado".
Boleta (03)Resumen diario (RC, condición 3)Mismo flujo por ticket; la boleta queda "anulada".
NC / ND— (no se anulan)Se corrigen emitiendo otra nota.

Si SUNAT demora el ticket, el comprobante queda en estado anulando y la respuesta trae el ticket para seguimiento. Los anulados dejan de sumar a tu facturación.

🔍 Consultas y descargas

EndpointDevuelve
GET /meDatos de tu cuenta emisora (RUC, ambiente, total emitido).
GET /comprobantesTus comprobantes (número, cliente, importe, estado, fecha) — últimos 200.
GET /comprobantes/:idDetalle completo: líneas, montos, hash, historial de eventos SUNAT (con tickets de anulación).
GET /comprobantes/:id/download?type=pdfRepresentación impresa A4 con código QR oficial SUNAT.
GET /comprobantes/:id/download?type=xmlXML UBL 2.1 firmado (el documento legal).
GET /comprobantes/:id/download?type=cdrConstancia de recepción de SUNAT (zip).
GET /statsMétricas: totales, montos facturados, por tipo/estado/día, actividad reciente.

📋 Catálogos SUNAT

Tipos de comprobante (catálogo 01)

CódigoDocumentoSerie sugerida
01FacturaF001
03Boleta de ventaB001
07Nota de créditoFC01 (de factura) / BC01 (de boleta)
08Nota de débitoFD01 / BD01

Documento de identidad del cliente (catálogo 06)

CódigoDocumento
0Sin documento (venta menor a S/ 700)
1DNI
4Carnet de extranjería
6RUC (obligatorio en facturas)
7Pasaporte

Motivos de nota de crédito (catálogo 09)

CódigoMotivo
01Anulación de la operación
02Anulación por error en el RUC
03Corrección por error en la descripción
06Devolución total
07Devolución por ítem
09Disminución en el valor

Motivos de nota de débito (catálogo 10)

CódigoMotivo
01Intereses por mora
02Aumento en el valor
03Penalidades / otros conceptos

🚦 Estados del comprobante

EstadoSignificado
aceptadoSUNAT emitió CDR de conformidad. El comprobante es válido.
observadoAceptado con observaciones — revisá el detalle, puede requerir corrección futura.
rechazadoSUNAT lo rechazó. NO tiene validez: corregí el dato y emití de nuevo (el número no se reutiliza).
anulandoAnulación enviada; el ticket de SUNAT aún está en proceso.
anuladoBaja (RA) o anulación por resumen (RC) aceptada por SUNAT.

🔔 Webhooks

Configurá una URL (PUT /api/v1/me/webhook o desde el portal → 🔌 API) y te notificamos cada evento con un POST JSON:

EventoCuándo
comprobante.emitidoAl emitir (aceptado, observado o rechazado).
comprobante.anuladoAl resolverse una anulación (RA/RC), incluso si el ticket demoró.
POST https://tu-sistema.com/webhooks/facturacion
X-Fact-Event: comprobante.emitido
X-Fact-Signature: sha256=3f5a8c…        // HMAC-SHA256(secret, body)

{
  "event": "comprobante.emitido",
  "timestamp": "2026-07-06T21:15:00.000Z",
  "data": {
    "tipoDoc": "03",
    "fullNumber": "B001-00000006",
    "estado": "aceptado",
    "importeTotal": 10,
    "moneda": "PEN",
    "cliente": { "tipoDoc": "1", "numDoc": "12345678", "nombre": "JUAN PEREZ" },
    "hash": "2cd5a302…",
    "observaciones": ["La Boleta numero B001-00000006, ha sido aceptada"]
  }
}

Verificá la firma: calculá HMAC-SHA256(secret, body_crudo) y comparalo con X-Fact-Signature (tras el prefijo sha256=). El secret se te entrega una sola vez al configurar la URL. Reintentamos una vez si tu endpoint falla; respondé 2xx rápido y procesá async. Para probar sin endpoint propio: /api/v1/webhook-test.

⚠️ Errores comunes

SituaciónCausa y solución
HTTP 401API key inválida, incompleta o desactivada. Verificá el header Authorization.
Rechazo 2800/2801Documento del cliente inválido (DNI de 8 dígitos, RUC de 11). En facturas el cliente debe ser RUC.
Rechazo por montosLa suma de líneas no cuadra con los totales: totalGravadas = Σ valorVenta; importeTotal = totalGravadas + totalIgv. Redondeá a 2 decimales.
Serie inválidaBoletas empiezan con B, facturas con F, NC con BC/FC, ND con BD/FD (4 caracteres).
"en proceso" al anularSUNAT no resolvió el ticket dentro del request. El comprobante queda "anulando" — reconsultá el detalle más tarde.
Nota sin refLas notas (07/08) requieren ref {tipoDoc, serie, correlativo} del documento afectado + motivoCodigo.

🌐 Ambientes

AmbientePara quéValidez
beta (homologación)Desarrollo y pruebas de integración contra el SUNAT beta real.Sin validez tributaria.
producciónOperación real con tu certificado digital vigente.Validez legal plena.

El cambio de ambiente lo gestiona el administrador del servicio (requiere tu certificado de producción). La API y tus series no cambian.