PDF/A-3 para Facturae, TicketBAI y LOPDGDD: Archivo Fiscal con IronPDF en C
En el mercado español, PDF/A no es simplemente un formato de archivo genérico: es el contenedor técnico que hace posible la factura electrónica híbrida. La Ley Crea y Crece exige que las facturas B2B y los documentos enviados a FACe (Punto General de Entrada de Facturas de la Administración) conserven tanto la representación visual como los datos estructurados dentro de un único fichero. El estándar que lo resuelve es PDF/A-3b con XML embebido.
IronPDF soporta la exportación a PDF/A-3b y PDF/A-4, los dos estándares activos de la serie ISO 19005, y proporciona la clase EmbedFileConfiguration para configurar los metadatos XMP de los archivos embebidos según las especificaciones de Facturae, TicketBAI y el reglamento LOPDGDD auditado por la AEPD.
Inicio rápido: Generar un PDF/A-3b con IronPDF en C#
-
Instala IronPDF con el Administrador de Paquetes NuGet
PM > Install-Package IronPdf -
Copie y ejecute este fragmento de código.
// Load existing PDF or render from HTML var document = IronPdf.PdfDocument.FromFile("invoice.pdf"); // Save as PDF/A-3b compliant archival document document.SaveAsPdfA3B("invoice-pdfa3b.pdf"); -
Despliegue para probar en su entorno real
Comienza a usar IronPDF en tu proyecto hoy mismo con una prueba gratuita
Flujo de trabajo mínimo (4 pasos)
- Descargue IronPDF para crear documentos PDF/A en C#
- Cargar PDF existente o renderizar desde plantilla HTML de factura
- Configurar
EmbedFileConfigurationpara Facturae XML o TicketBAI XML - Guardar como PDF/A-3b con el XML embebido mediante
SaveAsPdfA3B
Tres escenarios normativos donde PDF/A-3 es obligatorio en España
1. Facturae 3.2.2 embebido en PDF/A-3b para FACe (B2G)
La Administración española acepta facturas electrónicas a través del portal FACe bajo el estándar Facturae 3.2.2. La especificación técnica de FACe permite el envío como factura híbrida: el XML Facturae se embebe dentro de un PDF/A-3b, de modo que el fichero contiene simultáneamente la representación visual y los datos estructurados para procesamiento automático. Este patrón es el mismo que usan Factur-X (Francia) y ZUGFeRD (Alemania).
La norma europea EN 16931 y su implementación española CIUS-ES, promovidas por la ley Crea y Crece, definen el modelo de datos semántico del XML embebido.
var config = new EmbedFileConfiguration
{
EmbedFileName = "factura-2026-001.xml",
AFDesc = "Facturae 3.2.2 XML embebido",
ConformanceLevel = ConformanceLevel.EN16931,
SchemaNamespace = SchemaNamespace.facturX,
SchemaPrefix = SchemaPrefix.fx,
PropertyVersion = PropertyVersion.v1,
AFRelationship = AFRelationship.Alternative
};
var document = PdfDocument.FromFile("factura-visual.pdf");
document.EmbedFileFromFilePath("factura-2026-001.xml", config);
document.SaveAsPdfA3B("factura-face-hibrida.pdf");
var config = new EmbedFileConfiguration
{
EmbedFileName = "factura-2026-001.xml",
AFDesc = "Facturae 3.2.2 XML embebido",
ConformanceLevel = ConformanceLevel.EN16931,
SchemaNamespace = SchemaNamespace.facturX,
SchemaPrefix = SchemaPrefix.fx,
PropertyVersion = PropertyVersion.v1,
AFRelationship = AFRelationship.Alternative
};
var document = PdfDocument.FromFile("factura-visual.pdf");
document.EmbedFileFromFilePath("factura-2026-001.xml", config);
document.SaveAsPdfA3B("factura-face-hibrida.pdf");
Dim config As New EmbedFileConfiguration With {
.EmbedFileName = "factura-2026-001.xml",
.AFDesc = "Facturae 3.2.2 XML embebido",
.ConformanceLevel = ConformanceLevel.EN16931,
.SchemaNamespace = SchemaNamespace.facturX,
.SchemaPrefix = SchemaPrefix.fx,
.PropertyVersion = PropertyVersion.v1,
.AFRelationship = AFRelationship.Alternative
}
Dim document = PdfDocument.FromFile("factura-visual.pdf")
document.EmbedFileFromFilePath("factura-2026-001.xml", config)
document.SaveAsPdfA3B("factura-face-hibrida.pdf")
Los campos de EmbedFileConfiguration relevantes para Facturae/FACe:
ConformanceLevel.EN16931— identifica el perfil semántico del XML ante los validadores de la AdministraciónSchemaNamespace.facturX— URI del espacio de nombres compatible con los portales B2G españolesAFRelationship.Alternative— declara el XML como representación alternativa del documento (requerido por FACe)
2. TicketBAI XML embebido en PDF/A-3b (País Vasco)
Las tres haciendas forales del País Vasco tienen implementaciones distintas de TicketBAI con requisitos de archivo específicos:
- Bizkaia (programa BATUZ, portal
bizkaia.eus): los PDFs que acompañan a los registros TicketBAI deben conservarse durante el período de prescripción fiscal. PDF/A-3b garantiza la integridad del documento para inspecciones de la Diputación. - Gipuzkoa (
gipuzkoa.eus): exige archivado de los documentos asociados al registro TicketBAI firmado con XAdES. - Araba (
araba.eus): misma arquitectura base, con su propio endpoint de validación y requisitos de retención.
Para estos casos, el XML TicketBAI firmado se embebe en el PDF/A-3b usando la misma clase EmbedFileConfiguration con AFRelationship.Source para indicar que el XML es el documento fuente de la representación visual.
3. Retención LOPDGDD: 5–7 años con integridad garantizada
La LOPDGDD (Ley Orgánica de Protección de Datos y Garantía de Derechos Digitales), auditada por la AEPD, exige que los documentos con datos personales se conserven en formatos que garanticen su reproducibilidad exacta durante el período de retención aplicable:
- 4 años para facturas (IVA)
- 6 años para documentos del Impuesto de Sociedades
- El período específico que establezca la normativa sectorial
PDF/A cumple este requisito porque incrusta fuentes, perfiles de color y metadatos completos en el propio fichero, eliminando cualquier dependencia de software externo para la reproducción fiel del documento en el futuro.
Verificar la conformidad PDF/A con veraPDF
La herramienta de referencia para validar documentos PDF/A es veraPDF, el validador de código abierto recomendado por la ISO. Tras generar el PDF/A con IronPDF, valide el fichero para confirmar su conformidad antes de enviar a FACe o archivar bajo LOPDGDD.

