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 funcionan los reintentos y los registros bloqueados y cuándo reintentar, liberar o 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. Un error de datos en él se corrige con un registro nuevo (subsanar) o, cuando las reglas de facturación lo exigen, con una rectificativa. |
rejected | La AEAT lo rechazó por un error de datos (NIF del destinatario desconocido, esquema, totales), o Factuarea lo detuvo antes de enviarlo porque incumplía el esquema de la AEAT (SCHEMA_INVALID). | Respuesta definitiva, pero reparable | Corrige los datos y luego subsanar. |
error | Fallo técnico de transmisión (timeout, AEAT inaccesible), o el registro está bloqueado esperando algo que solo tú puedes aportar (un certificado, una representación). | No | Nada ante un fallo técnico (se reintenta solo); en un registro bloqueado, resuelve la causa y retry-blocked. |
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. Corregir un registro aceptado nunca lo edita: subsanar
genera un registro nuevo que lo sucede. Todos los demás estados admiten una
nueva transición, y eso es lo que hace posible el reintento.
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/companies/{company}/verifactu/records/{id},
GET /v1/companies/{company}/verifactu/records
y, indexado por factura, en
GET /v1/companies/{company}/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. |
is_blocked | true cuando el registro está en error sin reintento automático: necesita tu acción y detiene los registros que van detrás. |
block_reason | Por qué está bloqueado: MISSING_CERTIFICATE, MISSING_REPRESENTATION, PRESENTER_NOT_ENABLED o SUBMISSION_REJECTED; null en otro caso. |
aeat_error_code | El último código de la AEAT (por ejemplo 1110 o 4112), uno interno (MISSING_CERTIFICATE, SCHEMA_INVALID…) o el código de aviso de un registro aceptado con errores; null cuando no hay ninguno. |
can_subsanar | Si POST …/subsanar admite este registro: un alta aceptada, aceptada con errores o rechazada, que es la última de su factura y esta no está anulada. |
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/companies/{company}/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"
}
}Los reintentos no tienen tope, y algunos registros están bloqueados
Detrás de error hay dos situaciones muy distintas.
Un fallo técnico se reintenta solo, sin límite. Si un envío no obtiene respuesta,
obtiene un fallo de servidor o falla la red, sus registros se reintentan con
intervalos crecientes —1, 5, 15 y 30 minutos y después cada 55— de modo que no pase
más de una hora entre dos intentos, mientras dure la incidencia (art. 16.4 de la
Orden HAC/1177/2024). No hay número máximo de intentos, así que max_retries_exceeded
ya no se devuelve para los registros de facturación (sigue aplicando al reintento de
un evento en modo no_verifactu). Mientras hay una incidencia, el siguiente envío
lleva la marca de incidencia, y los registros generados entretanto esperan detrás de
los anteriores.
Un registro bloqueado no se reintenta, porque reintentar volvería a fallar hasta
que actúes: ningún certificado utilizable, ninguna representación activa, un
presentador que la AEAT no ha habilitado o un rechazo del lado del cliente. Muestra
is_blocked: true y su block_reason, y detiene todos los registros que van
detrás en la cadena de la empresa. Resuelve la causa y se libera solo (subir el
certificado, registrar la representación o cambiar el modo reactiva lo que ese suceso
puede liberar) o con una llamada a
POST /v1/companies/{company}/verifactu/records/retry-blocked,
que responde 202 con cuántos registros reactivó. Las causas y su significado están
en Alta automática en VeriFactu.
GET /v1/companies/{company}/verifactu/stats informa de cuántos registros siguen esperando
(pending_incident_count), cuántos de ellos están bloqueados
(blocked_incident_count) y la antigüedad del más antiguo (oldest_pending_at).
El contador de intentos y la planificación del siguiente reintento siguen sin
exponerse en el objeto registro; lo que consultas es el estado. La cronología de
auditoría está en
GET /v1/companies/{company}/verifactu/records/{id}/activities.
Reintentar o subsanar
Las dos operaciones actúan sobre un registro que ya existe, y una tercera libera los bloqueados. No son intercambiables.
| Estado del registro | Causa | Operación | Por qué |
|---|---|---|---|
error, no bloqueado | La declaración nunca llegó a la AEAT. | POST /v1/companies/{company}/verifactu/records/{id}/retry | El XML almacenado es correcto. Sale otra vez en el siguiente lote de la empresa, en orden. |
error, bloqueado | Algo necesita tu acción: certificado, representación, presentador. | Resuelve la causa y luego POST /v1/companies/{company}/verifactu/records/retry-blocked | Reactiva de una vez todos los registros bloqueados de la empresa. |
rejected | La AEAT lo leyó y rechazó los datos, o nunca salió porque incumplía el esquema. | POST /v1/companies/{company}/verifactu/records/{id}/subsanar | Un registro nuevo, regenerado a partir de los datos maestros corregidos. |
accepted | Un error de datos para el que las reglas de facturación no exigen una rectificativa. | POST /v1/companies/{company}/verifactu/records/{id}/subsanar | Un registro nuevo sucede al aceptado, que queda intacto. |
accepted, y las reglas de facturación lo exigen | Un importe erróneo, una devolución, un error que debe corregirse con una rectificativa. | Emite una factura rectificativa. | Es el camino que prescriben las reglas de facturación. |
rejected o accepted, 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 tampoco tiene límite de intentos. La subsanación es una
corrección manual deliberada con datos nuevos, la norma no le pone tope y nunca
edita un registro: genera un alta nueva, con la misma clave de factura que la que
corrige, su propia huella y su propia posición en la cadena, y el original queda
intacto (BR-VFC-020, BR-VFC-046). Antes de crear
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 crea 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).
Una subsanación se declara como un alta nueva que lleva siempre
Subsanacion=S, más RechazoPrevio cuando sigue a un rechazo: X para un alta
rechazada de una factura que la AEAT no tiene, S para una subsanación rechazada de
una factura que sí tiene, y ninguno para la subsanación de un registro aceptado.
Ninguna de las dos marcas entra en el cálculo de la huella, así que declararlas no
perturba la cadena (BR-VFC-026, BR-VFC-046). Los
registros de una empresa llegan a la AEAT en lotes ordenados de hasta 1.000,
respetando el tiempo de espera que indica la AEAT (BR-VFC-056).
Puedes verificar la cadena entera por tu cuenta con
GET /v1/companies/{company}/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— la política anterior de reintentos con tope; para los registros de facturación la sustituyeBR-VFC-040.BR-VFC-040— reintento periódico, al menos cada hora, sin tope de intentos, en el orden de la cadena y con el aviso de pendientes.BR-VFC-048— un registro bloqueado (sin reintento automático) y su liberación, por su causa o conretry-blocked.BR-VFC-049— un registro que incumple el esquema de la AEAT se aísla comorejected(SCHEMA_INVALID) y nunca se envía.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 aceptados o rechazados como un alta nueva, y guarda de la huella.BR-VFC-046— varias altas por factura: ordinal,RechazoPrevioy la última alta.BR-VFC-026— las marcas AEAT de un alta de subsanación (Subsanacion,RechazoPrevio).BR-VFC-056— remisión en lotes ordenados con control de flujo.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.