Simple Verifactu API

Simple Verifactu API actúa como intermediaria (patrón Facade) de la API de la AEAT. De esta forma, podrás cumplir con tus obligaciones sin pelearte con cadenas de registros, SOAPs o demás complejidades. A lo largo de la documentación, podrás ver que está diseñada por y para desarrolladores.

Toda nuestra API sigue los principios REST. Una URL por recurso y los verbos HTTP para definir las operaciones. Los cuerpos de las respuestas y las peticiones en formato JSON. Códigos de respuesta HTTP para describir el resultado de las peticiones.

Contamos con un entorno de pruebas con un funcionamiento idéntico a producción para facilitar el desarrollo de la integración.

URL base

https://api.simpleverifactuapi.com

Ejemplos de código en varios lenguajes

Inicio rápido

  1. 1. Puedes usar tu cuenta de Google para agilizar el proceso, aunque nosotros solo te pediremos email y contraseña.
  2. 2Añade tu NIF a través del dashboard.
  3. 3Copia las líneas de código del lenguaje que estés utilizando y registra tu primera factura.
  4. 4Actualiza el PDF de tu factura con el QR y la mención obligatoria. Te lo contamos en Generar PDF de factura.
  5. 5Redacta tu declaración responsable, el documento que acredita que tu software cumple el reglamento.

Siguientes pasos: registrar apoderamiento en la AEAT.

Registrar tu primera factura

POST/invoices/
curl -X POST \
  https://api.simpleverifactuapi.com/invoices/ \
  -H "Authorization: Bearer sk_test_xxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "invoice_number": "FAC-2024-001",
    "description": "Prestación de servicios de consultoría",
    "seller": { "nif": "B12345678", "name": "Mi Empresa S.L." },
    "customer": { "nif": "A87654321", "name": "Cliente S.A." },
    "expedition_date": "2024-01-15",
    "lines": [{ "base_amount": 100.00, "iva": 21 }]
  }'

Autenticación

Nuestra API usa API keys para autenticar las peticiones. Puedes ver y gestionar tus API keys en el Dashboard.

La API key de test tiene el prefijo sk_test_. Con ella, crearás facturas tanto en nuestro entorno de pruebas como en el de la AEAT. Para mayor comodidad, al registrarte, la tendrás insertada en las peticiones de la documentación.

La API key de producción tiene el prefijo sk_live_. Al generarla, se te mostrará una única vez. Cópiala y guárdala a buen recaudo. En caso de perderla, podrás generar una nueva en la sección de API keys del dashboard.

Header de autenticación

GET/invoices/
curl https://api.simpleverifactuapi.com/invoices/ \
  -H "Authorization: Bearer sk_test_xxxxxxxxxxxxxxxx"

Errores

Para las respuestas de error, se sigue el RFC 9457. Se usan los códigos de respuesta HTTP para indicar el éxito o fallo de las peticiones. Como Content-Type para los errores, usamosapplication/problem+json

Atributos del error

statusint

Código HTTP de la respuesta. Se añade también en el cuerpo para facilitar su lectura.

typestring

Código que identifica de forma estable el error. Es el que se debe usar si se quiere programar una respuesta automática ante el error.

titlestring

Descripción legible del error en lenguaje humano. Se puede usar para imprimir en los logs. No está pensado para devolverse directamente al usuario final.

invalid_paramsarray | null

Información de los campos erróneos. Solo en errores de validación.

namestring

Nombre del campo.

reasonstring

Mensaje de error.

Ejemplo respuesta de error

{
  "type": "/errors/validation-error",
  "title": "One or more fields failed validation.",
  "status": 400,
  "invalid_params": [
    {"name": "seller.nif", "reason": "NIF format is incorrect."},
    {"name": "expedition_date", "reason": "Expedition date cannot be in the future."}
  ]
}

Catálogo de tipos de error

Factura ya rectificada

400
/errors/invoice-already-rectified

Se intenta borrar (anular) una factura que ya se usó como base de una rectificativa.

Factura no rectificable

400
/errors/invoice-not-rectifiable

Se intenta rectificar una factura que ya está borrada o rectificada.

Tipo de rectificativa incorrecto

400
/errors/rectification-type-mismatch

Una factura simplificada solo puede rectificarse con otra simplificada, y una completa con otra completa. Manda customer (o no) igual que la factura que rectificas.

NIF emisor no autorizado

