VeriBaiDocs
Acceder

Documentos

Emitir la factura y obtener el PDF. VeriBai deriva el registro de las líneas comerciales, lo remite y devuelve el PDF con el QR.

La API admite dos formas de integrar:

  • Tu software genera la factura. Envía el registro con POST /v1/verifactu/crear o POST /v1/ticketbai/crear e imprime en tu plantilla el QR que devuelve la API.
  • VeriBai genera la factura. Envía las líneas comerciales con POST /v1/documentos/emitir. VeriBai deriva el registro, lo remite y devuelve el PDF terminado, con el QR.

Esta página documenta la segunda. Funciona con cualquier emisor dado de alta como cliente de tu cuenta, no solo con el NIF de la cuenta. El nombre y el domicilio fiscal del emisor que figuran en el PDF salen de su ficha de cliente en VeriBai: el cuerpo no lleva datos del emisor, solo nifEmisor. Base URL: https://sandbox.veribai.com (Sandbox) o https://api.veribai.com (LIVE). El sistema fiscal, VeriFactu o TicketBAI, y la provincia salen del emisor registrado: la ruta es la misma para los dos.

Método Endpoint Descripción
POST /v1/documentos/previsualizar Borrador del PDF. No registra nada ni consume número.
POST /v1/documentos/emitir Registra la factura y devuelve el PDF con el QR.
POST /v1/documentos/{idFactura}/reanudar Completa una emisión cuyo PDF no llegó a generarse.
GET /v1/documentos Listado de documentos emitidos de un emisor.
GET /v1/documentos/{idFactura} Detalle de un documento, con el PDF.

El cliente de Python todavía no incluye estas rutas. Los ejemplos muestran cURL y JavaScript.

El cuerpo: el documento comercial

previsualizar y emitir reciben el mismo cuerpo: la factura tal como la ve el destinatario, con precios unitarios y porcentajes. No reciben el registro. VeriBai calcula bases, cuotas, desglose y totales a partir de las líneas.

Campo Notas
nifEmisor Obligatorio. NIF del emisor.
serie Hasta 20 caracteres. No admite #, & ni '.
numero Opcional. Sin él, VeriBai asigna el siguiente número de la serie. Con él, se usa ese número. Hasta 20 caracteres.
fecha Obligatorio. Fecha de expedición, DD-MM-YYYY.
fechaVencimiento Opcional, DD-MM-YYYY. No puede ser anterior a fecha.
tipoFactura F1 (completa, por defecto) o F2 (simplificada). Para rectificar, anula y emite de nuevo.
destinatario Obligatorio en F1; no se admite en F2. nombre y uno de nif o idOtro (idType, id, codigoPais). Opcionales: email y direccion (calle, codigoPostal, municipio, provincia, pais, por defecto ES).
lineas Obligatorio, de 1 a 250. Ver la tabla siguiente.
retencionIrpf Opcional. Porcentaje de retención, hasta 2 decimales.
notas, condicionesPago, formaPago, iban Opcionales. Se imprimen en el PDF.

Cada línea:

Campo Notas
concepto Obligatorio. Hasta 250 caracteres.
referencia Opcional. Hasta 40 caracteres.
cantidad Por defecto "1". Distinta de cero, hasta 8 decimales.
precioUnitario Obligatorio. Precio sin IVA, hasta 8 decimales.
descuentoPct Opcional. Porcentaje de descuento de la línea, entre 0 y 100.
fiscal.operacion Obligatorio. VeriFactu: S1, S2, N1, N2, E1 a E8 (E7 y E8 solo con IGIC). TicketBAI: S1, S2, E1 a E6, OT, VT, RL, IE.
fiscal.tipoImpositivo Obligatorio con S1; no se admite con otra operación.
fiscal.clave Clave de régimen, dos dígitos. En TicketBAI, una factura admite hasta 3 claves distintas.
fiscal.impuesto Solo VeriFactu: 01 IVA, 02 IPSI, 03 IGIC, 05 Otros.
fiscal.tipoOperacion Solo TicketBAI: servicios o entrega.
fiscal.recargoTipo Opcional. Tipo del recargo de equivalencia, solo con S1.

Los importes y porcentajes viajan como cadenas. Un campo del otro sistema fiscal (por ejemplo, fiscal.impuesto en un emisor TicketBAI) o un campo del registro (desglose, totales) responde 400 VALIDATION_ERROR con el campo en campo.

