Introducción
De la cuenta al primer registro de facturación en el entorno Sandbox, paso a paso.
VeriBai es una API REST para el cumplimiento de VeriFactu y TicketBAI. Tu software envía los datos de la factura en JSON; VeriBai valida, firma, encadena y remite el registro a la administración que corresponda, y devuelve el código QR listo para incrustar.
Esta página te lleva de cero a tu primer registro en el entorno Sandbox.
1. Crea tu cuenta
Regístrate en app.veribai.com/registro. La cuenta incluye acceso completo al entorno Sandbox, sin coste.
2. Obtén tu clave API
Desde el panel, en Claves API, genera una clave para el entorno Sandbox. Las claves se envían en la cabecera x-api-key de cada petición. Más detalle en Autenticación.
3. Emite tu primera factura
Para la primera prueba, usaremos una factura simplificada (F2): es el tipo de factura más sencilla, ya que no lleva destinatario. La factura completa (F1) añade ese bloque; el contrato campo a campo lo puedes encontrar en las guías de VeriFactu y TicketBAI.
El sistema (VeriFactu o TicketBAI) lo define el endpoint al que envías la petición POST. En el siguiente ejemplo, un emisor de territorio común factura usando VeriFactu:
curl -X POST https://sandbox.veribai.com/v1/verifactu/crear \
-H "x-api-key: TU_CLAVE" \
-H "Content-Type: application/json" \
-d '{
"version": "1.0",
"cabecera": {
"serie": "A",
"numero": "12345",
"fechaExpedicion": "03-04-2026",
"tipoFactura": "F2",
"descripcion": "Descripcion de la factura"
},
"emisor": {
"nif": "B00000000",
"nombre": "Prueba 1 SL"
},
"detalleDesglose": [
{
"impuesto": "01",
"claveRegimen": "01",
"calificacionOperacion": "S1",
"baseImponible": "100.00",
"tipoImpositivo": "21.00",
"cuotaRepercutida": "21.00"
}
],
"totales": {
"cuotaTotal": "21.00",
"importeTotal": "121.00"
}
}'
from datetime import date
from decimal import Decimal
import veribai
client = veribai.Client(api_key="TU_CLAVE", environment="test")
respuesta = client.verifactu.crear({
"version": "1.0",
"cabecera": {
"serie": "A",
"numero": "12345",
"fechaExpedicion": date(2026, 4, 3),
"tipoFactura": "F2",
"descripcion": "Descripcion de la factura",
},
"emisor": {
"nif": "B00000000",
"nombre": "Prueba 1 SL",
},
"detalleDesglose": [
{
"impuesto": "01",
"claveRegimen": "01",
"calificacionOperacion": "S1",
"baseImponible": Decimal("100.00"),
"tipoImpositivo": Decimal("21.00"),
"cuotaRepercutida": Decimal("21.00"),
},
],
"totales": {
"cuotaTotal": Decimal("21.00"),
"importeTotal": Decimal("121.00"),
},
})
print(respuesta["idFactura"], respuesta["estado"])
const respuesta = await fetch("https://sandbox.veribai.com/v1/verifactu/crear", {
method: "POST",
headers: {
"x-api-key": "TU_CLAVE",
"Content-Type": "application/json",
},
body: JSON.stringify({
"version": "1.0",
"cabecera": {
"serie": "A",
"numero": "12345",
"fechaExpedicion": "03-04-2026",
"tipoFactura": "F2",
"descripcion": "Descripcion de la factura"
},
"emisor": {
"nif": "B00000000",
"nombre": "Prueba 1 SL"
},
"detalleDesglose": [
{
"impuesto": "01",
"claveRegimen": "01",
"calificacionOperacion": "S1",
"baseImponible": "100.00",
"tipoImpositivo": "21.00",
"cuotaRepercutida": "21.00"
}
],
"totales": {
"cuotaTotal": "21.00",
"importeTotal": "121.00"
}
}),
});
if (!respuesta.ok) throw new Error(`VeriBai ${respuesta.status}`);
const datos = await respuesta.json();
B00000000 es un NIF de ejemplo: sustitúyelo por el NIF real del emisor que hayas dado de alta. La AEAT no admite NIF con el número todo ceros.
En el caso del País Vasco, el emisor factura usando el sistema TicketBAI. En este caso, hay que añadir el campo provincia y podemos detallar también el desglose de los elementos de la factura en desglose:
curl -X POST https://sandbox.veribai.com/v1/ticketbai/crear \
-H "x-api-key: TU_CLAVE" \
-H "Content-Type: application/json" \
-d '{
"version": "1.0",
"provincia": "bizkaia",
"serie": "A",
"numero": "12345",
"fechaExpedicion": "03-04-2026",
"tipoFactura": "F2",
"descripcion": "Descripcion de la factura",
"emisor": {
"nif": "B00000000",
"nombre": "Prueba 1 SL"
},
"desglose": [
{
"baseImponible": "100.00",
"tipoImpositivo": "21.00",
"cuota": "21.00"
}
],
"importeTotal": "121.00"
}'
from datetime import date
from decimal import Decimal
import veribai
client = veribai.Client(api_key="TU_CLAVE", environment="test")
respuesta = client.ticketbai.crear({
"version": "1.0",
"provincia": "bizkaia",
"serie": "A",
"numero": "12345",
"fechaExpedicion": date(2026, 4, 3),
"tipoFactura": "F2",
"descripcion": "Descripcion de la factura",
"emisor": {
"nif": "B00000000",
"nombre": "Prueba 1 SL",
},
"desglose": [
{
"baseImponible": Decimal("100.00"),
"tipoImpositivo": Decimal("21.00"),
"cuota": Decimal("21.00"),
},
],
"importeTotal": Decimal("121.00"),
})
print(respuesta["idTbai"], respuesta["urlValidacion"])
const respuesta = await fetch("https://sandbox.veribai.com/v1/ticketbai/crear", {
method: "POST",
headers: {
"x-api-key": "TU_CLAVE",
"Content-Type": "application/json",
},
body: JSON.stringify({
"version": "1.0",
"provincia": "bizkaia",
"serie": "A",
"numero": "12345",
"fechaExpedicion": "03-04-2026",
"tipoFactura": "F2",
"descripcion": "Descripcion de la factura",
"emisor": {
"nif": "B00000000",
"nombre": "Prueba 1 SL"
},
"desglose": [
{
"baseImponible": "100.00",
"tipoImpositivo": "21.00",
"cuota": "21.00"
}
],
"importeTotal": "121.00"
}),
});
if (!respuesta.ok) throw new Error(`VeriBai ${respuesta.status}`);
const datos = await respuesta.json();
La pestaña de Python usa el cliente oficial:
pip install veribai
Acepta Decimal y date y los serializa en el formato que exige la API. Rechaza float: la representación binaria puede desviar una cuota un céntimo. Entornos, reintentos y el resto del paquete, en Cliente de Python.
Las pestañas de cURL y JavaScript muestran la petición HTTP tal cual.
La respuesta llega en el momento, con el QR generado. En VeriFactu:
{
"estado": "pendiente_proceso",
"numSerieFactura": "A12345",
"serie": "A",
"numero": "12345",
"tipoFactura": "F2",
"importeTotal": "121.00",
"urlValidacion": "https://…",
"qrBase64": "iVBORw0KG…"
}
En TicketBAI, la firma y el encadenado se completan en el alta, y la respuesta incluye el identificador TBAI:
{
"estado": "en_cola",
"idTbai": "TBAI-B00000000-…",
"numSerieFactura": "A12345",
"serie": "A",
"numero": "12345",
"tipoFactura": "F2",
"importeTotal": "121.00",
"urlValidacion": "https://…",
"qrBase64": "iVBORw0KG…"
}
El envío a la administración es asíncrono: la petición valida, firma y encola el registro, y la remisión se completa en segundo plano. Consulta el estado final con
GET /v1/facturas/{idFactura}/estado.
4. Siguientes pasos
- Autenticación: claves API y entornos.
- Crear factura (VeriFactu): el contrato completo, campo a campo.
- Crear factura (TicketBAI): la variante foral, con
provincia. - ¿VeriFactu o TicketBAI?: qué sistema aplica a cada emisor.
- Endpoints: el mapa completo de la API, con la referencia de cada endpoint.