400
/errors/seller-nif-not-authorized

El seller_nif de la factura no está en los NIFs autorizados del usuario.

Número de factura duplicado

409
/errors/duplicate-invoice-number

Ya existe una factura con ese invoice_number para ese seller_nif.

NIF autorizado duplicado

409
/errors/duplicate-authorized-nif

Ese NIF ya está dado de alta en este entorno. Cada NIF solo puede registrarse una vez por entorno.

Factura rechazada por la AEAT

402
/errors/verifactu-invoice-rejected

La AEAT ha rechazado la factura por un dato incorrecto.

Error de validación

400
/errors/validation-error

Fallo de validación de algún campo; el detalle va en invalid_params.

Recurso no encontrado

404
/errors/not-found

El recurso solicitado no existe.

Permiso denegado

403
/errors/permission-denied

El usuario autenticado no tiene permiso para realizar esa acción.

No autenticado

401
/errors/not-authenticated

La petición no incluye API key.

Autenticación fallida

401
/errors/authentication-failed

La API key no es válida.

Método no permitido

405
/errors/method-not-allowed

Se ha usado un método HTTP no soportado en ese endpoint.

Límite de peticiones superado

429
/errors/throttled

Se ha superado el límite de peticiones (20 peticiones por segundo).

Petición malformada

400
/errors/parse-error

El cuerpo de la petición no se ha podido interpretar.

Tipo de contenido no soportado

415
/errors/unsupported-media-type

El Content-Type de la petición no está soportado.

Error interno

500
/errors/internal-server-error

Excepción no controlada (no debería ocurrir, pero ya sabes cómo funciona esto).

API Facturas

Las facturas representan los documentos registrados en Verifactu. Cada factura tiene un estado que refleja su ciclo de vida y, una vez registrada ante la AEAT, no puede modificarse directamente (restricciones de Hacienda).

En nuestra API, solo te pedimos la información mínima necesaria para cumplir con la AEAT, no los datos de la factura completa. Por lo tanto, no generamos el PDF resultante. Para saber cómo hacerlo, consulta la sección Generar PDF de factura.

Endpoints

GET
/invoices/

Lista las facturas del usuario autenticado.

GET
/invoices/{id}/

Obtiene una factura por su ID.

POST
/invoices/

Crea y registra una nueva factura.

DELETE
/invoices/{id}/

Anula una factura registrada.

El objeto Factura

Atributos

iduuid · read only

UUID único de la factura.

statusstring · read only

Posibles valores: created, deleted, rectified, pending_creation, pending_deletion, pending_nif_verification, errored_on_creation o errored_on_deletion.

invoice_numberstring

Número de la factura.

descriptionstring

Descripción de la operación facturada.

sellerobjeto

Emisor de la factura.

nifstring

NIF del emisor.

namestring

Nombre o razón social del emisor.

customerobjeto | null

Receptor de la factura. Es null en las facturas simplificadas.

nifstring

NIF del receptor.

namestring

Nombre o razón social del receptor.

expedition_datestring · YYYY-MM-DD

Fecha de expedición de la factura.

total_amountnumber · read only

Importe total (base + IVA).

base_amountnumber · read only

Base imponible total.

iva_amountnumber · read only

IVA total. Se calcula agregando los importes por tipo impositivo y resolviendo el reparto una vez sobre cada agregado, no línea a línea, que es como lo exige la AEAT.

qr_urlstring | null · read only

URL del QR de verificación de la AEAT. Es null mientras el alta no esté registrada (pending_creation, pending_nif_verification, errored_on_creation) y en las facturas anuladas: en esos casos la AEAT no encontraría la factura, así que no hay QR que pintar.

linesarray

Líneas de la factura, tal como se enviaron. Los dos campos de importe vienen siempre, con null en el que no se usó.

base_amountnumber | null · 2 decimales

Importe de la línea sin IVA. Es null si la línea se envió con total_amount.

total_amountnumber | null · 2 decimales

Importe de la línea con el IVA incluido. Es null si la línea se envió con base_amount.

ivainteger

Tipo de IVA aplicado. Valores posibles: 0, 4, 10, 21.

rectified_invoiceuuid | null

Si se quiere crear una factura rectificativa, hay que enviar el uuid de la factura a rectificar (la original).

El objeto Factura

