Ir al contenido

Rechazos y reenvío

Cuando la DIAN rechaza un documento, este pasa a rejected. No se pierde: conserva su número y puedes corregirlo y reenviarlo.

GET .../documents/{document_id} trae dian.rules: cada regla con su code, si rechaza (kind: rejection) o solo notifica, el message tal como lo devolvió la DIAN, y una explanation y un hint con la corrección sugerida para los códigos conocidos.

"dian": {
"rules": [{
"code": "FAK24",
"kind": "rejection",
"message": "El nombre del adquiriente no corresponde",
"explanation": "Regla sobre los datos del adquiriente (identificación, nombre, dirección o responsabilidades).",
"hint": "Corrige el campo `customer` según el mensaje y reenvía."
}]
}

El significado de las reglas conocidas está en la referencia de errores. Un documento rechazado también produce el evento de webhook document.rejected.

POST .../documents/{document_id}/resubmit con el mismo cuerpo de emisión, ya corregido, sin resolution_id ni number (el documento conserva los suyos). Responde 202 con el documento otra vez en pending.

Ventana de terminal
curl -s -X POST "https://api.foliios.com/v1/companies/$FOLIIOS_COMPANY_ID/documents/$DOCUMENT_ID/resubmit" \
-H "Authorization: Bearer $FOLIIOS_API_KEY" -H "Content-Type: application/json" \
-d '{
"type": "invoice",
"customer": {
"identification": {"type": "nit", "number": "900373076"},
"name": "Comercializadora Andina S.A.S.",
"emails": ["facturas@andina.example"]
},
"lines": [{"code": "PARQ", "description": "Parqueadero", "quantity": "3", "unit": "HUR", "unit_price": "4000.00",
"taxes": [{"scheme": "iva", "percent": "19"}]}]
}'
import time
from foliios_inicio import EMPRESA, llamar
estado, documento, _ = llamar("GET", f"/v1/companies/{EMPRESA}/documents/{documento_id}")
if documento["status"] == "rejected":
for regla in documento["dian"]["rules"]:
print(regla["code"], regla["message"], "->", regla["hint"])
corregido = armar_documento_corregido(documento) # tu código: arregla lo que dicen las reglas
estado, documento, _ = llamar(
"POST", f"/v1/companies/{EMPRESA}/documents/{documento_id}/resubmit", corregido
)
assert estado == 202, documento

Detalles:

  • Solo se reenvía un documento rejected. Cualquier otro estado responde 409 invalid_state.
  • El número se recupera. Si en modo manual otro documento lo tomó entretanto, 409 number_already_used. En modo automático el siguiente número libre más bajo puede haberse reutilizado: en ese caso también falla.
  • El reenvío se valida otra vez: un cuerpo corregido que sigue siendo inválido responde 422.
  • Cuando la corrección exige un dato fiscal que solo tu cliente tiene (un NIT, un dígito de verificación, un correo), no lo inventes: pídeselo.

Para probar tu manejo de rechazos, pide un escenario de rechazo con la cabecera Foliios-Sandbox-Scenario en la emisión (o con la nota [sandbox:<id>] en notes, o un comprador 999000NNN). El catálogo completo, con la regla que dispara cada uno, está en escenarios; por ejemplo rejected_fad06:

Ventana de terminal
curl -s -X POST "https://api.foliios.com/v1/companies/$FOLIIOS_COMPANY_ID/documents" \
-H "Authorization: Bearer $FOLIIOS_API_KEY" -H "Content-Type: application/json" \
-H "Idempotency-Key: rechazo-1" -H "Foliios-Sandbox-Scenario: rejected_fad06" \
-d @factura.json

Con una clave que no es de sandbox, la cabecera responde 422 sandbox_scenario_not_allowed: se rechaza en vez de ignorarse.

failed no es un rechazo de la DIAN: es un problema (casi siempre de configuración) que impidió firmar o transmitir. No se reintenta solo. El documento trae dian.reason y un dian.failure_code estable:

failure_code Qué falló ¿Reintentable? Quién corrige
environment_mismatch, issuer_not_configured, certificate_unavailable Configuración de la empresa o su certificado Sí El alta de la empresa, en el portal
resolution_expired, resolution_not_yet_valid, number_out_of_range La resolución del documento Sí La resolución en el portal
dian_sender_fault, dian_certificate_rejected La DIAN rechazó la solicitud o el certificado Sí Configuración o certificado
duplicate_unverified La DIAN dijo que ya procesó el documento y en 24 horas no se pudo confirmar su estado Sí, solo verifica Tú o soporte: reintentar consulta de nuevo, no reenvía
invalid_document, rendering_failed, not_sent, unclassified Contenido o defecto de la plataforma No Documento nuevo o soporte

Una vez corregida la causa: POST .../documents/{document_id}/retry, sin cuerpo. Antes de tocar nada foliios revisa que la configuración ya esté bien: si sigue mal responde 409 configuration_still_invalid y no cambia nada. Es idempotente por estado: sobre un documento que ya espera transmisión responde 202 con el documento actual e Idempotent-Replayed: true.

Un documento accepted o rejected no se reintenta (409 invalid_state): un rechazo se corrige con resubmit.

Provoca un rechazo, corrígelo y reenvíalo hasta accepted. Esta comprobación la declara tu programa: la verificación de integración no puede comprobarla, y debes informarla como no verificada.