Saltar al contenido
Tarifa anual desde S/ 37 al mes + IGV. Pide tu demo sin costo. Reserva tu demo
Sistema Facturación Perú
Menú del portal

Empezar

Conceptos de la API

Empresa y subdominio, locales y series, modo pruebas y producción, el camino de un comprobante ante SUNAT y la diferencia entre resumen diario y envío directo.

Actualizado el

Antes de integrar, conviene tener claras seis ideas. Con ellas entiendes por qué una boleta queda «registrada» y una factura «aceptada» al instante, o por qué tu clave emite en un local y no en otro.

Empresa y dirección de la API

Cada empresa de Sistema Facturación Perú tiene su propio subdominio y su propia API:

Entorno Dirección Clave
Producción https://<tu-subdominio>.sistemafacturacionperu.com/api/v1 sfp_live_…
Pruebas https://pruebas.sistemafacturacionperu.com/api/v1 sfp_test_…

Todo lo que emites por la API pasa por las mismas reglas que la web: series, régimen tributario, Ficha RUC, detracción, anticipos, deuda vencida del cliente, control de stock y límite del plan. Lo que la web no deja hacer, la API tampoco.

Las respuestas siempre tienen la misma forma:

{ "success": true, "data": { "…": "…" }, "meta": { "page": 1, "per_page": 20, "total": 87, "last_page": 5 } }
{ "success": false, "code": "serie_invalida", "message": "La serie ingresada es incorrecta…", "errors": { "serie_documento": ["…"] } }

Decide por el code (es estable) y muestra el message (está en español). La lista completa está en el catálogo de errores.

Locales (sedes) y series

Una clave actúa como el usuario que elegiste al crearla: sus permisos, su local y sus series. Para emitir en otro local, manda el código SUNAT del local en establecimiento:

{ "establecimiento": "0001", "serie_documento": "F002", "…": "…" }

GET /establecimientos te da cada local con sus series y almacenes:

{
  "success": true,
  "data": [{
    "id": 1, "codigo": "0000", "nombre": "Tienda principal", "direccion": "Av. Lima 123", "ubigeo": "150101",
    "series": [{ "tipo": "01", "serie": "F001" }, { "tipo": "03", "serie": "B001" }, { "tipo": "09", "serie": "T001" }],
    "almacenes": [{ "id": 1, "nombre": "Almacén Lima", "principal": true }]
  }]
}
  • Una clave creada con local fijo solo emite en ese local (403 establecimiento_no_permitido en otro).
  • Una serie que no es del local o del tipo de comprobante responde 422 serie_invalida.
  • "numero_documento": "#" toma el siguiente correlativo de la serie. Es lo recomendado.

Modo pruebas y producción

Pruebas Producción
Empresa Una empresa de pruebas aparte, compartida La tuya
SUNAT Beta de SUNAT: nada tiene validez tributaria Producción: comprobantes válidos
Lo que ves Solo lo que emitió tu clave Todo lo de tu empresa que tu usuario puede ver
Clientes y productos Compartidos entre todas las claves de pruebas: no pongas datos reales Los tuyos
Duración Se borra a los 7 días Se guarda los años que pide SUNAT
Plan Las claves de pruebas se crean desde el Plan PRO Desde el Plan PRO

El modo pruebas no cambia nada de tu empresa: no consume tus correlativos ni tu stock y no cuenta para el límite de tu plan. Una clave sfp_test_ contra la dirección de producción responde 401 clave_de_pruebas.

El camino de un comprobante

Cada comprobante tiene un estado con un código SUNAT, una clave legible y una descripción:

{ "estado": { "codigo": "05", "clave": "aceptado", "descripcion": "Aceptado" } }
clave codigo Qué significa
registrado 01 Creado y firmado. Aún no está en SUNAT (o va en el resumen diario).
enviado 03 Enviado; SUNAT todavía no responde (pasa con resúmenes y bajas, que van por ticket).
aceptado 05 SUNAT lo aceptó. Ya tiene CDR.
observado 07 Aceptado con observaciones: es válido, pero revisa la nota de SUNAT.
rechazado 09 SUNAT lo rechazó: no tiene validez. Corrige y emite uno nuevo.
por_anular 13 Pediste la anulación y SUNAT todavía no responde.
anulado 11 Anulado con una comunicación de baja o un resumen de anulación.

El camino normal es registrado → enviado → aceptado / observado / rechazado, y después, si lo anulas, por_anular → anulado. La respuesta de SUNAT queda en sunat:

{ "sunat": { "codigo": "0", "descripcion": "La Factura numero F001-120, ha sido aceptada", "notas": [] } }

No hace falta preguntar el estado cada minuto: registra un webhook y te avisamos con comprobante.aceptado, comprobante.observado, comprobante.rechazado o comprobante.anulado.

Resumen diario frente a envío directo

SUNAT recibe los comprobantes de dos formas, y el sistema elige la correcta por ti:

Facturas y sus notas Boletas y sus notas
Cómo llegan a SUNAT Envío directo: uno por uno, al emitir (según la configuración de la empresa) Dentro del resumen diario
Estado al emitir Normalmente aceptado u observado en la misma respuesta registrado
Quién arma el envío La API, en la misma llamada El sistema, solo: dos veces al día envía las boletas de los días anteriores y consulta los resúmenes enviados
Para anular Comunicación de baja Resumen de anulación

Por eso POST /comprobantes/{id}/reenviar-sunat solo sirve para facturas y sus notas: una boleta responde 422 va_en_resumen. Lo explicamos en detalle en la guía del resumen diario.

Orígenes: facturar lo que ya existe

Para facturar una cotización, un pedido, una nota de venta o una guía, manda origen. Queda enlazado como en la web y la mercadería no sale dos veces del stock:

{ "origen": { "tipo": "cotizacion", "id": 15 }, "serie_documento": "F001", "…": "…" }

tipo puede ser cotizacion, pedido, nota_venta o guia. Si el origen no existe o no se puede facturar responde 422 origen_no_existe, origen_no_permitido o nota_venta_no_facturable.

Productos, lotes, series y almacenes

Las líneas usan tu codigo_interno. Si la empresa tiene control de stock, un código que no existe responde 422 producto_no_existe: créalo antes con POST /productos (nace sin stock). Lotes, números de serie y almacén van en cada línea:

{
  "codigo_interno": "CEL-A15",
  "almacen_id": 2,
  "series": ["356938035643809", "356938035643817"],
  "lotes": [{ "codigo": "L-01", "cantidad": 2 }]
}

El stock por almacén, lote y serie lo consultas con GET /stock (alcance stock.leer).

Cobros

Un comprobante al contado lleva sus pagos al emitirse. Para los cobros posteriores (una factura a crédito, por ejemplo) usa POST /comprobantes/{id}/cobros con la cuenta de cobro y el número de operación si no es efectivo, y GET /comprobantes/{id}/cobros para saber cuánto falta cobrar. Es el mismo registro que Por cobrar › Registrar cobro de la web.

Sigue con

Portal para desarrolladores · ¿Algo no está claro o te falta un ejemplo? Escríbenos y lo mejoramos.