{
  "id": "a1b2c3d4-...",
  "status": "created",
  "invoice_number": "FAC-2024-001",
  "description": "Prestación de servicios de consultoría",
  "seller": { "nif": "B12345678", "name": "Mi Empresa S.L." },
  "customer": { "nif": "A87654321", "name": "Cliente S.A." },
  "expedition_date": "2024-01-15",
  "total_amount": 121.00,
  "base_amount": 100.00,
  "iva_amount": 21.00,
  "qr_url": "https://www2.agenciatributaria.gob.es/...",
  "lines": [{ "base_amount": 100.00, "total_amount": null, "iva": 21 }],
  "rectified_invoice": null
}

Estados de la factura

EstadoDescripción
createdFactura creada y registrada.
deletedRegistrada la anulación.
rectifiedRectificada por otra factura.
pending_creation / pending_deletionEstado inicial tras la creación o el borrado. Se mantiene en este estado hasta que se consigue registrar en la AEAT. El primer intento será síncrono. Si no es posible registrar la factura, permanecerá en este estado hasta que se registre. Se reintentará periódicamente.
pending_nif_verificationSi se crea una factura pero aún no has registrado el apoderamiento en la AEAT, se crea en este estado. Se reintenta periódicamente.
errored_on_creation / errored_on_deletionSi, tras un reintento, una factura en estado pending_creation / pending_deletion falla, pasará a este estado.

Listar facturas

Devuelve un array con todas las facturas de la cuenta.

Parámetros de consulta

invoice_numberstring · opcional

Filtra por número de factura exacto.

seller_nifstring · opcional

Filtra por NIF del emisor exacto. Ojo: los filtros son planos, aunque en el cuerpo el emisor sea el objeto seller.

customer_nifstring · opcional

Filtra por NIF del receptor exacto. Las facturas simplificadas nunca aparecen aquí: no tienen receptor.

expedition_date_afterstring · opcional

Solo facturas expedidas en o después de esta fecha (YYYY-MM-DD).

expedition_date_beforestring · opcional

Solo facturas expedidas en o antes de esta fecha (YYYY-MM-DD).

statusstring · opcional

Filtra por estado. Valores posibles: created, deleted, rectified, pending_nif_verification, pending_creation, pending_deletion, errored_on_creation, errored_on_deletion.

Listar facturas

GET/invoices/
curl https://api.simpleverifactuapi.com/invoices/ \
  -H "Authorization: Bearer sk_test_xxxxxxxxxxxxxxxx"
Response
[
  {
    "id": "a1b2c3d4-...",
    "status": "created",
    "invoice_number": "FAC-2024-001",
    "description": "Prestación de servicios de consultoría",
    "seller": { "nif": "B12345678", "name": "Mi Empresa S.L." },
    "customer": { "nif": "A87654321", "name": "Cliente S.A." },
    "expedition_date": "2024-01-15",
    "total_amount": 121.00,
    "base_amount": 100.00,
    "iva_amount": 21.00,
    "qr_url": "https://www2.agenciatributaria.gob.es/...",
    "lines": [{ "base_amount": 100.00, "total_amount": null, "iva": 21 }],
    "rectified_invoice": null
  }
]

Leer una factura

Obtiene los detalles de una factura a partir de su id.

Devuelve 404 si la factura no existe o no pertenece a la cuenta autenticada.

Leer una factura

GET/invoices/{id}/
curl https://api.simpleverifactuapi.com/invoices/a1b2c3d4-.../ \
  -H "Authorization: Bearer sk_test_xxxxxxxxxxxxxxxx"
Response
{
  "id": "a1b2c3d4-...",
  "status": "created",
  "invoice_number": "FAC-2024-001",
  "description": "Prestación de servicios de consultoría",
  "seller": { "nif": "B12345678", "name": "Mi Empresa S.L." },
  "customer": { "nif": "A87654321", "name": "Cliente S.A." },
  "expedition_date": "2024-01-15",
  "total_amount": 121.00,
  "base_amount": 100.00,
  "iva_amount": 21.00,
  "qr_url": "https://www2.agenciatributaria.gob.es/...",
  "lines": [{ "base_amount": 100.00, "total_amount": null, "iva": 21 }],
  "rectified_invoice": null
}

Crear una factura

Crea una nueva factura.

El seller_nif debe estar autorizado en la cuenta. Consulta la sección NIFs Autorizados para más información.

