Cesibilidad (Ley 19.983)
Si una factura se puede ceder a un factoring, y por qué eso solo lo sabe el SII.
Una factura electrónica se puede ceder — traspasarle el crédito a una empresa de factoring, con mérito ejecutivo. La Ley 19.983 dice cuándo:
- cuando el receptor da acuse de recibo (art. 3), o
- cuando pasan ocho días corridos sin que la reclame (art. 4 inc. 4).
Y dice también cuándo nunca: si el emisor declaró que el pago fue al contado, sin saldo insoluto, el documento no es cedible. La Circular N°35 de 23.06.2017 no deja espacio: «estos documentos no podrán ser cedidos».
Ninguna de esas tres cosas se puede calcular desde el documento que tienes. Dependen de lo que
hizo —o no hizo— la contraparte, y de lo que el SII tenga registrado. Por eso Facturia no calcula la
cesibilidad: se la pregunta al registro del SII y te devuelve la respuesta tal cual. Los ocho días
corridos se cuentan desde la recepción en el SII, no desde tu issue_date.
Preguntar
curl -X POST https://api.facturia.cl/v1/documents/doc_01K2R7.../cesion \
-H "Authorization: Bearer $FACTURIA_KEY" -H "Facturia-Empresa: $EMPRESA"202 si esta llamada encoló la pregunta, 200 si ya hay una idéntica en vuelo. La respuesta llega
al documento; no hay webhook, así que se consulta con GET /v1/documents/doc_01K2R7...:
{
"id": "doc_01K2R7...",
"tipo_dte": 33,
"status": "accepted",
"cesion": {
"cedible": true,
"sii_status_code": 25,
"checked_at": "2026-08-23T09:12:40Z"
}
}| Campo | Qué es |
|---|---|
cedible | true con los códigos 23 y 25 del SII, false con el 21 y el 24, null si nadie ha preguntado todavía o si el SII contestó un código que no leemos como veredicto |
sii_status_code | El codResp crudo, tal como vino. 23 = acuse expreso; 25 = se cumplieron los ocho días; 24 = no cedible; 21 = no cedible porque una nota de crédito de anulación la referencia |
checked_at | Cuándo el SII contestó — no cuándo lo intentamos. Un fallo transitorio de red no lo mueve: reintenta la cola, no tú |
cedible y sii_status_code van juntos a propósito. Si el SII contesta un código que no tenemos
leído, cedible se queda en null y el código queda guardado entero: preferimos decirte «el SII
contestó 9» antes que inventar un booleano. Un false inventado le diría a un factoring que una
factura perfectamente cedible no lo es.
Los dos rechazos
| Código | HTTP | Cuándo |
|---|---|---|
cesion_not_applicable | 422 | El registro del SII responde por los tipos 33, 34 y 43 y por ningún otro. Boletas y notas no tienen estado de cesibilidad |
cesion_status_not_available | 409 | El SII todavía no tiene registrado el documento (queued, sent) o nunca lo va a tener (failed, rejected). Pregunta de nuevo cuando esté accepted |
La tipo 46 no está en esa lista, aunque parezca que debería. La factura de compra sí aparece en
la enumeración de recibos de la Ley 19.983 (33, 34, 43, 46 y 52), pero no aparece en ninguna lista
de tipoDoc del registro del SII, que responde código 3 («Tipo de documento no corresponde»). Son
dos listas distintas y acá aplica la del registro.
Esto es solo lectura
POST .../cesion no cede nada. No arma un AEC, no firma, no escribe en el Registro de Cesión de
Créditos del SII. La operación que consulta (consultarDocDteCedible) es la única de ese servicio
que no lleva código de acción y no puede cambiar ningún estado allá.
Por eso mismo acepta una llave con scope documents:read: quien necesita esto suele ser un sistema
de factoring, y no tiene por qué cargar con una llave capaz de emitir facturas.
No confundir con la copia cedible
Son dos cosas distintas y se parecen mucho de nombre:
GET /v1/documents/doc_01K2R7.../pdf?copy=cediblete da la tercera copia impresa, la que lleva la leyendaCEDIBLEy el recuadro de acuse de recibo. Existe por tipo: toda 33 y toda 34 tienen una, incluso una factura al contado cuya copia no sirve para ceder nada. Ver Artefactos.cesionte dice si el crédito se puede mover ahora.
Tener la copia no significa poder ceder.
En modo de prueba
En sandbox nada de esto sale a la red: la respuesta se simula en proceso, aplicando la misma regla
legal contra el reloj simulado de la empresa. Devuelve 24 hasta que pasan ocho días desde la
aceptación y 25 de ahí en adelante, así que las dos ramas se pueden probar:
# Recién emitida: todavía no
curl -X POST https://api.facturia.cl/v1/documents/doc_01K2R7.../cesion \
-H "Authorization: Bearer $FACTURIA_TEST_KEY" -H "Facturia-Empresa: $EMPRESA"
# → "cesion": { "cedible": false, "sii_status_code": 24, ... }
# Adelanta el reloj de la empresa nueve días
curl -X POST https://api.facturia.cl/v1/test_helpers/clock \
-H "Authorization: Bearer $FACTURIA_TEST_KEY" -H "Facturia-Empresa: $EMPRESA" \
-H "Content-Type: application/json" -d '{"advance_days":9}'
curl -X POST https://api.facturia.cl/v1/documents/doc_01K2R7.../cesion \
-H "Authorization: Bearer $FACTURIA_TEST_KEY" -H "Facturia-Empresa: $EMPRESA"
# → "cesion": { "cedible": true, "sii_status_code": 25, ... }El código simulado para el caso cedible es 25 y no 23 a propósito: en sandbox no hay receptor que
dé acuse, así que el silencio es la única forma en que una factura simulada llega a ser cedible.
Ceder de verdad — POST .../cede (ticket #60)
Todo lo de arriba es lectura: POST .../cesion solo pregunta. POST .../cede sí cede — arma un
Archivo Electrónico de Cesión (AEC) —el DTE original firmado por el emisor, más los términos de la
transferencia, firmados por el cedente— y lo sube al Registro Electrónico de Transferencia de Crédito
del SII. Es un acto real e irreversible, y funciona igual sin importar por qué canal se emitió la
factura — el AEC lleva el sobre original firmado tal cual, así que ya no distingue entre
emission_channel=sfg y emission_channel=mercado (ticket #60, resolución 2026-09-06).
curl -X POST https://api.facturia.cl/v1/documents/doc_01K2R7.../cede \
-H "Authorization: Bearer $FACTURIA_KEY" -H "Facturia-Empresa: $EMPRESA" \
-H "Idempotency-Key: $(uuidgen)" -H "Content-Type: application/json" \
-d '{
"cesionario": {
"rut": "76000000-0",
"razon_social": "Factoring Ejemplo SpA",
"direccion": "Av. Ejemplo 1234, Santiago",
"email": "cesiones@factoring-ejemplo.cl"
},
"ultimo_vencimiento": "2026-10-15"
}'| Campo | Obligatorio | Nota |
|---|---|---|
cesionario.rut | Sí | Dígito verificador módulo 11 |
cesionario.razon_social | Sí | |
cesionario.direccion | Sí | Entre 5 y 80 caracteres — el mínimo y el máximo del propio esquema AEC |
cesionario.email | Sí | |
monto | No | CLP, entre 1 y el total del documento. Por defecto, el total completo |
ultimo_vencimiento | Sí | AAAA-MM-DD |
otras_condiciones, contacto {nombre, fono, email}, email_deudor | No |
202 con un job si esta llamada encoló un intento NUEVO; 200 con el MISMO job si ya hay uno
queued/submitted/aec_generated para este documento — un intento a la vez. El resultado llega al
documento, bajo cesion.status:
"cesion": {
"cedible": true,
"sii_status_code": 25,
"checked_at": "2026-08-23T09:12:40Z",
"status": "confirmed"
}status recorre queued → uno de:
status | Qué significa |
|---|---|
submitted | El AEC se armó, se firmó y se subió al Registro Electrónico de Transferencia de Crédito, que respondió «Envío recibido OK» y entregó un TrackID. Un acuse de recibo no es un registro (ticket #69): el registro valida después, y avisa un rechazo por correo al cedente horas más tarde. No pagues contra este valor. |
confirmed | La propia consulta del registro, wsRPETCConsulta.getEstEnvio, respondió EOK («Envío Aceptado») para ese TrackID. Eso es el SII diciendo que la cesión quedó anotada, y es lo único que escribe confirmed. |
refused | El SII dijo que no: rechazó la subida (el usuario autenticado no tiene permiso de «Envío de Documentos» en la empresa cedente, o la empresa no es emisora DTE), o el registro rechazó el sobre en alguna de sus etapas de validación |
failed | Un intento fenced, una subida malformada, un error interno del SII, una falla de transporte, o una respuesta que nadie reconoce y se guardó para revisión en vez de actuar sobre ella |
aec_generated | LEGADO. El recorrido retirado por el Portal MIPYME llegaba a su página «AEC ha sido generado exitosamente», que producía un ARCHIVO y no registraba nada. Ya nadie lo escribe |
Un intento cuyo sobre nunca se resuelve dentro del presupuesto de consultas conserva submitted
(el AEC sí se recibió) y su job queda failed con cesion_registration_unconfirmed: hay que abrir el
Registro de Cesión de Créditos y mirar.
document.cesion_submitted significa «AEC recibido, anotación pendiente», no «cesión
registrada». El evento sobre el que una integración de factoring debe pagar es
document.cesion_confirmed. document.cesion_failed cubre refused, failed y el registro que
nunca pudo confirmarse.
Rechazos antes de escribir nada, además de los 404/permiso habituales:
| Código | HTTP | Cuándo |
|---|---|---|
cesion_tipo_not_cedible | 422 | El tipo no es 33, 34 ni 43 |
cesion_attempt_may_have_registered | 409 | El intento más reciente de este documento ya había puesto el AEC firmado en el cable cuando se detuvo (ticket #76). Desde aquí no se puede saber si alcanzó a registrarse, así que una segunda cesión sobre la misma factura se rechaza. Esperar no lo resuelve |
En modo de prueba esto se resuelve en la misma request, igual que la rama sandbox de
POST .../cesion: no se abre ningún socket, el intento queda simulated, y se disparan los dos
webhooks —document.cesion_submitted y luego document.cesion_confirmed— para que el evento sobre
el que se paga en producción también sea ejercitable en pruebas.
El envío en vivo sigue bloqueado por el dueño, y desde el 2026-09-06 exige además que la empresa
esté habilitada. El armado del AEC y la subida al registro están construidos y probados contra el
propio esquema del SII — el primer envío en vivo (2026-09-03) fue aceptado por el registro con un
TrackID real y luego rechazado en validación por un defecto de firma, ya corregido. Abrir el envío en
vivo exige DOS condiciones a la vez, ninguna de las cuales activa un deploy por sí sola: una variable
de entorno que solo el dueño exporta en su propia sesión, y que la empresa cedente haya llegado a
onboarding_status=emitting, esté activa, en ambiente palena y no sea sandbox. Un intento en vivo
que no cumpla alguna de las dos se acepta y se encola igual que cualquier otro, y termina failed
sin reintento, nombrando cuál de las dos condiciones falta.