Factuarea APIDevelopers

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

statusSignificado¿Terminal?Qué haces
pendingEl registro existe y está encadenado, pero aún no se ha transmitido.NoNada. La transmisión está en cola.
submittedEnviado a la AEAT, a la espera de la respuesta definitiva.NoNada. Consultar.
acceptedLa AEAT registró la declaración. aeat_csv viene informado.Sí — inmutableNada. 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.
rejectedLa 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 reparableCorrige los datos y luego subsanar.
errorFallo 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).NoNada 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:

CampoSignificado
statusUno de los cinco estados de arriba.
typeALTA (la factura se emitió) o ANULACION (se anuló).
invoice_typeEl tipo de factura AEAT congelado en el momento de emitir: F1, F2, F3, R1–R5.
huellaLa huella SHA-256 de este registro, en hexadecimal mayúsculas. Es el eslabón al que apuntará el registro siguiente.
is_blockedtrue cuando el registro está en error sin reintento automático: necesita tu acción y detiene los registros que van detrás.
block_reasonPor qué está bloqueado: MISSING_CERTIFICATE, MISSING_REPRESENTATION, PRESENTER_NOT_ENABLED o SUBMISSION_REJECTED; null en otro caso.
aeat_error_codeEl ú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_subsanarSi 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_csvEl 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_idNuestro identificador de transmisión, para conversaciones con soporte.
transmitted_atISO 8601 de la última transmisión que llegó a la AEAT. Viene informado en submitted y accepted; vale null en pending, rejected y error.
environmentEl 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_simplifiedSi 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 registroCausaOperaciónPor qué
error, no bloqueadoLa declaración nunca llegó a la AEAT.POST /v1/companies/{company}/verifactu/records/{id}/retryEl XML almacenado es correcto. Sale otra vez en el siguiente lote de la empresa, en orden.
error, bloqueadoAlgo necesita tu acción: certificado, representación, presentador.Resuelve la causa y luego POST /v1/companies/{company}/verifactu/records/retry-blockedReactiva de una vez todos los registros bloqueados de la empresa.
rejectedLa AEAT lo leyó y rechazó los datos, o nunca salió porque incumplía el esquema.POST /v1/companies/{company}/verifactu/records/{id}/subsanarUn registro nuevo, regenerado a partir de los datos maestros corregidos.
acceptedUn error de datos para el que las reglas de facturación no exigen una rectificativa.POST /v1/companies/{company}/verifactu/records/{id}/subsanarUn registro nuevo sucede al aceptado, que queda intacto.
accepted, y las reglas de facturación lo exigenUn 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 huellaSe 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, error o rejected. 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 sustituye BR-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 con retry-blocked.
  • BR-VFC-049 — un registro que incumple el esquema de la AEAT se aísla como rejected (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 — modo no_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, RechazoPrevio y 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.

En esta página

¿Te echamos una mano?Contactar con soporte