Si el NIF autorizado tiene status=unverified, se registra como pending_nif_verification a la espera de que se complete el registro del apoderamiento en la AEAT. Una vez completado, la factura se enviará de forma automática a la AEAT y se actualizará su estado.

Para crear una factura simplificada (un ticket), omitir el campocustomer.

Cada línea lleva su importe en base_amount (sin IVA) o en total_amount(con el IVA incluido): exactamente uno de los dos, y el mismo en todas las líneas. Si fijas precios finales, usa total_amount.

Parámetros

invoice_numberstring · requerido

Número único de la factura (e.g. "FAC-2024-001").

descriptionstring · requerido

Descripción de la operación facturada (qué se ha vendido o qué servicio se ha prestado). Máximo 500 caracteres.

sellerobjeto · requerido

Emisor de la factura.

nifstring · requerido

NIF del emisor. Debe estar autorizado en la cuenta.

namestring · requerido

Nombre o razón social del emisor.

customerobjeto · opcional

Receptor de la factura. Omitirlo crea una factura simplificada (un ticket).

nifstring · requerido

NIF del receptor.

namestring · requerido

Nombre o razón social del receptor.

expedition_datestring · requerido

Fecha de expedición en formato ISO 8601 (YYYY-MM-DD). La fecha de expedición debe ser anterior a la fecha actual.

linesarray · requerido

Líneas de la factura. Cada línea lleva su importe en una de las dos convenciones — base_amount o total_amount — y **todas las líneas de una factura deben usar la misma**.

base_amountnumber · requiere uno de los dos

Importe de la línea sin IVA, con dos decimales. Úsalo si fijas precios sin IVA (e.g. "1.000 € + IVA"): preserva exacta la base.

total_amountnumber · requiere uno de los dos

Importe de la línea con el IVA incluido, con dos decimales. Úsalo si fijas precios finales (e.g. "un café, 1,50 €"): preserva exacto el total.

ivainteger · requerido

Tipo de IVA aplicado. Valores posibles: 0, 4, 10, 21.

rectified_invoiceuuid · opcional

UUID de la factura original que se rectifica con esta. Debe ser del mismo tipo: una simplificada solo se rectifica con otra simplificada.

Crear una factura

POST/invoices/
curl -X POST \
  https://api.simpleverifactuapi.com/invoices/ \
  -H "Authorization: Bearer sk_test_xxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "invoice_number": "FAC-2024-001",
    "description": "Prestación de servicios de consultoría",
    "seller": { "nif": "B12345678", "name": "Mi Empresa S.L." },
    "customer": { "nif": "A87654321", "name": "Cliente S.A." },
    "expedition_date": "2024-01-15",
    "lines": [{ "base_amount": 100.00, "iva": 21 }]
  }'
Response
{
  "id": "a1b2c3d4-...",
  "status": "created",
  "invoice_number": "FAC-2024-001",
  "description": "Prestación de servicios de consultoría",
  "seller": { "nif": "B12345678", "name": "Mi Empresa S.L." },
  "customer": { "nif": "A87654321", "name": "Cliente S.A." },
  "expedition_date": "2024-01-15",
  "total_amount": 121.00,
  "base_amount": 100.00,
  "iva_amount": 21.00,
  "qr_url": "https://www2.agenciatributaria.gob.es/...",
  "lines": [{ "base_amount": 100.00, "total_amount": null, "iva": 21 }],
  "rectified_invoice": null
}

Eliminar una factura

Anula una factura registrada.

Verifactu exige mantener todo el histórico de facturas. Por lo tanto, esta operación cambia el estado de la factura por deleted.

Si la factura aún estaba en pending_nif_verification y, por lo tanto, no se había registrado, sí se borra completamente.

Eliminar una factura

DELETE/invoices/{id}/
curl -X DELETE \
  https://api.simpleverifactuapi.com/invoices/a1b2c3d4-.../ \
  -H "Authorization: Bearer sk_test_xxxxxxxxxxxxxxxx"

Modificar una factura

Verifactu no permite editar directamente una factura ya registrada ante la AEAT. Para corregirla, tienes dos opciones:

Opción 1 — Factura rectificativa

Crea una nueva factura incluyendo el campo rectified_invoice con el id de la factura original. La nueva factura quedará vinculada a la original y ambas aparecerán como relacionadas en el sistema de la AEAT.

