Límites y convenciones
Límites de peticiones, paginación y las convenciones comunes a toda la API.
Límites de peticiones
Cada clave API lleva asociado un límite de peticiones por segundo, una ráfaga y una cuota mensual, según el plan:
| Plan | Peticiones/s | Ráfaga | Cuota mensual |
|---|---|---|---|
| Sandbox | 10 | 20 | 20.000 peticiones |
| Esencial | 50 | 100 | 500.000 peticiones |
| Plataforma | 100 | 200 | 5.000.000 de peticiones |
| Dedicado | 500 | 1.000 | 50.000.000 de peticiones |
Estos límites son topes técnicos, no la unidad de facturación. Una petición no es una factura: las consultas de estado, los listados y las comprobaciones de /v1/cuenta cuentan para la cuota y no se facturan. Lo que se factura son las altas aceptadas en LIVE. Ver Precios.
Las cuotas están dimensionadas por encima de lo que consume una integración correcta al volumen de su plan. Sondear el estado de cada factura en bucle agota la cuota antes que el volumen real de emisión: usa webhooks para el resultado de la remisión y reserva las consultas para los casos que no lo reciban.
La cuota mensual es por clave, no por cuenta. Cada clave tiene su propio contador, que se reinicia el día 1. Rotar no lo reinicia: la clave nueva hereda el consumo de la anterior.
El consumo se lee en el campo consumo de GET /v1/cuenta, junto con la marca de tiempo de la lectura. El dato va unos minutos por detrás. Sirve para anticipar el tope, no para decidir si la siguiente llamada entrará.
Superar cualquiera de los dos límites devuelve 429. Reintenta con retroceso exponencial; el cliente de Python lo hace por defecto. Si el 429 responde a la cuota mensual, el reintento no ayuda: contacta con el equipo.
Los límites se comparten entre la API de facturación y la API de gestión.
Paginación
Un solo patrón en todos los listados: la petición acepta limite y cursor, y la respuesta devuelve proximaPagina (el cursor de la página siguiente, null cuando no hay más):
GET /v1/facturas?nifEmisor=B00000000&limite=100
GET /v1/facturas?nifEmisor=B00000000&limite=100&cursor=eyJQSyI6…
En los listados de facturación, limite es 100 por defecto y 500 como máximo. Pedir más del máximo no es un error: la respuesta se recorta a 500. Un limite no entero o menor que 1 sí lo es: 400 INVALID_PARAMETER, nombrando el parámetro. En los listados de la API de gestión, un limite inválido toma el valor por defecto en lugar de responder un error. El cursor es opaco: pásalo de vuelta tal cual en cursor, sin interpretarlo ni construirlo. Los cursores caducan; no los persistas entre sesiones.
Convenciones
- Formato: JSON en peticiones y respuestas,
Content-Type: application/json. La excepción: el XML firmado (application/xml). - Importes: cadenas decimales con dos decimales (
"121.00"). No se admiten números en coma flotante:121.0puede perder precisión al serializarse, y un importe descuadrado provoca el rechazo del registro. El formato lo fijan los esquemas de las administraciones: hasta 12 dígitos enteros, como máximo dos decimales y el punto como separador. La notación científica ("1e3"), la coma decimal ("1,00"), un tercer decimal y un valor no numérico responden400nombrando el campo. En las líneas de detalle de TicketBAI,cantidad,importeUnitario,descuentoeimporteTotaladmiten hasta ocho decimales. - Campos de texto: la API se encarga del escapado del XML, así que el texto viaja tal cual: sin entidades XML o HTML ya codificadas (
<,�,&…), que se rechazan con400en ambos sistemas por ser una doble codificación, y sin caracteres de control ilegales en XML. Un&suelto en un nombre es correcto. Los límites de longitud y las restricciones deserieynumerolos fija cada especificación. Ver VeriFactu y TicketBAI. - Fechas de factura:
dd-mm-aaaa("03-04-2026"), el formato de la normativa. Reglas completas (no-futuro, zona horaria, fecha de operación) en Fechas de la factura. - Marcas de tiempo generadas por la API:
AAAA-MM-DDTHH:MM:SSZ, en UTC y con segundos enteros, sin fracción ni desfase ("2026-09-27T10:00:00Z"). Mismo formato en las respuestas, en el cuerpo de los webhooks y en la cabeceraX-VeriBai-Timestamp(creadoEn,validadoEn,timestamp). Al tener ancho fijo, dos valores del mismo campo se comparan correctamente como texto. Los parámetros de consulta comoveredictoDesdeadmiten cualquier instante ISO 8601 con zona horaria. - Alta síncrona, remisión asíncrona: los endpoints de emisión devuelven
200con el registro validado, firmado y encolado; el resultado de la remisión se consulta en/estadoo llega por webhook. - Campos sin valor: un campo que no aplica o aún no tiene valor no aparece en la respuesta; no se envía como
null. Una cadena vacía ("") es un valor: por ejemplo,serieen una factura sin serie. Lee los campos opcionales contemplando que falten. Dos excepciones:proximaPagina, que valenullen la última página, ynombreCensoen la validación de NIF. - Campos nuevos: las respuestas y los eventos de webhook pueden incorporar campos nuevos sin previo aviso. Ignora los que no reconozcas.
- Avisos: el campo
avisos, cuando aparece, lista avisos de validación no bloqueantes. Revísalos: suelen anticipar rechazos futuros.
El campo idMaquina
Todos los endpoints de emisión y anulación aceptan un idMaquina opcional (máx. 64 caracteres, A-Za-z0-9._-): el identificador del dispositivo, TPV o proceso que originó la petición. Se conserva en el registro y se devuelve en /v1/registros (trazabilidad para tu propia observabilidad, sin efecto en el procesamiento).
Para emisores de gran volumen con muchos dispositivos existe un modo contratado, Alta capacidad, en el que
idMaquinadeja de ser metadato y pasa a encaminar una cadena de encadenado por dispositivo. Los dispositivos se dan de alta con/v1/clientes/{nif}/dispositivosy cada serie queda atada de forma permanente a un solo dispositivo. Si emites desde decenas de TPV con el mismo NIF, habla con el equipo.