Desarrolladores
API de facturación electrónica (SUNAT)
Tu sistema manda la venta y nosotros la numeramos, la firmamos con tu certificado digital y la enviamos a SUNAT con tu RUC. Recibes la respuesta de SUNAT (la constancia o CDR) en la misma llamada.
Cómo empezar
- Con tu cuenta y el servicio de facturación activo, entra a Fiscal → Configuración y completa los 4 pasos: datos de tu empresa, usuario SOL y certificado, numeración y paso a Producción (cada paso tiene su tutorial).
- En Fiscal → API toca Nueva llave y guárdala: se muestra una sola vez.
- Prueba en modo de pruebas: los comprobantes van al ambiente de pruebas de SUNAT, sin valor tributario y sin costo.
- Cuando todo esté en verde, pasa a Producción desde Configuración. Desde ahí cada comprobante vale ante SUNAT.
Autenticación
Base de la API: https://mercurius33.app/api/fiscal/v1. Manda tu llave en cada pedido y una clave de idempotencia en cada POST:
| Authorization | Bearer fk_… (también vale el encabezado X-Api-Key). |
| Idempotency-Key | Obligatoria en cada POST, hasta 240 caracteres (por ejemplo el número de tu venta). Repetir el pedido con la misma clave devuelve el mismo comprobante: no se numera ni se cobra dos veces. Usar la misma clave con otros datos responde 409. |
| X-Correlation-Id | Opcional: un identificador tuyo para rastrear el pedido; vuelve como requestId. |
Emitir una boleta o factura
POST /documents
| documentType | "03" boleta · "01" factura. |
| issueDate | Fecha de emisión, AAAA-MM-DD. |
| customer.documentType | Catálogo 06 de SUNAT: "6" RUC (obligatorio en factura), "1" DNI, "4" carné de extranjería, "7" pasaporte. Boleta sin datos del cliente: "1", número "00000000" y nombre "Cliente varios". Si la boleta pasa de S/ 700, SUNAT pide el documento del cliente. |
| customer.documentNumber | Número del documento del cliente. |
| customer.legalName | Nombre o razón social. |
| items[].description | Lo que se vende. |
| items[].quantity | Cantidad (mayor que 0). |
| items[].unitPrice | Precio unitario con IGV. El IGV y la base se calculan solos. |
| items[].unitCode | Unidad de medida de SUNAT: "NIU" unidades, "ZZ" servicios. |
| items[].taxAffectationCode | "10" (gravado con IGV). Por ahora es el único que se emite. |
| send | Opcional. true = además de numerar, firma y envía a SUNAT en la misma llamada. |
curl -X POST https://mercurius33.app/api/fiscal/v1/documents \
-H "Authorization: Bearer fk_TU_LLAVE" \
-H "Idempotency-Key: venta-000123" \
-H "Content-Type: application/json" \
-d '{
"documentType": "01",
"issueDate": "2026-10-10",
"customer": { "documentType": "6", "documentNumber": "20123456789", "legalName": "CLIENTE S.A.C." },
"items": [{ "description": "Menú ejecutivo", "quantity": 2, "unitPrice": 23.6, "unitCode": "NIU", "taxAffectationCode": "10" }],
"send": true
}'Respuesta 201:
{
"ok": true,
"requestId": "…",
"reused": false,
"mode": "PRODUCTION",
"document": { "id": "cm…", "formattedNumber": "F001-00000124", "status": "NUMBER_ASSIGNED",
"taxableAmount": "40", "igvAmount": "7.2", "totalAmount": "47.2", … },
"sunat": {
"status": "ACCEPTED",
"accepted": true,
"cdr": { "code": "0", "description": "La Factura numero F001-00000124, ha sido aceptada", "notes": [] },
"error": null,
"numberTaken": false
}
}Los montos llegan como texto (por ejemplo "47.2"). Guarda document.id. Si el envío falla (SUNAT no responde), el comprobante igual queda numerado: vuelve a enviarlo con la ruta de abajo. Si numberTaken es true, otro sistema ya usó ese número: la serie queda en pausa hasta corregir la numeración en Fiscal → Configuración.
Enviar a SUNAT
POST /documents/{id}/send — firma (si hace falta) y envía una boleta o factura ya numerada. Responde 200 si SUNAT la aceptó y 422 si no, con el mismo bloque sunat. Necesita su propia Idempotency-Key.
Consultar
| GET /documents | Tus comprobantes, con número, cliente, totales y estado. Filtros opcionales: search, type (INVOICE, RECEIPT) y status. |
| GET /documents/{id}/xml | El XML firmado del comprobante. |
| GET /documents/{id}/lifecycle | Su estado y su historial de eventos. |
Errores
Los errores llegan como { "ok": false, "error": { "code": "…", "message": "…" } }.
| 401 API_KEY_INVALID | La llave no existe o fue revocada. |
| 400 IDEMPOTENCY_KEY_REQUIRED | Falta Idempotency-Key en un POST. |
| 400 DOCUMENT_VALIDATION_ERROR | Faltan datos o no son válidos (vienen los detalles). |
| 402 INSUFFICIENT_BALANCE | No hay saldo para emitir en Producción. |
| 409 IDEMPOTENCY_CONFLICT | La misma Idempotency-Key con otros datos. |
| 422 SERIES_NUMBERING_NOT_CONFIRMED… | La serie está en pausa: revisa la numeración en Configuración. |
| 422 DOCUMENT_NOT_ALLOWED_FOR_TAX_REGIME | Tu régimen no permite ese comprobante. |
| 422 TAX_AFFECTATION_NOT_SUPPORTED | Un ítem no es gravado (por ahora solo "10"). |
| 503 FISCAL_API_PRICE_NOT_CONFIGURED | La API todavía no está activa en Producción. |
Cobro
En modo de pruebas no se cobra. En Producción, cada comprobante emitido se descuenta de tu saldo prepago; el precio está en Fiscal → API. Un pedido repetido con la misma Idempotency-Key no se cobra dos veces, y enviar o reenviar a SUNAT no se cobra.