La rectificativa tiene que ser del mismo tipo que la original: una factura simplificada solo se rectifica con otra simplificada, y una completa con otra completa.

Es la opción habitual para correcciones de importe, datos del cliente o líneas de factura.

Creamos facturas rectificativas por sustitución. Es decir, los datos correctos son los que deben aparecer en la factura rectificativa. Creemos que es la opción más sencilla.

Para más información acerca de las facturas rectificativas, consultar la documentación al respecto de la AEAT.

Opción 2 — Anulación y reemisión

Anula la factura original con DELETE /invoices/{id}/ y emite una nueva con los datos correctos. Ambas operaciones se notifican a la AEAT de forma independiente.

En caso de que la primera opción de algún problema, siempre tenemos esta opción. Es más difícil que surja algún problema.

Factura rectificativa

POST/invoices/
curl -X POST \
  https://api.simpleverifactuapi.com/invoices/ \
  -H "Authorization: Bearer sk_test_xxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "invoice_number": "FAC-2024-002",
    "description": "Prestación de servicios de consultoría",
    "seller": { "nif": "B12345678", "name": "Mi Empresa S.L." },
    "customer": { "nif": "A87654321", "name": "Cliente S.A." },
    "expedition_date": "2024-01-20",
    "rectified_invoice": "a1b2c3d4-...",
    "lines": [{ "base_amount": 100.00, "iva": 21 }]
  }'
Response
{
  "id": "e5f6g7h8-...",
  "status": "created",
  "invoice_number": "FAC-2024-002",
  "description": "Prestación de servicios de consultoría",
  "seller": { "nif": "B12345678", "name": "Mi Empresa S.L." },
  "customer": { "nif": "A87654321", "name": "Cliente S.A." },
  "expedition_date": "2024-01-20",
  "total_amount": 121.00,
  "base_amount": 100.00,
  "iva_amount": 21.00,
  "qr_url": "https://www2.agenciatributaria.gob.es/...",
  "lines": [{ "base_amount": 100.00, "total_amount": null, "iva": 21 }],
  "rectified_invoice": "a1b2c3d4-..."
}

API NIFs Autorizados

Los NIFs autorizados son aquellos para los cuales nos has dado permisos para emitir facturas en su nombre. Para ello, deberás completar un pequeño formulario en Hacienda. Para más info, ve a la sección Registrar apoderamiento en la AEAT de la documentación.

Si solo vas a emitir facturas en tu nombre o de tu empresa, lo más sencillo es que añadas los NIFs a través del dashboard.

En caso de que necesites emitir facturas de un gran número de NIFs, dejamos a tu disposición esta API para que automatices el proceso (aunque la persona a la que pertenece el NIF tendrá que registrar el apoderamiento igualmente).

Endpoints

GET
/authorized-nifs/

Lista los NIFs autorizados del usuario.

GET
/authorized-nifs/{id}/

Obtiene un NIF autorizado.

POST
/authorized-nifs/

Crea un nuevo NIF.

DELETE
/authorized-nifs/{id}/

Elimina un NIF autorizado.

El objeto NIF Autorizado

Atributos

iduuid · read only

UUID único del NIF autorizado.

nifstring

El NIF del que nos vas a autorizar para emitir facturas.

statusstring · read only

Estado del NIF autorizado: verified o unverified.

El objeto NIF Autorizado

{
  "id": "a1b2c3d4-...",
  "nif": "B12345678",
  "status": "verified"
}

Estados del NIF autorizado

EstadoDescripción
unverifiedPermanecerá en este estado hasta que registres el apoderamiento en la AEAT y crees una factura de forma exitosa para ese seller_nif.
verifiedEstado terminal. Se ha comprobado que tenemos poderes para emitir facturas para este NIF.

Listar NIFs autorizados

Devuelve un array con todos los NIFs autorizados registrados en la cuenta.

Parámetros de consulta

nifstring · opcional

Filtra por NIF exacto.

statusstring · opcional

Filtra por estado. Valores posibles: unverified, verified.

Listar NIFs autorizados

GET/authorized-nifs/
curl https://api.simpleverifactuapi.com/authorized-nifs/ \
  -H "Authorization: Bearer sk_test_xxxxxxxxxxxxxxxx"
Response
[{ "id": "a1b2c3d4-...", "nif": "B12345678", "status": "verified" }]

Leer un NIF autorizado

Devuelve los datos de un NIF autorizado concreto.