:path=/static-assets/pdf/content-code-examples/how-to/pdfa-fromfile.cs
using IronPdf;
// Create a PdfDocument object or open any PDF File
PdfDocument pdf = PdfDocument.FromFile("wikipedia.pdf");
// Use the SaveAsPdfA method to save to file
pdf.SaveAsPdfA("pdf-a3-wikipedia.pdf", PdfAVersions.PdfA3b);
Imports IronPdf
' Create a PdfDocument object or open any PDF File
Private pdf As PdfDocument = PdfDocument.FromFile("wikipedia.pdf")
' Use the SaveAsPdfA method to save to file
pdf.SaveAsPdfA("pdf-a3-wikipedia.pdf", PdfAVersions.PdfA3b)
El fichero de entrada antes de la conversión:
El fichero de salida validado como PDF/A-3b:
Generar PDF/A-3b desde plantillas HTML de factura
Para sistemas de facturación que generan facturas a partir de plantillas HTML, IronPDF permite convertir directamente el HTML renderizado a PDF/A-3b sin pasos intermedios. Este es el flujo habitual en ISVs que construyen software de facturación para el mercado español:
:path=/static-assets/pdf/content-code-examples/how-to/pdfa-fromhtml.cs
using IronPdf;
// Use the Chrome Renderer to make beautiful HTML designs
var chromeRenderer = new ChromePdfRenderer();
// Render an HTML design as a PdfDocument object using Chrome
PdfDocument pdf = chromeRenderer.RenderHtmlAsPdf("design.html");
// Use the SaveAsPdfA method to save to file
pdf.SaveAsPdfA("design-accessible.pdf", PdfAVersions.PdfA3b);
Imports IronPdf
' Use the Chrome Renderer to make beautiful HTML designs
Private chromeRenderer = New ChromePdfRenderer()
' Render an HTML design as a PdfDocument object using Chrome
Private pdf As PdfDocument = chromeRenderer.RenderHtmlAsPdf("design.html")
' Use the SaveAsPdfA method to save to file
pdf.SaveAsPdfA("design-accessible.pdf", PdfAVersions.PdfA3b)
Verificación de conformidad del fichero generado desde HTML:

¿Qué versiones de PDF/A soporta IronPDF?
IronPDF es compatible con los niveles de conformidad A y B de PDF/A-1, PDF/A-2, PDF/A-3 y PDF/A-4. La salida predeterminada es PDF/A-3B (ISO 19005-3).
| Estándar | Archivos adjuntos | Firmas digitales | Caso de uso principal en España |
|---|---|---|---|
| PDF/A-1 | No | Limitado | Archivo histórico sin XML embebido |
| PDF/A-2 | No | Soportado | Documentos firmados sin XML embebido |
| PDF/A-3 | Sí (XML, CSV…) | Soportado | Facturae para FACe, XML TicketBAI, LOPDGDD |
| PDF/A-4 | No | Soporte mejorado | Expedientes técnicos, documentación de ingeniería |
Incrustar archivos adicionales en PDF/A-3b
IronPDF ofrece tres métodos para incrustar archivos durante la conversión a PDF/A-3b: por ruta de archivo, por matriz de bytes o mediante stream. Los tres métodos son equivalentes funcionalmente; el más adecuado depende de cómo el sistema de facturación gestiona el XML de Facturae o TicketBAI en memoria.
Método 1: incrustar por ruta de archivo
:path=/static-assets/pdf/content-code-examples/how-to/pdfa-attachment-path.cs
using IronPdf;
using System.Collections.Generic;
PdfDocument pdf = new PdfDocument("Google.pdf");
// Initialize collection of embed file as string of path
IEnumerable<string> embedPaths = new[] { "File1.xml", "File2.png" };
// Convert to Pdf/A-3B with embeded files
pdf.ConvertToPdfA(embedPaths);
Imports IronPdf
Imports System.Collections.Generic
Private pdf As New PdfDocument("Google.pdf")
' Initialize collection of embed file as string of path
Private embedPaths As IEnumerable(Of String) = { "File1.xml", "File2.png" }
' Convert to Pdf/A-3B with embeded files
pdf.ConvertToPdfA(embedPaths)
Método 2: incrustar por matriz de bytes
Útil cuando el XML está ya en memoria (generado por la biblioteca de facturación):
:path=/static-assets/pdf/content-code-examples/how-to/pdfa-attachment-byte.cs
using IronPdf;
using System.Collections.Generic;
using System.IO;
PdfDocument pdf = new PdfDocument("Google.pdf");
// Initialize collection of embed file as Bytes and their file type
byte[] fileData1 = File.ReadAllBytes("File1.png");
byte[] fileData2 = File.ReadAllBytes("File2.xml");
var embedFileConfig1 = new EmbedFileConfiguration(EmbedFileType.png);
embedFileConfig1.EmbedFileName = "logo.png";
var embedFileConfig2 = new EmbedFileConfiguration(EmbedFileType.xml)
{
EmbedFileName = "supportSystem.xml",
AFDesc = "Internal system",
ConformanceLevel = ConformanceLevel.XRECHNUNG,
SchemaNamespace = SchemaNamespace.Zugferd1,
SchemaPrefix = SchemaPrefix.rsm,
PropertyVersion = PropertyVersion.v1p0,
AFRelationship = AFRelationship.Supplement,
};
IEnumerable<EmbedFileByte> embedBytes = new[]
{
new EmbedFileByte(fileData1, embedFileConfig1),
new EmbedFileByte(fileData2, embedFileConfig2)
};
// Convert to Pdf/A-3B with embeded files
pdf.ConvertToPdfA(embedBytes).SaveAs("PdfACompliance.pdf");
Imports IronPdf
Imports System.Collections.Generic
Imports System.IO
Private pdf As New PdfDocument("Google.pdf")
' Initialize collection of embed file as Bytes and their file type
Private fileData1() As Byte = File.ReadAllBytes("File1.png")
Private fileData2() As Byte = File.ReadAllBytes("File2.xml")
Private embedFileConfig1 = New EmbedFileConfiguration(EmbedFileType.png)
embedFileConfig1.EmbedFileName = "logo.png"
Dim embedFileConfig2 = New EmbedFileConfiguration(EmbedFileType.xml) With {
.EmbedFileName = "supportSystem.xml",
.AFDesc = "Internal system",
.ConformanceLevel = ConformanceLevel.XRECHNUNG,
.SchemaNamespace = SchemaNamespace.Zugferd1,
.SchemaPrefix = SchemaPrefix.rsm,
.PropertyVersion = PropertyVersion.v1p0,
.AFRelationship = AFRelationship.Supplement
}
Dim embedBytes As IEnumerable(Of EmbedFileByte) = {
New EmbedFileByte(fileData1, embedFileConfig1),
New EmbedFileByte(fileData2, embedFileConfig2)
}
' Convert to Pdf/A-3B with embeded files
pdf.ConvertToPdfA(embedBytes).SaveAs("PdfACompliance.pdf")
Método 3: incrustar mediante stream
Ideal para pipelines de procesamiento de facturas en tiempo real:
:path=/static-assets/pdf/content-code-examples/how-to/pdfa-attachment-stream.cs
using IronPdf;
using System.Collections.Generic;
using System.IO;
PdfDocument pdf = new PdfDocument("Google.pdf");
// Initialize collection of embed file as Stream and their file type
Stream stream1 = new MemoryStream(File.ReadAllBytes("File1.png"));
Stream stream2 = new MemoryStream(File.ReadAllBytes("File2.xml"));
var embedFileConfig1 = new EmbedFileConfiguration(EmbedFileType.png);
embedFileConfig1.EmbedFileName = "logo.png";
var embedFileConfig2 = new EmbedFileConfiguration(EmbedFileType.xml)
{
EmbedFileName = "supportSystem.xml",
AFDesc = "Internal system",
ConformanceLevel = ConformanceLevel.XRECHNUNG,
SchemaNamespace = SchemaNamespace.Zugferd1,
SchemaPrefix = SchemaPrefix.rsm,
PropertyVersion = PropertyVersion.v1p0,
AFRelationship = AFRelationship.Supplement,
};
IEnumerable<EmbedFileStream> embedStreams = new[]
{
new EmbedFileStream(stream1, embedFileConfig1),
new EmbedFileStream(stream2, embedFileConfig2)
};
// Convert to Pdf/A-3B with embeded files
pdf.ConvertToPdfA(embedStreams).SaveAs("PdfACompliance.pdf");
Imports IronPdf
Imports System.Collections.Generic
Imports System.IO
Private pdf As New PdfDocument("Google.pdf")
' Initialize collection of embed file as Stream and their file type
Private stream1 As Stream = New MemoryStream(File.ReadAllBytes("File1.png"))
Private stream2 As Stream = New MemoryStream(File.ReadAllBytes("File2.xml"))
Private embedFileConfig1 = New EmbedFileConfiguration(EmbedFileType.png)
embedFileConfig1.EmbedFileName = "logo.png"
Dim embedFileConfig2 = New EmbedFileConfiguration(EmbedFileType.xml) With {
.EmbedFileName = "supportSystem.xml",
.AFDesc = "Internal system",
.ConformanceLevel = ConformanceLevel.XRECHNUNG,
.SchemaNamespace = SchemaNamespace.Zugferd1,
.SchemaPrefix = SchemaPrefix.rsm,
.PropertyVersion = PropertyVersion.v1p0,
.AFRelationship = AFRelationship.Supplement
}
Dim embedStreams As IEnumerable(Of EmbedFileStream) = {
New EmbedFileStream(stream1, embedFileConfig1),
New EmbedFileStream(stream2, embedFileConfig2)
}
' Convert to Pdf/A-3B with embeded files
pdf.ConvertToPdfA(embedStreams).SaveAs("PdfACompliance.pdf")
PDF/A-4 y la leyenda VERI*FACTU en documentos VeriFactu
PDF/A-4 es el estándar más reciente (basado en PDF 2.0), con soporte mejorado para firmas digitales cualificadas. Su uso en España se orienta a documentos que requieren firma eIDAS de nivel alto o a expedientes técnicos de larga duración.
Para los ISVs que desarrollan software de facturación certificado bajo VeriFactu (Real Decreto-Ley 15/2025, con entrada en vigor escalonada en 2027), el PDF de la factura que acompaña al registro VeriFactu debe incluir la leyenda obligatoria VERI*FACTU —preservando el asterisco— y la referencia Factura verificable en la sede electrónica de la AEAT. IronPDF no es por sí mismo un sistema de facturación certificado VeriFactu: actúa como componente de generación de PDFs dentro del software de facturación certificado del ISV.
:path=/static-assets/pdf/content-code-examples/how-to/save-as-pdfa4.cs
using IronPdf;
// Load the environmental impact assessment document
PdfDocument pdf = PdfDocument.FromFile("ENV-2026-1847-Assessment-Report.pdf");
// Save as PDF/A-4 compliant document for long-term archival
pdf.SaveAsPdfA("ENV-2026-1847-Report-PDFA4Compliant.pdf", PdfAVersions.PdfA4);
Imports IronPdf
' Load the environmental impact assessment document
Dim pdf As PdfDocument = PdfDocument.FromFile("ENV-2026-1847-Assessment-Report.pdf")
' Save as PDF/A-4 compliant document for long-term archival
pdf.SaveAsPdfA("ENV-2026-1847-Report-PDFA4Compliant.pdf", PdfAVersions.PdfA4)
Verificación del documento PDF/A-4:

Problemas de visualización de caracteres en documentos PDF/A en español
PDF/A exige que todos los caracteres del documento se correspondan con una fuente visual y semánticamente correcta. Para documentos fiscales en español con el juego de caracteres Latin-1 extendido (á, é, í, ó, ú, ü, ñ, ¿, ¡, €), es imprescindible que la fuente utilizada incluya soporte completo para estos glifos. En servidores Linux o Docker, donde la codificación del sistema operativo puede diferir de Windows, asegúrese de instalar fuentes con soporte Latin-1 completo para evitar caracteres rotos en los PDFs generados.

¿Listo para profundizar? Consulte nuestra guía completa: Crear PDFs en C#
Preguntas Frecuentes
¿Cómo embebo el XML de Facturae 3.2.2 en un PDF/A-3b para enviarlo a FACe?
Con IronPDF, configure EmbedFileConfiguration con ConformanceLevel.EN16931 y SchemaNamespace.facturX. Cargue el PDF visual, llame a EmbedFileFromFilePath con la ruta al XML de Facturae y guarde con SaveAsPdfA3B. El fichero resultante contiene tanto la representación visual como los datos estructurados en un único contenedor PDF/A-3b compatible con FACe.
¿Qué diferencia hay entre PDF/A-3b y PDF/A-4 para facturación en España?
PDF/A-3b es el estándar para facturas híbridas en España: permite embeber XML (Facturae, TicketBAI) y es compatible con FACe y los portales forales del País Vasco. PDF/A-4 ofrece mejor soporte para firmas digitales eIDAS cualificadas pero no admite archivos adjuntos embebidos, por lo que no sirve para el patrón de factura híbrida requerido por Crea y Crece.
¿Cómo cumplo la LOPDGDD usando PDF/A para retención de documentos?
PDF/A incrusta fuentes, perfiles de color y metadatos en el propio fichero, garantizando la reproducibilidad exacta durante el período de retención requerido por la LOPDGDD (4 años para IVA, 6 años para Impuesto de Sociedades). La AEPD exige que los documentos con datos personales se conserven en formatos que garanticen la integridad a largo plazo, requisito que PDF/A cumple por diseño.
¿Pueden los ISVs usar IronPDF como sistema de facturación certificado para VeriFactu?
No. IronPDF es un componente de generación de PDFs que se usa DENTRO de software de facturación certificado. El software de facturación certificado para VeriFactu (Real Decreto-Ley 15/2025) es responsabilidad del ISV. IronPDF genera los PDFs que acompañan los registros VeriFactu, incluyendo la leyenda obligatoria VERI*FACTU, pero no gestiona el envío a la AEAT ni la cadena de huellas.
¿Cómo incrustar el XML TicketBAI de Bizkaia, Gipuzkoa o Araba en un PDF/A-3b?
Use EmbedFileConfiguration con AFRelationship.Source para indicar que el XML es la fuente del PDF. Cada hacienda foral tiene especificaciones técnicas propias: Bizkaia (BATUZ), Gipuzkoa y Araba aceptan el patrón de factura híbrida PDF/A-3b. IronPDF proporciona los tres métodos de incrustación (ruta, byte array, stream) para adaptarse al flujo del sistema de facturación del ISV.

