Documentacion API

Guia de integracion para emitir comprobantes electronicos con Zafra.

Como empezar a facturar

3 pasos para emitir tu primer comprobante electronico

Paso 1

Crea tu empresa

Registra tu RUC, razon social, datos fiscales y configura tus series (F001, B001, etc.)

Paso 2

Certificado digital o PSE

Sube tu archivo .pfx de SUNAT o selecciona un PSE (Proveedor de Servicios Electronicos) para firmar tus comprobantes

Paso 3

Envia comprobantes

Genera tu API Key, arma tu JSON y envia facturas, boletas, notas de credito y mas por API

Tu sistema envia JSON Zafra valida + XML + firma SUNAT

Autenticacion

Incluye tu API Key en cada solicitud:

Header
X-Api-Key: zfr_tu_api_key_aqui
Importante: Tu API Key es secreta. No la expongas en codigo frontend ni repositorios publicos.

Endpoints

Cada cliente tiene un entorno (Pruebas o Produccion) que puedes cambiar desde el detalle del cliente. Los endpoints cambian segun el entorno:

PRUEBAS

Base URL

https://api.zafra.io/v1

POST /invoices

POST /credit-notes

POST /debit-notes

POST /voided

Los comprobantes se envian al entorno Beta de SUNAT. No tienen validez tributaria.

PRODUCCION

Base URL

https://api.zafra.io/v1

POST /invoices

POST /credit-notes

POST /debit-notes

POST /voided

Los comprobantes se envian a SUNAT real. Tienen validez tributaria.

Mismos endpoints, diferente comportamiento. La URL del API es la misma para ambos entornos. El sistema rutea internamente a SUNAT Beta o Produccion segun la configuracion del cliente asociado al API Key.

SUNAT trabaja con 2 decimales

Todos los montos monetarios deben tener maximo 2 decimales. Ejemplo: 118.00, 18.50.

CampoFormatoDecimales
Montos (totales, IGV, total_item)n(12,2)Max 2
valor_unitario, precio_unitarion(12,10)Hasta 10
cantidadn(12,10)Hasta 10
porcentaje_igvn(3,5)Hasta 5

Si envias total_igv: 18.005 el servicio lo rechazara. Redondea a 2 decimales antes de enviar.

Portal del Consumidor

Tus clientes pueden consultar sus comprobantes

Zafra ofrece un Portal del Consumidor donde el receptor del comprobante (tu cliente final) puede ingresar con su numero de telefono, verificarse via SMS y ver todos sus comprobantes. Sin necesidad de integraciones adicionales como WhatsApp o email.

Como funciona:

  1. 1 Al emitir un comprobante, incluye el campo telefono en datos_del_cliente_o_receptor
  2. 2 Tu cliente ingresa a /consumer con ese numero de telefono
  3. 3 Recibe un codigo de verificacion por SMS y accede a todos sus comprobantes de cualquier establecimiento

Importante: el campo telefono es obligatorio para esta funcionalidad

Si no envias el campo telefono en el JSON del comprobante, este se emitira correctamente pero no sera visible en el Portal del Consumidor. No existe otra forma de vincular el comprobante con el receptor. Si deseas que tus clientes finales puedan consultar sus comprobantes, siempre incluye el telefono.

Ejemplo en el JSON:

"datos_del_cliente_o_receptor": {
  "codigo_tipo_documento_identidad": "1",
  "numero_documento": "47852369",
  "apellidos_y_nombres_o_razon_social": "Juan Perez Lopez",
  "telefono": "999888777"    // El consumidor usara este numero para ingresar al portal
}

Idempotency-Key (obligatorio)

Toda emision (factura, boleta, NC, ND, anulacion) requiere el header Idempotency-Key. Si tu request se reintenta (timeout, error de red), Zafra responde la misma respuesta que la primera vez, sin emitir un comprobante duplicado.

  • • Generalo en tu lado como UUID v4 unico por intento logico.
  • • Reusalo si reintentas el mismo POST. Cambialo solo si es una emision nueva.
  • • Si falta, la API responde 400 IDEMPOTENCY_KEY_REQUIRED.
  • • Las respuestas en cache viven 24 horas.
POST https://api.zafra.io/v1/invoices
Authorization: Bearer <tu-api-key>
Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000
Content-Type: application/json

Validar antes de emitir (dry-run)

Mientras desarrollas tu integracion, podes verificar el JSON sin emitir nada ni consumir cuota:

POST https://api.zafra.io/v1/invoices/validate
Authorization: Bearer <tu-api-key>
Content-Type: application/json

{ ... tu JSON identico al de POST /invoices ... }

Respuesta 200: { "success": true, "valid": true }. Si tiene errores, 400 con detalle de campos. No persiste, no firma, no llama a SUNAT.