Leer un NIF autorizado

GET/authorized-nifs/{id}/
curl https://api.simpleverifactuapi.com/authorized-nifs/a1b2c3d4-.../ \
  -H "Authorization: Bearer sk_test_xxxxxxxxxxxxxxxx"
Response
{
  "id": "a1b2c3d4-...",
  "nif": "B12345678",
  "status": "verified"
}

Crear un NIF

Registra un nuevo NIF en la cuenta. El NIF quedará en estado unverified hasta que la persona titular haya registrado el apoderamiento en la AEAT.

Parámetros

nifstring · requerido

NIF español válido a autorizar.

Crear un NIF

POST/authorized-nifs/
curl -X POST \
  https://api.simpleverifactuapi.com/authorized-nifs/ \
  -H "Authorization: Bearer sk_test_xxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{"nif": "B12345678"}'
Response
{ "id": "a1b2c3d4-...", "nif": "B12345678", "status": "unverified" }

Eliminar un NIF

Elimina un NIF autorizado de la cuenta.

Devuelve 204 No Content en caso de éxito, sin cuerpo de respuesta.

Eliminar un NIF

DELETE/authorized-nifs/{id}/
curl -X DELETE \
  https://api.simpleverifactuapi.com/authorized-nifs/a1b2c3d4-.../ \
  -H "Authorization: Bearer sk_test_xxxxxxxxxxxxxxxx"

Entorno de pruebas

Este entorno es una réplica idéntica del de producción. Está pensado para ser usado desde los entornos de desarrollo, pudiendo comprobar fácilmente la integración.

Para alternar entre el entorno de pruebas y el de producción, se usan las API keys. Si usas la de test (sk_test_…), todas las peticiones que hagas serán contra este entorno.

Hemos replicado también la página de verificación de las facturas. De esta forma, podréis comprobar el funcionamiento de qr_url.

El dashboard también es idéntico entre entornos. Así sabréis qué esperar en los casos reales. Para alternar entre uno y otro, tendréis un botón en la parte superior.

Captura del entorno de pruebas

Registrar apoderamiento en la AEAT

Por restricciones legales, para registrar facturas en tu nombre, necesitamos que registres un apoderamiento en la AEAT. Si quieres registrar facturas de NIFs de terceros (e.g. en un Marketplace), cada persona tendrá que habernos apoderado para emitir facturas en su nombre.

A pesar de ser un trámite con Hacienda, es bastante sencillo:

  1. 1Accede a la página de Hacienda de gestión de apoderamientos.
  2. 2Selecciona la opción “Alta de poder mediante identificación electrónica” e inicia sesión con tu método preferido (Cl@ve, certificado digital, etc).
  3. 3Aquí te recomendamos seleccionar “Alta de apoderamiento para trámites tributarios específicos” para darnos los poderes justos.
  4. 4Rellena el formulario con los siguientes campos:
    • NIF del Apoderado: 12425734F¡Copiado!
    • Fecha fin de la autorización: ¡Copiado! (El máximo permitido son 5 años. Tranquilo, te avisaremos con tiempo para renovarlo.)
    • Apoderamiento por absorbente: No
    • Permisos: Para encontrarlos mejor, te recomendamos seleccionar la opción “Visualizar los trámites en modo árbol” que encontrarás en la parte superior del formulario. Después, seleccionar los permisos de Verifactu que encontrarás en: Impuestos, tasas y prestaciones patrimoniales > IVA > SISTEMAS INFORMATICOS DE FACTURACION Y VERI*FACTU.
  5. 5¡Firma y comienza a almacenar facturas!
Paso 1 del apoderamiento en la AEAT
Paso 2 del apoderamiento en la AEAT
Paso 3 del apoderamiento en la AEAT

Generar PDF de factura

Nosotros no generamos el PDF de factura. Para aumentar la simplicidad, hemos preferido pedirte solo la información necesaria para registrar la factura en la AEAT, lo que nos impide crearla. Hemos pensado que la mayoría de vosotros estará adaptando sus facturas existentes.

Para cumplir con la AEAT, tienes que añadir a tus facturas dos cosas nuevas:

  • Generar un QR (una imagen, no la URL en texto) a partir del campo qr_url que te devolvemos. Este deberá ir al inicio de la factura con un tamaño de 30 × 30 o 40 × 40 mm.
  • Añadir la frase “Factura verificable en la sede electrónica de la AEAT”.

