Clients

C# client

Install the C# client, render a PDF from .NET in a child process or through brevier serve, and handle errors. Needs .NET 8 or newer.

On this page

Community

The C# client calls the Brevier engine from .NET. You pass HTML and data, and you get the PDF back. It needs .NET 8 or newer. The engine does the layout, so you write no PDF drawing code.

There are two modes:

Mode How the client reaches the engine Use it for
Child process It starts the brevier command for each render. Development, scripts and batch jobs
Serve mode It calls a running brevier serve over HTTP. Production and many renders

Install the engine

The engine is the brevier command. Child process mode starts it, so it must be on the PATH of the machine that runs your .NET code:

pip install brevier

Other ways to install it are on the Installation page.

Get a trial key

Every render needs a licence key, also for testing. Get the key before the first render.

  1. Request a free 30-day trial key on the pricing page. It arrives by email.
  2. Set the BREVIER_LICENCE_KEY environment variable:
Linux and macOS
export BREVIER_LICENCE_KEY="<your-licence-key>"
Windows PowerShell
$env:BREVIER_LICENCE_KEY = "<your-licence-key>"

The engine reads the key from its environment. The client passes your environment on to the child process. In serve mode, set the key in the shell that starts brevier serve.

Add the client

dotnet add package Brevier

Child process

This program renders a PDF from an HTML string and a dictionary:

Hello.cs
using Brevier;

byte[] pdf = await Pdf.Builder()
    .WithHtml("<h1>Hello {{ name }}</h1>")
    .WithData(new Dictionary<string, string> { ["name"] = "World" })
    .ToBytesAsync();

await File.WriteAllBytesAsync("hello.pdf", pdf);

Run it with dotnet run. The folder now has hello.pdf.

  • WithHtml and WithCss take the layout as text. WithHtmlFileAsync and WithCssFileAsync read it from a file.
  • WithData takes any C# object. WithJson takes JSON text.
  • ToBytesAsync returns the PDF. ToFileAsync writes it to a path.

Serve mode

In serve mode the engine runs as a service, and your code asks it for a PDF by the name of a template. A template is a folder with a file of the same name:

templates/hello/hello.html
<!DOCTYPE html>
<html lang="en">
<body>
  <h1>Hello {{ name }}</h1>
</body>
</html>

Start the server in the folder that holds templates:

brevier serve --templates templates

The server listens on 127.0.0.1:8080. It has no TLS and no login, so put a gateway in front of it before you expose it. Then render the template from C#:

HelloServe.cs
using Brevier;

byte[] pdf = await new TemplateBuilder("hello", new ConnectOptions { Url = "http://127.0.0.1:8080" })
    .With("name", "World")
    .RenderAsync();

await File.WriteAllBytesAsync("hello.pdf", pdf);
  • With(name, value) sets one root of the template. With(dictionary) sets several.
  • Rows(list) sets the rows of a table.
  • RenderAsync(objects) binds each object to the root of its type.
  • Without a URL, the client reads the environment variable BREVIER_URL. Without that, it starts brevier serve --stdio as a child process. It reads the templates folder of the working directory and reuses the process.

How do I render many PDFs at once?

Pdf.Batch() renders every HTML file of a folder, and its subfolders, into one PDF each. All files get the same CSS. The batch passes no data: each file must already be the finished page, for example from your own template engine.

Batch.cs
using Brevier;

var batch = await Pdf.Batch().WithInput("letters", "*.html").WithCssFileAsync("company.css");
var written = await batch.WithOutput("out").ToFilesAsync();

foreach (var file in written)
{
    Console.WriteLine(file);
}

With letters/2026-001.html and letters/2026-002.html, the program prints one line per PDF it wrote, in the order it found the files:

Output
out/2026-001.pdf
out/2026-002.pdf

For one PDF per record of your data, call Pdf.Builder() in a loop instead. A subfolder of letters comes back as the same subfolder of out. When one file fails, ToFilesAsync stops with a BrevierException.

How do I send the PDF from a web endpoint?

Render to bytes and return them as a file with the content type application/pdf. In an ASP.NET Core minimal API:

Program.cs
app.MapGet("/invoices/{id}/pdf", async (string id) =>
{
    byte[] pdf = await new TemplateBuilder("rechnung").RenderAsync(await invoices.FindAsync(id));
    return Results.File(pdf, "application/pdf", $"rechnung-{id}.pdf");
});

invoices is your own data access. Set BREVIER_URL on the server, and every render goes to your running brevier serve. The code does not change.

How do I get HTML instead of a PDF?

Html.Builder() takes the same calls as Pdf.Builder() and returns HTML. Use it to show the document in a web portal, or to compare it in a test:

byte[] html = await Html.Builder()
    .WithHtml("<h1>Hello {{ name }}</h1>")
    .WithData(new Dictionary<string, string> { ["name"] = "World" })
    .ToBytesAsync();

The class names of this HTML stay stable between releases. Output and tests shows how to use it in a snapshot test.

Replace a JasperReports or Word call

If your service fills a JasperReports report or a Word file today, import the template first. Then replace the call in two steps.

Step 1 keeps your dictionary of data and passes the rows:

return new TemplateBuilder("kontoauszug").With(data).Rows(buchungen).Render();

Step 2 passes your objects. The client binds each object to the root of its type.

return new TemplateBuilder("kontoauszug").Render(konto, kunde, buchungen);

Errors

The client throws a BrevierException. It has Code, the error code of the engine such as DATA_ERROR, and Path, the place in the data where the problem is. The message never holds a value from your data.