POST /v1/documentos/previsualizar

Devuelve el PDF tal como quedará, con la marca de agua «BORRADOR · SIN VALIDEZ FISCAL». El QR aparece como un recuadro en su posición final, sin código. No registra nada ni consume número de la serie. Valida el cuerpo igual que emitir.

POST/v1/documentos/previsualizar

curl -X POST https://sandbox.veribai.com/v1/documentos/previsualizar \
  -H "x-api-key: TU_CLAVE" \
  -H "Content-Type: application/json" \
  -d '{
    "nifEmisor": "B00000000",
    "serie": "A2026",
    "numero": "00014",
    "fecha": "27-10-2026",
    "tipoFactura": "F1",
    "destinatario": {
      "nif": "B11111119",
      "nombre": "Cliente Ejemplo SL"
    },
    "lineas": [
      {
        "concepto": "Sesiones de entrenamiento personal",
        "cantidad": "5",
        "precioUnitario": "55.00",
        "descuentoPct": "10",
        "fiscal": {
          "impuesto": "01",
          "clave": "01",
          "operacion": "S1",
          "tipoImpositivo": "21"
        }
      }
    ],
    "retencionIrpf": "15"
  }'

Respuesta

200 OK
{
  "pdfBase64": "JVBERi0xLjQK…",
  "borrador": true,
  "resumen": {
    "subtotal": "247.50",
    "iva": "51.98",
    "recargo": "0.00",
    "total": "299.48",
    "cuotaTotal": "51.98",
    "baseIrpf": "247.50",
    "retencionIrpf": "37.13",
    "aPagar": "262.35",
    "numSerieFactura": "A202600014",
    "serie": "A2026",
    "numero": "00014",
    "sistemaFiscal": "verifactu",
    "variosTipos": false
  }
}

resumen trae los importes calculados. total incluye el IVA y el recargo y no descuenta la retención. aPagar es total menos retencionIrpf: solo figura en el PDF, no en el registro. variosTipos es true si las líneas usan más de un tipo impositivo.

POST /v1/documentos/emitir

Registra la factura y devuelve el PDF con el QR oficial. El registro se remite a la administración igual que una factura enviada con /crear: el estado final se consulta con GET /v1/facturas/{idFactura}/estado o por webhook.

POST/v1/documentos/emitir

curl -X POST https://sandbox.veribai.com/v1/documentos/emitir \
  -H "x-api-key: TU_CLAVE" \
  -H "Content-Type: application/json" \
  -d '{
    "nifEmisor": "B00000000",
    "serie": "A2026",
    "fecha": "27-10-2026",
    "fechaVencimiento": "26-11-2026",
    "tipoFactura": "F1",
    "destinatario": {
      "nif": "B11111119",
      "nombre": "Cliente Ejemplo SL",
      "email": "facturas@example.com",
      "direccion": {
        "calle": "Calle Mayor 1",
        "codigoPostal": "28013",
        "municipio": "Madrid",
        "provincia": "Madrid",
        "pais": "ES"
      }
    },
    "lineas": [
      {
        "referencia": "SRV-01",
        "concepto": "Sesiones de entrenamiento personal",
        "cantidad": "5",
        "precioUnitario": "55.00",
        "descuentoPct": "10",
        "fiscal": {
          "impuesto": "01",
          "clave": "01",
          "operacion": "S1",
          "tipoImpositivo": "21"
        }
      }
    ],
    "retencionIrpf": "15",
    "formaPago": "Transferencia",
    "iban": "ES9121000418450200051332"
  }'

Respuesta

