---
title: "Create PDF/A"
url: https://recursiveai.org/onepdf/cookbook/create-pdf-a/
description: "Write PDF/A-2b and PDF/A-3u files in C# from documents made or edited with OnePDF, attach data to PDF/A-3, and check files from elsewhere first."
version: "1.11.0"
---

# Create PDF/A

Write PDF/A-2b and PDF/A-3u files in C# from documents made or edited with OnePDF, attach data to PDF/A-3, and check files from elsewhere first.

OnePDF writes PDF/A for documents it made or edited, and for existing files that already meet the requirements. It doesn’t convert arbitrary files: it embeds no fonts into content it didn’t create and rewrites no colors or transparency. A file that breaks a requirement is refused, with every violation listed, and nothing is written.

```sh
dotnet add package RecursiveAI.OnePdf --version 1.11.0
dotnet add package RecursiveAI.OnePdf.Layout --version 1.11.0
```

```csharp
using OnePdf;
using OnePdf.Layout;

// A new document, written straight to PDF/A-2b.
LayoutDocument minutes = LayoutDocument.Compose(doc =>
{
    doc.Title("Minutes, October meeting").Language("en-US");
    doc.Page(page =>
    {
        page.Margin(54);
        page.Content().Text("The committee approved the harbor trial report.");
    });
});
using (FileStream file = File.Create("minutes-pdfa.pdf"))
    minutes.Save(file, new PdfSaveOptions { PdfA = new PdfAOptions { Part = PdfAPart.Part2, Conformance = PdfAConformance.B } });

// A file OnePDF made earlier, as PDF/A-3u with its data attached.
using (PdfDocument doc = PdfDocument.Open("invoice.pdf", new PdfOpenOptions { AllowEditing = true }))
{
    doc.AttachFile("invoice.xml", File.ReadAllBytes("invoice.xml"),
        new PdfAttachmentOptions
        {
            MimeType = "text/xml",
            Relationship = PdfAttachmentRelationship.Data,
            ModificationDate = File.GetLastWriteTimeUtc("invoice.xml"),   // PDF/A-3 requires a date on every attachment
        });
    doc.Save("invoice-pdfa3.pdf", new PdfSaveOptions { PdfA = new PdfAOptions { Part = PdfAPart.Part3, Conformance = PdfAConformance.U } });
}

// A file from elsewhere: make the repairs OnePDF can make, then see what is still wrong before saving.
using (PdfDocument doc = PdfDocument.Open("of345.pdf", new PdfOpenOptions { AllowEditing = true }))
{
    var options = new PdfAOptions { Part = PdfAPart.Part2, Conformance = PdfAConformance.B };
    IReadOnlyList<PdfAViolation> problems = doc.PreparePdfA(options);
    if (problems.Count == 0)
    {
        doc.Save("of345-pdfa.pdf", new PdfSaveOptions { PdfA = options });
    }
    else
    {
        Console.WriteLine($"of345.pdf cannot be PDF/A-2b as it is: {problems.Count} violations, for example:");
        foreach (PdfAViolation v in problems.Take(4))
            Console.WriteLine($"  {v.Clause}: {v.Message} (object {v.ObjectNumber})");
    }
}
```

```text
of345.pdf cannot be PDF/A-2b as it is: 6 violations, for example:
  6.2.11.4.1: The font ZapfDingbats is not embedded. (object 20)
  6.2.11.4.1: The font Times-Roman is not embedded. (object 191)
  6.3.3: A button widget's /N must be a dictionary of appearance states. (object 188)
  6.4.1: A widget annotation has an /A or /AA entry. (object 188)
```

The veraPDF validator passes `minutes-pdfa.pdf` as PDF/A-2b and `invoice-pdfa3.pdf` as PDF/A-3u.

## What a PDF/A save does

A save with `PdfSaveOptions.PdfA` makes the repairs that need no judgement and then checks the result:

- adds an sRGB output intent with a color profile generated by OnePDF,
- writes the XMP metadata, taken from the document information so the two agree,
- embeds Liberation faces for standard fonts that OnePDF itself added (Helvetica, Times, Courier), when the `RecursiveAI.OnePdf.Fonts` package is registered,
- sets the print flag on annotations and generates missing form-field appearances,
- writes the header and file identifiers the standard asks for.

Parts 2 and 3 are supported, at levels B (the pages look the same everywhere), U (B, plus Unicode for all text) and A (U, plus tagged structure: see [Create PDF/UA](https://recursiveai.org/onepdf/cookbook/create-pdf-ua/)). OnePDF writes attachments only in PDF/A-3 files, and each needs a modification date: the sample sets one from the file.

## Good to know

- `PreparePdfA` makes the repairs in memory and returns what is still wrong. `CheckPdfA` only reports, and works on read-only documents. A save that fails throws `PdfAException` with the same list in `Violations`.
- OnePDF is not a validator. A clean check covers what OnePDF can verify from the file’s structure, not every rule of the standard. Run a validator such as veraPDF before you rely on a file.
- DeviceCMYK color is refused, because OnePDF’s output intent is RGB.
- An encrypted document needs `Encryption = PdfEncryptionAction.Remove` in the same save, since PDF/A forbids encryption.
- Existing signatures don’t survive a PDF/A save, which rewrites the file. Sign afterwards.
- A part of the file that can’t be read, such as a damaged font program, makes the save fail rather than leave the part out.

What is written, checked and not checked, clause by clause, is in [PDF/A](https://recursiveai.org/onepdf/docs/pdfa/).

A longer walk-through with PDF/A-3 XML attachments: [Create PDF/A in C#](https://recursiveai.org/onepdf/articles/create-pdf-a-csharp/).
