📚 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
- 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). - Probá en beta: tu cuenta arranca en el ambiente de homologación de SUNAT — emisiones reales de punta a punta pero sin validez tributaria.
- Emití tu primer comprobante (abajo el ejemplo) o usá el portal web sin escribir código.
- 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)
}- El correlativo lo asigna el servicio de forma atómica — no lo mandes; evita duplicados y saltos ante reintentos.
- Facturas (01): el cliente debe ser RUC (tipoDoc 6). La forma de pago Contado se informa automáticamente; para crédito con cuotas mandá
formaPago. - Campos opcionales:
fechaEmision(ISO),totalExoneradas,totalInafectas,serviceCharge(recargo al consumo).
📝 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:
| Documento | Mecanismo | Qué 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
| Endpoint | Devuelve |
|---|---|
GET /me | Datos de tu cuenta emisora (RUC, ambiente, total emitido). |
GET /comprobantes | Tus comprobantes (número, cliente, importe, estado, fecha) — últimos 200. |
GET /comprobantes/:id | Detalle completo: líneas, montos, hash, historial de eventos SUNAT (con tickets de anulación). |
GET /comprobantes/:id/download?type=pdf | Representación impresa A4 con código QR oficial SUNAT. |
GET /comprobantes/:id/download?type=xml | XML UBL 2.1 firmado (el documento legal). |
GET /comprobantes/:id/download?type=cdr | Constancia de recepción de SUNAT (zip). |
GET /stats | Métricas: totales, montos facturados, por tipo/estado/día, actividad reciente. |
📋 Catálogos SUNAT
Tipos de comprobante (catálogo 01)
| Código | Documento | Serie sugerida |
|---|---|---|
| 01 | Factura | F001 |
| 03 | Boleta de venta | B001 |
| 07 | Nota de crédito | FC01 (de factura) / BC01 (de boleta) |
| 08 | Nota de débito | FD01 / BD01 |
Documento de identidad del cliente (catálogo 06)
| Código | Documento |
|---|---|
| 0 | Sin documento (venta menor a S/ 700) |
| 1 | DNI |
| 4 | Carnet de extranjería |
| 6 | RUC (obligatorio en facturas) |
| 7 | Pasaporte |
Motivos de nota de crédito (catálogo 09)
| Código | Motivo |
|---|---|
| 01 | Anulación de la operación |
| 02 | Anulación por error en el RUC |
| 03 | Corrección por error en la descripción |
| 06 | Devolución total |
| 07 | Devolución por ítem |
| 09 | Disminución en el valor |
Motivos de nota de débito (catálogo 10)
| Código | Motivo |
|---|---|
| 01 | Intereses por mora |
| 02 | Aumento en el valor |
| 03 | Penalidades / otros conceptos |
🚦 Estados del comprobante
| Estado | Significado |
|---|---|
| aceptado | SUNAT emitió CDR de conformidad. El comprobante es válido. |
| observado | Aceptado con observaciones — revisá el detalle, puede requerir corrección futura. |
| rechazado | SUNAT lo rechazó. NO tiene validez: corregí el dato y emití de nuevo (el número no se reutiliza). |
| anulando | Anulación enviada; el ticket de SUNAT aún está en proceso. |
| anulado | Baja (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:
| Evento | Cuándo |
|---|---|
comprobante.emitido | Al emitir (aceptado, observado o rechazado). |
comprobante.anulado | Al 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ón | Causa y solución |
|---|---|
| HTTP 401 | API key inválida, incompleta o desactivada. Verificá el header Authorization. |
| Rechazo 2800/2801 | Documento del cliente inválido (DNI de 8 dígitos, RUC de 11). En facturas el cliente debe ser RUC. |
| Rechazo por montos | La suma de líneas no cuadra con los totales: totalGravadas = Σ valorVenta; importeTotal = totalGravadas + totalIgv. Redondeá a 2 decimales. |
| Serie inválida | Boletas empiezan con B, facturas con F, NC con BC/FC, ND con BD/FD (4 caracteres). |
| "en proceso" al anular | SUNAT no resolvió el ticket dentro del request. El comprobante queda "anulando" — reconsultá el detalle más tarde. |
| Nota sin ref | Las notas (07/08) requieren ref {tipoDoc, serie, correlativo} del documento afectado + motivoCodigo. |
🌐 Ambientes
| Ambiente | Para qué | Validez |
|---|---|---|
| beta (homologación) | Desarrollo y pruebas de integración contra el SUNAT beta real. | Sin validez tributaria. |
| producción | Operació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.