200 OK
{
  "idFactura": "…",
  "nifEmisor": "B00000000",
  "numSerieFactura": "A202600014",
  "serie": "A2026",
  "numero": "00014",
  "sistemaFiscal": "verifactu",
  "estado": "emitida",
  "registro": {
    "estado": "pendiente_proceso",
    "urlValidacion": "https://…"
  },
  "pdfBase64": "JVBERi0xLjQK…"
}
Campo Notas
idFactura El identificador de la factura. Sirve para /v1/documentos/{idFactura} y para las rutas de /v1/facturas.
numero El número asignado. Sin numero en el cuerpo, el siguiente de la serie.
estado Estado del documento. Ver la tabla siguiente.
registro El registro remitido: estado de la remisión, urlValidacion (la URL que codifica el QR) y, en TicketBAI, idTbai. avisos si la validación detectó avisos no bloqueantes.
pdfBase64 El PDF en base64. Presente cuando estado es emitida.
yaExistente true cuando la petición repite una emisión anterior.
aviso Presente con estado: "pdf_pendiente".
estado Significado
emitida El registro está remitido y el PDF guardado. El PDF no cambia: repetir la emisión devuelve el mismo fichero con yaExistente: true.
pdf_pendiente Respuesta 200. La factura está registrada, pero el PDF no se generó. Llama a reanudar para obtenerlo.
pendiente Solo en el listado y el detalle. No consta si el registro llegó a crearse. reanudar lo resuelve.

Repeticiones y numeración

Repetir el mismo cuerpo (un doble clic, un reintento tras un tiempo de espera agotado) devuelve la misma factura, con el mismo idFactura y sin consumir otro número. Un cuerpo distinto con un número ya usado responde 409.

La numeración automática es propia de cada serie del emisor. Tiene en cuenta los números enteramente numéricos registrados en esa serie con /v1/verifactu/crear o /v1/ticketbai/crear. Un número alfanumérico no la mueve. Un numero explícito por delante del contador lo adelanta hasta ese número.

Una emisión rechazada no consume número: la serie no queda con huecos.

POST /v1/documentos/{idFactura}/reanudar

Completa una emisión en estado pendiente o pdf_pendiente. Si el registro ya existe, no lo remite de nuevo: genera y guarda el PDF. Se puede repetir sin efectos adicionales.

POST/v1/documentos/ID_FACTURA/reanudar

curl -X POST https://sandbox.veribai.com/v1/documentos/ID_FACTURA/reanudar \
  -H "x-api-key: TU_CLAVE" \
  -H "Content-Type: application/json" \
  -d '{
    "nifEmisor": "B00000000"
  }'

La respuesta tiene la forma de la de emitir: estado: "emitida" con pdfBase64, o pdf_pendiente con aviso si el PDF sigue sin generarse.

GET /v1/documentos

Los documentos emitidos de un emisor, del más reciente al más antiguo.

GET/v1/documentos?nifEmisor=B00000000&limite=50

curl "https://sandbox.veribai.com/v1/documentos?nifEmisor=B00000000&limite=50" \
  -H "x-api-key: TU_CLAVE"

Respuesta

200 OK
{
  "nifEmisor": "B00000000",
  "documentos": [
    {
      "idFactura": "…",
      "nifEmisor": "B00000000",
      "estado": "emitida",
      "serie": "A2026",
      "numero": "00014",
      "numSerieFactura": "A202600014",
      "fechaExpedicion": "27-10-2026",
      "tipoFactura": "F1",
      "sistemaFiscal": "verifactu",
      "destinatarioNif": "B11111119",
      "destinatarioNombre": "Cliente Ejemplo SL",
      "importeTotal": "299.48",
      "aPagar": "262.35",
      "creadoEn": "2026-10-27T10:00:00Z",
      "actualizadoEn": "2026-10-27T10:00:02Z",
      "pdfDisponible": true,
      "registro": {
        "estado": "pendiente_proceso",
        "urlValidacion": "https://…"
      }
    }
  ],
  "total": 1,
  "proximaPagina": "…"
}
Parámetro Notas
nifEmisor Obligatorio.
limite Opcional, por defecto 50, máximo 200.
cursor Opcional. Cursor de paginación: el proximaPagina de la página anterior.

proximaPagina no aparece en la última página. El listado no incluye el PDF. registro.estado es el estado de la remisión en el momento de la emisión; el estado actual está en /v1/facturas.

GET /v1/documentos/{idFactura}

Un documento, con los campos del listado. Con estado: "emitida", la respuesta incluye pdfBase64. Si el PDF no puede leerse, la respuesta trae pdfDisponible: false y no incluye pdfBase64. Requiere ?nifEmisor=. Un idFactura que no corresponde a un documento del emisor responde 404 NOT_FOUND.

GET/v1/documentos/ID_FACTURA?nifEmisor=B00000000

