Estados de envío VeriFactu
El ciclo de vida de un registro de facturación VeriFactu — pending, submitted, accepted, rejected, error —, qué significan el CSV y la huella, cómo funciona el presupuesto de reintentos y cuándo reintentar en lugar de subsanar.
Cada factura que emite tu empresa bajo VeriFactu produce un registro de
facturación: una declaración XML firmada que se transmite a la AEAT y queda
encadenada criptográficamente al registro anterior de la misma empresa. La
factura y su registro son dos objetos distintos con dos ciclos de vida
distintos — una factura puede estar sent y cobrada mientras su registro sigue
rejected por la AEAT.
Esta página trata del registro. Si integras contra Factuarea y solo vigilas el estado de la factura, no te enterarás de que la Administración tributaria rechazó una declaración.
Cuándo aplica
El ciclo de vida del registro aplica a toda empresa con VeriFactu efectivamente
activado, desde el momento en que una factura sale de draft. No aplica a:
- Empresas todavía en modo
no_verifactu: los registros se siguen creando y encadenando en local, pero nunca se transmiten, así que quedan fuera del ciclo aceptado/rechazado (BR-VFC-018, RD 1007/2023 art. 16). - Facturas históricas importadas saltándose el paso de VeriFactu — no se crea
registro alguno, de modo que no hay nada que consultar
(
BR-VFC-009).
Consulta Alta automática en VeriFactu para las compuertas que deciden si el registro llega a crearse.
Los cinco estados
status | Significado | ¿Terminal? | Qué haces |
|---|---|---|---|
pending | El registro existe y está encadenado, pero aún no se ha transmitido. | No | Nada. La transmisión está en cola. |
submitted | Enviado a la AEAT, a la espera de la respuesta definitiva. | No | Nada. Consultar. |
accepted | La AEAT registró la declaración. aeat_csv viene informado. | Sí — inmutable | Nada. Para corregir la factura, emite una rectificativa. |
rejected | La AEAT lo rechazó por un error de datos (NIF del destinatario desconocido, esquema, totales). | Respuesta definitiva, pero reparable | Corrige los datos y luego subsanar. |
error | Fallo técnico de transmisión: timeout, AEAT inaccesible, problema de firma. | No | Nada, o forzar un retry. |
La distinción que importa es rejected frente a error. rejected es la AEAT
diciendo «he leído tu declaración y está mal». error es la declaración que
nunca llegó. Se reparan con operaciones distintas, y confundirlas es el error de
integración más habitual en este endpoint.
accepted es el único estado genuinamente inmutable: la matriz de transiciones
rechaza cualquier salida de él, porque el RD 1007/2023 hace inalterable un
registro ya registrado. Todos los demás estados admiten una nueva transición, y
eso es lo que hace posibles el reintento y la subsanación.
Qué envía la API
Nunca creas un registro con un payload — se crea por ti. Lo que haces es
leerlo. La API v1 devuelve el objeto registro en
GET /v1/verifactu/records/{id},
GET /v1/verifactu/records
y, indexado por factura, en
GET /v1/invoices/{id}/verifactu:
| Campo | Significado |
|---|---|
status | Uno de los cinco estados de arriba. |
type | ALTA (la factura se emitió) o ANULACION (se anuló). |
invoice_type | El tipo de factura AEAT congelado en el momento de emitir: F1, F2, F3, R1–R5. |
huella | La huella SHA-256 de este registro, en hexadecimal mayúsculas. Es el eslabón al que apuntará el registro siguiente. |
aeat_csv | El Código Seguro de Verificación que devuelve la AEAT al aceptar. Vale null hasta entonces. Es el valor con el que concilias contra la Administración tributaria. |
aeat_submission_id | Nuestro identificador de transmisión, para conversaciones con soporte. |
transmitted_at | ISO 8601 de la última transmisión que llegó a la AEAT. Viene informado en submitted y accepted; vale null en pending, rejected y error. |
environment | El entorno AEAT de esta empresa — producción o el entorno de pruebas de la AEAT. Un CSV obtenido en pruebas no es un alta real. |
is_simplificada / is_substitute_for_simplified | Si la factura de origen era una F2, y si este registro sustituye facturas simplificadas mediante una F3. |
Dos campos merecen su propio aviso.
La huella es identidad, no una suma de control que puedas recalcular. Se
calcula a partir del NIF del emisor, la serie y el número, la fecha de
expedición, el tipo de factura, la cuota total, el importe total, la huella del
registro anterior y la marca de tiempo de generación — en ese orden y formato
exactos.
Si cualquiera de esos valores cambia, la cadena se rompe y falla la prueba de
integridad de toda la empresa (BR-VFC-013). Por eso hay
correcciones que no se pueden reparar en el sitio; ver
Reintentar o subsanar.
El aeat_csv se escribe una sola vez. Al aceptarse se persiste y nunca se
sobrescribe, ni siquiera si la AEAT devuelve el mismo CSV en una transmisión
posterior. Un registro que pasa a rejected después de haber estado submitted
conserva el CSV anterior a efectos de auditoría, así que un aeat_csv no nulo
en un registro rejected es lo esperado, no un fallo
(BR-VFC-016).
curl https://api.factuarea.com/v1/invoices/0197a2a8-4cf0-7a31-9a5e-3f2b8c1d6e42/verifactu \
-H "Authorization: Bearer fact_live_3pXnR2VbY7TcA9eFmN5z8KqW"{
"data": {
"id": "0197b3c9-1de2-7c40-8b71-a4d5e6f70123",
"object": "verifactu_record",
"type": "ALTA",
"invoice_type": "F1",
"invoice_number": "F-2026-0042",
"date": "2026-05-15",
"amount": 121.0,
"status": "accepted",
"huella": "9F2C1A0B7E4D6835A1C0B9E8D7F6A5B43C2D1E0F9A8B7C6D5E4F3A2B1C0D9E8F",
"aeat_submission_id": "sub_0197b3c9",
"aeat_csv": "FCT-2026-A1B2C3D4-E5F6",
"environment": "production",
"transmitted_at": "2026-05-15T09:41:02Z",
"is_simplificada": false,
"is_substitute_for_simplified": false,
"created_at": "2026-05-15T09:40:58Z"
}
}El presupuesto de reintentos existe, y no viaja en el payload
Detrás de error hay un contador y una planificación. Una transmisión fallida se
vuelve a encolar con retroceso exponencial, y el número de reintentos técnicos a
ciegas está topado por ronda de transmisión; agotado el tope, un reintento manual
adicional responde con un error de regla de negocio en lugar de volver a encolar
(BR-VFC-006). Junto al contador, el registro lleva una marca
de incidencia técnica, que se levanta cuando fue la propia AEAT la que estuvo
inaccesible y hubo que declarar la incidencia — se conserva incluso tras una
aceptación posterior, a efectos de auditoría.
Ninguno de esos tres valores — el contador de intentos, el siguiente reintento
programado y la marca de incidencia — se expone en el objeto registro de la v1.
Gobiernan el comportamiento que observas, pero hoy no puedes leerlos por la API
pública. Lo que sí puedes observar es el estado en sí, transmitted_at y la
cronología de auditoría del registro vía
GET /v1/verifactu/records/{id}/activities.
No construyas en tu cliente un modelo adivinado de la planificación de
reintentos: consulta el estado.
Reintentar o subsanar
Ambas operaciones actúan sobre un registro que ya existe. No son intercambiables.
| Estado del registro | Causa | Operación | Por qué |
|---|---|---|---|
error | La declaración nunca llegó a la AEAT. | POST /v1/verifactu/records/{id}/retry | El XML almacenado es correcto. Se reenvía sin cambios. |
rejected | La AEAT lo leyó y rechazó los datos. | POST /v1/verifactu/records/{id}/subsanar | Hay que regenerar el XML a partir de los datos maestros corregidos. |
accepted | — | Ninguna. | El registro es inmutable. Emite una factura rectificativa. |
rejected, pero la corrección toca un campo de la huella | Se declaró mal el total, la fecha, el número, el NIF o el tipo de factura. | Ninguna — anular y volver a emitir. | Cambiar un campo de la huella invalidaría la cadena. subsanar lo rechaza de entrada. |
Reintentar a ciegas consume el presupuesto de reintentos técnicos. La
subsanación no: es una corrección manual deliberada con datos nuevos, la norma no
le pone tope y ejecutarla reinicia la ronda de transmisión — el contador de
intentos vuelve a cero y la retransmisión automática del contenido corregido
recupera su presupuesto íntegro (BR-VFC-006,
BR-VFC-020).
La subsanación regenera el payload pero incrusta la huella original, el eslabón
de cadena original y la marca de tiempo de generación original, porque son los
que permiten a la AEAT casar el reenvío con el registro que rechazó. Antes de
persistir nada compara los campos regenerados que entran en la huella con los
almacenados; si alguno difiere, responde 422 con el subcódigo que te indica que
hace falta anular, y no se modifica nada. El flujo completo, los subcódigos de
error y los consejos de prevención están en
Subsanación de registros VeriFactu.
Qué sale en el PDF
El estado del registro no cambia el PDF. Sea cual sea el estado, la factura
imprime el mismo bloque QR legal en la esquina superior derecha de la primera
página: la etiqueta QR tributario:, un código de 30×30 mm que apunta al
servicio de verificación de la AEAT con el NIF del emisor, la serie y el número,
la fecha y el total, y la leyenda debajo (BR-VFC-015).
Tres consecuencias que conviene contemplar en el diseño:
- El QR se imprime en cuanto existe un registro — incluso mientras está
pending,errororejected. Un destinatario que lo escanee antes de la aceptación verá que la AEAT no informa de ningún alta. Es el comportamiento correcto, no un defecto. - El CSV no se imprime en el PDF. Solo está disponible por la API y en el panel.
- La huella y la marca de tiempo del alta también dejaron de imprimirse. Si los estabas extrayendo del PDF, léelos del registro.
La subsanación es la única operación que además toca el documento impreso:
vuelve a congelar deliberadamente los snapshots inmutables de destinatario y
emisor a partir de los datos maestros actuales, para que el PDF coincida con lo
que se volvió a declarar a la AEAT (BR-INV-024,
BR-VFC-020). Es el único camino que reescribe un snapshot ya
congelado.
Qué llega a la AEAT
Cada registro transmite una declaración, encadenada por su huella al registro
anterior de la misma empresa. Existen tres clases de registro, y no comparten una
sola cadena: las altas (ALTA) y las anulaciones (ANULACION) comparten la
cadena de facturación, mientras que los registros de eventos del sistema
mantienen una cadena propia aparte, porque la norma trata los eventos operativos
como evidencia separada (BR-VFC-014).
Cuando un reenvío sigue a un rechazo, la declaración regenerada lleva además las
marcas AEAT que declaran que el envío anterior fue rechazado y que, por tanto, el
registro nunca llegó a registrarse. Ninguna de las dos entra en el cálculo de la
huella, así que declararlas no perturba la cadena
(BR-VFC-026).
Puedes verificar la cadena entera por tu cuenta con
GET /v1/verifactu/chain/validate,
que recalcula todas las huellas e informa de las anomalías. Está limitado a una
llamada por minuto y empresa porque recorre el libro registro completo.
Trazabilidad
Derivado de las reglas de dominio del backend de Factuarea:
BR-VFC-006— política de reintentos: retroceso exponencial, intentos topados por ronda, y el tope que explícitamente no aplica a la subsanación.BR-VFC-013— la cadena de huellas es inmutable y verificable; cualquier alteración invalida la garantía de integridad ante la AEAT.BR-VFC-014— las tres clases de registro y sus cadenas independientes.BR-VFC-015— el bloque QR obligatorio en la factura impresa.BR-VFC-016— el CSV como identidad pública del registro, persistido sin alterar.BR-VFC-018— modono_verifactu: cadena local, sin transmisión.BR-VFC-020— subsanación de registros rechazados, guarda de la huella y reinicio de la ronda de transmisión.BR-VFC-026— las marcas AEAT para un reenvío tras rechazo.BR-INV-024— el snapshot inmutable del destinatario y la única excepción que lo refresca.
Derivado también de la máquina de estados de transmisión documentada junto a esas
reglas (AeatTransmissionStatus), que es la fuente de verdad de la matriz de
transiciones citada en Los cinco estados.