Para más información, te dejamos el enlace a la normativa y a las FAQs de la AEAT.

Si aún no tienes un software de facturación, te dejamos una plantilla de factura completa en HTML y un ejemplo de código de cómo rellenarla.

Rellenar la plantilla de factura

POST/invoices/
# 1. Registra la factura en Simple Verifactu API (solo los datos que exige la AEAT)
curl -X POST \
  https://api.simpleverifactuapi.com/invoices/ \
  -H "Authorization: Bearer sk_test_xxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "invoice_number": "FAC-2024-001",
    "description": "Prestación de servicios de consultoría",
    "seller": { "nif": "B12345678", "name": "Mi Empresa S.L." },
    "customer": { "nif": "A87654321", "name": "Cliente S.A." },
    "expedition_date": "2024-01-15",
    "lines": [{ "base_amount": 100.00, "iva": 21 }]
  }' > respuesta.json

QR_URL=$(jq -r '.qr_url' respuesta.json)

# 2. Generamos el QR de verdad a partir de "qr_url" (con qrencode)
qrencode -o qr.png "$QR_URL"
QR_DATA_URI="data:image/png;base64,$(base64 -w0 qr.png)"

# 3. Descarga la plantilla renderizable y rellénala con los datos + el QR
curl -O https://tu-dominio.example/plantilla-factura.html

sed -e "s|{{SELLER_NAME}}|Mi Empresa S.L.|g" \
    -e "s|{{SELLER_NIF}}|B12345678|g" \
    -e "s|{{BUYER_NAME}}|Cliente S.A.|g" \
    -e "s|{{BUYER_NIF}}|A87654321|g" \
    -e "s|{{INVOICE_NUMBER}}|FAC-2024-001|g" \
    -e "s|{{ISSUE_DATE}}|2024-01-15|g" \
    -e "s|{{QR_URL}}|$QR_URL|g" \
    -e "s|{{QR_CODE}}|<img src=\"$QR_DATA_URI\">|g" \
    plantilla-factura.html > factura-completa.html

# Nota: para campos con caracteres especiales (direcciones, líneas de
# factura...) usa un lenguaje con templating real; sed no escala bien.

Redactar la declaración responsable

Es un documento legal más, al estilo de los términos y condiciones o la política de privacidad: un texto público en el que se declara que tu software cumple el reglamento. Si has desarrollado el tuyo, tienes que redactar la tuya.

Al lado tienes lo que exige la AEAT, sus ejemplos oficiales y el nuestro por si te sirve de guía.

Si te surge cualquier duda, escríbenos por el formulario de contacto.

¿Qué es Veri*factu?

Normativa que regula cómo debe funcionar todo software que genere alguna factura. Hay que cumplir con las siguientes obligaciones:

  1. 1Informar a la AEAT de cada factura en el momento de emitirla, junto con otros requisitos técnicos (registros encadenados, inalterables y trazables).
  2. 2Añadir a la factura un código QR y la frase “Factura verificable en la sede electrónica de la AEAT”.
  3. 3Tener una declaración responsable: otro documento legal, como los términos y condiciones o la política de privacidad, en el que se declara que el software cumple el reglamento. Cómo redactar la tuya.

Resumen divulgativo, no asesoramiento fiscal.

Veri*factu de un vistazo

ConceptoResumen
Desde cuándo1 de enero de 2027 (sociedades) y 1 de julio de 2027 (el resto).
Dónde aplicaTerritorio común. País Vasco y Navarra tienen normativa foral propia (TicketBAI).
NormativaLey 11/2021 (antifraude), RD 1007/2023 y Orden HAC/1177/2024.

Cuándo entra en vigor

El calendario se ha aplazado dos veces, así que circulan bastantes fechas antiguas por internet. El vigente lo fija el Real Decreto-ley 15/2025, de 2 de diciembre, publicado en el BOE el 3 de diciembre de 2025:

  • 1 de enero de 2027 para los contribuyentes del Impuesto sobre Sociedades.
  • 1 de julio de 2027 para el resto: autónomos y profesionales en IRPF, IRNR con establecimiento permanente y entidades en atribución de rentas.

