Flujo de emisión

Desde la versión v1.4.0, toda emisión de DTE es asíncrona.

Por qué asíncrono

Procesar un DTE contra el SII toma unos segundos. Un modelo asíncrono te da una respuesta inmediata y un manejo robusto de reintentos, sin dejar tu request colgado esperando.

El flujo

  1. Tu sistema envía POST /v1/dte/emitir con el JSON del documento. Folyo valida los datos y responde 202 Accepted de inmediato con un job_id.
  2. Folyo procesa el documento y lo envía al SII en segundo plano.
  3. Recibes el resultado por uno de tres canales:
CanalCuándo usar
WebhookRecomendado. Tu endpoint recibe el evento dte.emitido con el resultado.
PollingGET /v1/dte/emision/:jobId cada 2-3 segundos hasta un estado terminal: completed, failed, dlq o discarded.
SSESolo para dashboards en el browser. No recomendado para integraciones server-side.

Estados del job

  • reserved — reserva interna previa al folio; no está publicable ni puede reclamarse.
  • pending — en cola, esperando procesamiento.
  • scheduled — reintento programado para una hora posterior.
  • processing — en proceso contra el SII.
  • completed — el SII recibió el envío y devolvió un Track ID. No confirma la aceptación final del DTE.
  • failed — error terminal del procesamiento. Revisa el campo error para el detalle.
  • dlq — el job llegó a la cola de fallas por un error permanente o tras agotar sus reintentos; no implica un reintento automático. No reemitas todavía: primero confirma si el SII alcanzó a recibir el documento.
  • discarded — un job reservado o en DLQ fue descartado manualmente; no continuará su procesamiento.

Después del envío: el veredicto del SII

Que el job termine en completed significa que el SII recibió el documento y le asignó un Track ID. El veredicto (aceptación o rechazo) llega después: el documento queda en estado enviado y Folyo consulta al SII de forma automática hasta obtener una respuesta firme, momento en que pasa a aceptado_sii o rechazado_sii.

La aceptación SII queda persistida y puede consultarse con GET /v1/dte/consulta/:tipo/:folio; no genera un webhook externo. Un rechazo SII sí dispara dte.rechazado. El evento dte.emitido corresponde al envío con Track ID, no a la aceptación tributaria final.

Normalmente el SII responde en minutos, pero en horas de alta carga puede demorar más de una hora en procesar un envío. Es una demora del SII, no un error:

  • No reemitas un documento porque siga en enviado: el folio ya está usado y una reemisión crea un documento duplicado. Si reintentas un POST /v1/dte/emitir por un error de red, usa siempre el header Idempotency-Key.
  • Usa polling para la aceptación final y, si tu plan incluye webhooks, suscríbete a dte.rechazado para enterarte de un rechazo sin asumir un plazo fijo.

Idempotencia y validación previa

La Idempotency-Key se evalúa por tenant. Usa una clave por emisión lógica y conserva esa misma clave al reintentar el mismo body: Folyo devuelve el job existente. La misma clave con un cuerpo distinto responde 409 IDEMPOTENCY_KEY_CONFLICT.

Un estado failed o dlq no demuestra que el SII no haya recibido el documento: el fallo puede ocurrir después del intento de envío. No lo reemitas automáticamente. Antes de corregirlo, confirma con Folyo y el SII que no hubo envío, que no existe Track ID y que el documento no está registrado. Solo después de esa confirmación explícita usa el request corregido con una nueva clave. Si Folyo reencola operativamente el job original, no crees otra emisión.

Antes de crear el job, Folyo normaliza los giros para el XML del DTE: el GiroEmis efectivo de la empresa —el principal o el seleccionado con emisor_acteco— se acorta a 80 caracteres Unicode y el giro del receptor a 40. La normalización no modifica los datos guardados de la empresa ni del cliente; solo protege la emisión frente a los límites del SII.