curl "https://sandbox.veribai.com/v1/documentos/ID_FACTURA?nifEmisor=B00000000" \
  -H "x-api-key: TU_CLAVE"

En GET /v1/facturas y en el detalle de una factura, documentoDisponible: true indica que la factura tiene un PDF guardado.

El PDF

  • Viaja en base64 dentro del JSON. Para obtener el fichero, decodifica pdfBase64.
  • Formato A4. El emisor figura en la cabecera. VeriBai no aparece en el documento.
  • VeriFactu: el QR, de 35 mm, va al principio de la factura, con «QR tributario:» encima y «VERI*FACTU» debajo.
  • TicketBAI: el identificador TBAI y el QR debajo, al final de la factura.
  • Las líneas muestran el precio unitario sin IVA y la base de cada línea. La tabla por tipo impositivo solo aparece con más de un tipo, y el bloque de retención, solo con retencionIrpf.
  • En Sandbox, el PDF lleva la marca de agua «TEST» y la nota «El código QR no tiene validez fiscal».
  • El PDF queda guardado y se descarga de nuevo con GET /v1/documentos/{idFactura}. En Sandbox se conserva 45 días, como el resto de datos de Sandbox.
curl -s -H "x-api-key: $KEY" \
  "https://sandbox.veribai.com/v1/documentos/$ID?nifEmisor=$NIF" \
  | jq -r .pdfBase64 | base64 -d > factura.pdf

Errores

Los errores siguen el formato común.

HTTP code Cuándo
400 VALIDATION_ERROR El cuerpo no supera la validación. errors enumera los fallos y campo nombra el primero. Incluye los campos del otro sistema fiscal y los del registro.
400 MISSING_PARAMETER Falta nifEmisor: en el cuerpo de un POST, en la consulta de un GET.
403 FORBIDDEN El emisor no pertenece a tu cuenta.
404 NOT_FOUND idFactura desconocido para ese emisor.
409 EMISOR_ADDRESS_MISSING previsualizar, emitir y reanudar: la ficha del emisor no tiene el domicilio fiscal completo (calle, numero, codigoPostal, ciudad, provincia). El cuerpo trae nifEmisor. No se registra nada ni se consume número. Completa la dirección con PATCH /v1/clientes/{nif} y repite la petición.
409 SERIE_EN_USO Otra emisión de la misma serie está en curso. Reintenta en unos segundos.
409 NUMERO_YA_UTILIZADO Ya consta una factura con esa serie, número y fecha, registrada con /crear. siguienteNumero trae el siguiente número libre.
409 DOCUMENTO_CONFLICTO Ese número ya se usó en /v1/documentos/emitir para un documento con otro contenido. siguienteNumero trae el siguiente número libre.
4xx Varios, con origen: "crear" La validación del registro rechazó la factura. El code, message y errors son los de /crear. No se registró nada: corrige y emite de nuevo.
502 EMISION_INCIERTA No consta si el registro llegó a crearse. El cuerpo trae idFactura. No emitas de nuevo: llama a reanudar con ese idFactura pasados unos segundos.

Un software, varias cuentas VeriBai

Un software puede emitir para varios emisores de dos formas:

  • Cada usuario final con su propia cuenta. Cada emisor abre su cuenta de VeriBai y introduce su clave API en tu software. Cada factura es autoemisión de esa cuenta.
  • Una cuenta con los emisores como clientes. Tu cuenta da de alta a cada emisor como cliente y emite para él. En LIVE, cada emisor necesita la representación firmada.

Con una cuenta por usuario final:

  • Guarda una clave por cliente, asociada a ese cliente. Una clave no se comparte entre clientes.
  • Cada clave pertenece a un entorno: Sandbox (sandbox.veribai.com) o LIVE (api.veribai.com). Comprueba cada clave al guardarla y al arrancar con GET /v1/cuenta: entorno indica el entorno y nifClientePrincipal, el NIF de la cuenta. Úsalos para identificar la clave.
  • La cuota mensual y el límite de peticiones son por clave: cada cliente consume los suyos.
  • Cada cliente rota y revoca su clave desde su panel. Tu software debe permitir que el cliente sustituya la clave sin un despliegue nuevo.

Series y destinatarios

La configuración de series (número siguiente, ancho del número) y la agenda de destinatarios se gestionan desde el panel. No tienen rutas con clave API.