Calendario

  1. Julio 2021

    Ley 11/2021, antifraude

    Crea la obligación y su régimen sancionador.

  2. Diciembre 2023

    Real Decreto 1007/2023

    Aprueba el reglamento con los requisitos técnicos.

  3. 1 enero 2027

    Obligatorio · Impuesto sobre Sociedades

  4. 1 julio 2027

    Obligatorio · resto de obligados

Quién tiene la obligación

Cualquier software que cobre por un producto o servicio. Resumiendo: si estás integrado con Stripe, te toca.

Da igual que cobres a empresas o a particulares, y da igual el importe.

Están obligados

  • SaaS de suscripción. Cada cobro recurrente es una factura. Estilo Netflix.
  • Productos de pago por uso. Una factura por cada periodo de consumo. Estilo Claude Code.
  • Marketplaces. Estilo Amazon o Airbnb: hay que registrar las facturas de las transacciones que ocurren dentro.

Qué hay que hacer para cumplirlo

Por cada factura hay que generar un registro y hacérselo llegar a la AEAT. Lo que hay que construir para eso:

  • Registros inalterables. Nada se edita ni se borra: corregir una factura es añadir un registro nuevo que apunta al anterior.
  • Conservarlos accesibles y legibles. El reglamento no fija años: remite al plazo de la Ley General Tributaria, que va de un mínimo de cuatro a más de diez según el caso. Los registros que la AEAT ya ha aceptado los guarda ella.
  • Encadenarlos con una huella. Cada registro lleva un SHA-256 calculado sobre sus datos y sobre la huella del anterior. Como una blockchain: si uno cambia o desaparece, los siguientes dejan de cuadrar.
  • Firmar los envíos con certificado electrónico, el tuyo o el de la empresa, y tenerlo instalado allí donde corra el proceso.
  • Integrarte con la API SOAP de la AEAT: XML contra su WSDL, con sus esquemas, sus códigos de error y sus entornos.
  • Montar una cola de salida. La AEAT no quiere una llamada por factura: hay que ir acumulando los registros pendientes y mandarlos agrupados, en lotes de hasta 1.000. Esa cola tiene que ser persistente y reintentar sola, porque una factura ya emitida no puede quedarse sin enviar.
  • Enviar al ritmo que te marquen. En cada respuesta, la AEAT te devuelve los segundos que debes esperar antes del siguiente lote. Ese valor manda: si envías antes, te rechaza el lote.

Todo eso es lo que hay detrás del POST /invoices/. Lo que sigue siendo tuyo es la factura en sí: el QR y la mención en el documento que entregas al cliente, explicados en Generar PDF de factura.

Requisitos técnicos (nuestra parte)

ConceptoValor
ProtocoloServicio web SOAP, mensajes XML, respuesta síncrona.
HuellaSHA-256 sobre los datos del registro y la huella del anterior.
Tamaño del loteHasta 1.000 registros por envío.
Ritmo de envíoEl que indique la AEAT en cada respuesta.
AutenticaciónCertificado electrónico del obligado o de quien le represente.
ConservaciónEl plazo de la LGT: mínimo cuatro años, más en algunos supuestos.

Requisitos documentales (tu parte)

RequisitoDónde va
Código QREn la factura, al inicio y de 30×30 o 40×40 mm. Ver Generar PDF de factura.
MenciónLa frase “Factura verificable en la sede electrónica de la AEAT”, junto al QR.
Declaración responsablePublicada y accesible. Ver Redactar la declaración responsable.

Sanciones

Tres supuestos, tres importes:

  • 1.000 €. Vender un software adaptado pero sin declaración responsable. Se cuenta por cada copia comercializada.
  • 50.000 €. Usar un software que genera facturas en nuestro nombre sin declaración responsable. La paga quien factura, no quien lo desarrolló, y se cuenta por cada ejercicio.
  • 150.000 €. Desarrollar o vender un software que no cumple. Por cada ejercicio con ventas y por cada producto distinto.

Nada de esto es exigible hasta que llegue tu fecha de obligación.

Cómo no comerte ninguna

  • Si te animas a desarrollarlo por tu cuenta, asegurate de cumplir todos los requisitos. No dudes en escribirnos si te surge alguna duda sobre cómo implementarlo.
  • Comprueba que el software con el que facturas tiene declaración responsable y guárdate una copia.
  • No te olvides de publicar tu declaración responsable. Te contamos cómo en Redactar la declaración responsable.

Las cuantías son fijas, no porcentajes: aplican igual a una multinacional que a un autónomo. Texto del artículo.