Leer el resultado: el documento v1, los avisos y los errores
Qué trae el documento v1, qué significa la dirección y el aviso TIPO_DISCREPANTE, cómo tratar un aviso que tu programa no conoce y los códigos de error estables.
El documento v1
Un trabajo terminado trae en documento la factura auditada. Su esquema completo es
respuesta.schema.json; estos son sus apartados:
| campo | qué es |
|---|---|
direccion | RECIBIDA (una compra de la empresa de la llave) o EMITIDA (una venta): la que declaraste al subirla |
proveedor, cliente | las dos partes, con nombre, cif_nif y direccion |
factura | la cabecera: numero, fecha, divisa, base_total, iva_total, total_factura, recargo_total… |
impuestos_y_retenciones | las retenciones (hoy, IRPF), con su porcentaje y su importe, negativos si son retención |
lineas | las líneas de la factura |
dictamen_auditoria | los hallazgos de la auditoría |
verificacion_identidad | lo que dice la Agencia Tributaria del NIF de la otra parte |
lectura_papel | quién emite y quién recibe según el papel, leído a ciegas |
trazabilidad | lo que se comprobó del desglose al cerrar |
avisos | los avisos de la API; lista vacía si no hay ninguno |
proveedor es siempre quien emite la factura y cliente siempre quien la recibe, en compras y en ventas.
En una venta, tu empresa es el proveedor. Para saber quién es quién según el papel, mira lectura_papel.
Un trabajo terminado, tal como lo devuelve la API (una compra del banco de pruebas, con NIF reservados por la AEAT), recortado a lo principal:
{
"trabajo": "trb_01J9ZQ3K4T7W2B5N8C6D0F1G2H",
"estado": "terminado",
"creado": "2026-10-02T16:18:24Z",
"terminado": "2026-10-02T16:18:49Z",
"caduca": "2026-10-03T16:18:49Z",
"documento": {
"cliente": {"nombre": "TEST SL", "cif_nif": "B00000018", "direccion": ""},
"proveedor": {"nombre": "OPERACION NO IDENTIFICADA EN CONSTITUCIÓN", "cif_nif": "B99999997", "direccion": "Poligono Norte 5, 50014 Zaragoza"},
"factura": {"numero": "P-2026-0925", "fecha": "2026-09-22", "divisa": "EUR", "base_total": 150.0, "total_factura": 181.5, "es_rectificativa": false, "tiene_recargo_equivalencia": false, "iva_total": 31.5, "recargo_total": null},
"impuestos_y_retenciones": [],
"verificacion_identidad": {"verificado_por": "Agencia Tributaria (censo de NIF)", "identificador": "B99999997", "situacion": "IDENTIFICADO", "fecha_verificacion": "2026-09-25"},
"trazabilidad": {"desglose_cuadra": true, "errores_finales": 0},
"direccion": "RECIBIDA",
"avisos": []
},
"pool": {"estado": "activa", "disponibles": 2411, "aviso_80": false}
}
El ejemplo entero, con sus líneas y su lectura_papel, está en la
referencia interactiva.
factura.recargo_total es el recargo de equivalencia tal como lo da el motor de lectura, y null si no lo ha
dado: la API no lo calcula ni lo supone.
En v1 se pueden añadir campos, nunca quitarlos ni renombrarlos. Tu programa debe ignorar los campos que
no conozca.
Los avisos
Un aviso no rechaza la factura: el trabajo llega terminado, con su documento, y descuenta de la pool como
cualquier otro; pero conviene revisarla antes de contabilizarla. Van en documento.avisos, cada uno con su
codigo estable y un mensaje. Los de hoy (… es el dato de tu factura):
codigo | mensaje que recibes |
|---|---|
LECTURA_INCOMPLETA | La auditoría terminó sin que todas las comprobaciones cuadraran. Revise el documento antes de contabilizarlo. |
DESCUADRE | Los importes del documento no cuadran entre sí (bases, cuotas y total) ni tras releerlo. Puede que la factura esté mal calculada en origen. |
NIF_CONTRAPARTE_NO_LOCALIZADO | No se pudo localizar el NIF de la otra parte de la factura (el emisor si es recibida, el receptor si es emitida). |
CIERRE_DESCONOCIDO | No se pudo determinar cómo terminó la auditoría. Revise el documento. |
PAGINAS_NO_LEIDAS | El documento tiene … páginas y solo se leen las … primeras. |
EMPRESA_NO_APARECE | El NIF asociado a la llave (…) no aparece entre los identificadores leídos en el documento. Compruebe que la factura es de esa empresa. |
TIPO_DISCREPANTE | Se ha leído como …, como se indicó al subirla, pero en el documento la empresa de la llave aparece como …. Compruebe si es una compra o una venta. |
TIPO_DISCREPANTE: dijiste compra y el papel dice venta (o al revés)
La factura se lee como la declaraste al subirla, y direccion lo repite. Pero en el papel la empresa de la
llave aparece en el lado contrario. Antes de contabilizarla, comprueba si es una compra o una venta, que es lo
que te pide el mensaje del aviso.
Un aviso que tu programa no conoce
La lista crece: se añaden códigos, nunca se renombran. Un código que tu programa no conozca, trátalo como «revise el documento».
Los errores
Cada error lleva un codigo estable, que es el que debe mirar tu programa, y un mensaje para personas,
que puede cambiar de redacción:
{
"error": {
"codigo": "RITMO_EXCEDIDO",
"mensaje": "Demasiadas peticiones seguidas. Espera y reintenta.",
"reintentar_en_s": 5
}
}
En 429 y 503, reintentar_en_s es lo mismo que la cabecera Retry-After. En POOL_AGOTADA, recargar dice
dónde se recarga la pool.
| HTTP | codigo | qué hace tu programa |
|---|---|---|
| 401 | LLAVE_INVALIDA, LLAVE_ANULADA, IP_NO_PERMITIDA, LLAVE_SIN_PERMISO | revisar la llave: falta, no es válida, está anulada, la IP no está permitida o no sirve para esa ruta |
| 402 | POOL_AGOTADA, POOL_CERRADA | la pool no puede procesar (ver la guía de la pool) |
| 410 | NO_ENCONTRADO | no existe, es de otra llave o ya caducó |
| 410 | RECOGIDA_NO_VALIDA | el vale de recogida está usado, caducado o no existe |
| 413, 415, 422 | DOCUMENTO_NO_VALIDO | el fichero pasa de 15 MB, no es PDF, JPEG ni PNG, falta o está roto |
| 422 | PETICION_NO_VALIDA | la petición está mal formada |
| 429 | RITMO_EXCEDIDO | esperar Retry-After y reintentar |
| 500 | ERROR_INTERNO | un fallo nuestro; no se ha descontado nada y puedes reintentar |
| 503 | ERROR_INTERNO | el motor de lectura no está disponible ahora mismo: reintentar tras Retry-After |
Y dentro de un trabajo rechazado (que contesta 200), error.codigo es NO_ES_FACTURA, MULTIFACTURA,
DOCUMENTO_NO_VALIDO o ERROR_INTERNO. Un trabajo rechazado no descuenta de la pool.
Una ráfaga de ellos hace que el cortafuegos de entrada bloquee tu IP durante horas. Los fallos de llave son
401; los de la pool, 402; los de ritmo, 429; los del documento, 413, 415 o 422; y si el motor de
lectura no está disponible, 503 con Retry-After. El guion de arranque rápido en Python solo vuelve a preguntar
ante 429 y 503, esperando lo que dice Retry-After.
La tabla de todos los errores, con un ejemplo literal de cada uno, está en la documentación.