FormaTeX

\begin{article}

Using All Four LaTeX Engines via the FormaTeX API

Practical code examples for pdfLaTeX, XeLaTeX, LuaLaTeX, and latexmk via the FormaTeX REST API — when to use each engine and how to call them.

·5 min read·
Using All Four LaTeX Engines via the FormaTeX API

The FormaTeX API supports all four LaTeX engines. Each produces a PDF but serves different document requirements — custom fonts, Lua scripting, bibliography management, or maximum speed and compatibility. This guide walks through a concrete API call for each engine with example documents that demonstrate their unique capabilities.

When to Pick Each Engine

Before reaching for the API, choose your engine:

I needEngine
Standard document, fastest compilationpdflatex
Custom OpenType fontsxelatex
Non-Latin scripts (Arabic, CJK, Hebrew)xelatex
Lua scripting inside the documentlualatex
Bibliography (BibTeX, Biber)latexmk
Cross-references, index, glossarylatexmk
Maximum package compatibilitypdflatex

pdfLaTeX API Call

The default engine — fastest, widest compatibility:

bash
curl -X POST https://api.formatex.io/api/v1/compile \
  -H "X-API-Key: $FORMATEX_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "engine": "pdflatex",
    "content": "\\documentclass{article}\\usepackage[utf8]{inputenc}\\usepackage{amsmath}\\begin{document}\\section{Introduction}The Pythagorean theorem: $a^2 + b^2 = c^2$.\\end{document}"
  }' \
  --output pdflatex-output.pdf

pdfLaTeX requires \usepackage[utf8]{inputenc} for UTF-8 source files. Math typesetting works out of the box with amsmath.

XeLaTeX with fontspec

XeLaTeX's key feature is native OpenType font loading:

latex
\documentclass{article}
\usepackage{fontspec}
\setmainfont{TeX Gyre Termes}      % Times New Roman compatible
\setsansfont{TeX Gyre Heros}       % Helvetica compatible
\setmonofont{JetBrains Mono}       % any system monospace font

\begin{document}
\section{Custom Fonts}
This document uses OpenType fonts directly via fontspec.
No encoding packages needed — XeLaTeX handles Unicode natively.

\textbf{Bold}, \textit{italic}, and \texttt{monospace} all
render with proper OpenType features including ligatures.

Arabic: \textrm{مرحبا} \quad Hebrew: \textrm{שלום}
\end{document}
bash
curl -X POST https://api.formatex.io/api/v1/compile \
  -H "X-API-Key: $FORMATEX_KEY" \
  -H "Content-Type: application/json" \
  -d "{\"engine\": \"xelatex\", \"content\": $(cat xelatex-doc.tex | jq -Rs .)}" \
  --output xelatex-output.pdf

Never mix \usepackage[utf8]{inputenc} with XeLaTeX. XeLaTeX handles UTF-8 natively and the inputenc package will cause a conflict error. Remove it entirely when using XeLaTeX or LuaLaTeX.

LuaLaTeX with Lua Scripting

LuaLaTeX embeds a full Lua 5.3 interpreter — use it for programmatic content generation:

latex
\documentclass{article}
\usepackage{fontspec}
\usepackage{luacode}

\begin{document}

\section{Lua-Generated Content}

The following multiplication table was generated by Lua code
running inside the LaTeX document:

\begin{center}
\begin{tabular}{r|rrrrr}
$\times$ & 1 & 2 & 3 & 4 & 5 \\
\hline
\directlua{
  for i = 1, 5 do
    tex.sprint(i)
    for j = 1, 5 do
      tex.sprint(" & " .. (i * j))
    end
    tex.sprint(" \\\\")
  end
}
\end{tabular}
\end{center}

\section{Dynamic Text}

\directlua{
  local words = {"alpha", "beta", "gamma", "delta"}
  for i, w in ipairs(words) do
    tex.sprint(i .. ". " .. w:upper() .. " ")
  end
}

\end{document}
bash
curl -X POST https://api.formatex.io/api/v1/compile \
  -H "X-API-Key: $FORMATEX_KEY" \
  -H "Content-Type: application/json" \
  -d "{\"engine\": \"lualatex\", \"content\": $(cat lualatex-doc.tex | jq -Rs .)}" \
  --output lualatex-output.pdf

latexmk for Bibliography

latexmk handles the multi-pass compilation sequence that bibliography requires:

latex
\documentclass{article}
\usepackage{amsmath}
\usepackage[backend=bibtex]{biblatex}

% Embed the .bib inline for single-file API calls
\begin{filecontents*}{refs.bib}
@book{knuth1984tex,
  author    = {Knuth, Donald E.},
  title     = {The {\TeX} Book},
  publisher = {Addison-Wesley},
  year      = {1984}
}
@article{lamport1994latex,
  author  = {Lamport, Leslie},
  title   = {{\LaTeX}: A Document Preparation System},
  year    = {1994},
  publisher = {Addison-Wesley}
}
\end{filecontents*}

\addbibresource{refs.bib}

\begin{document}

\section{Introduction}

TeX was created by \textcite{knuth1984tex} to produce
high-quality mathematical typography. \LaTeX{} \cite{lamport1994latex}
provides a higher-level document preparation system on top of TeX.

\printbibliography

\end{document}
bash
curl -X POST https://api.formatex.io/api/v1/compile \
  -H "X-API-Key: $FORMATEX_KEY" \
  -H "Content-Type: application/json" \
  -d "{\"engine\": \"latexmk\", \"content\": $(cat bibliography-doc.tex | jq -Rs .)}" \
  --output bibliography-output.pdf

Engine Selection Logic in Code

A TypeScript utility that picks the right engine based on document analysis:

typescript
type Engine = "pdflatex" | "xelatex" | "lualatex" | "latexmk";

function detectEngine(latexSource: string): Engine {
  // Bibliography → must use latexmk
  if (/\\bibliography\{|\\addbibresource\{/.test(latexSource)) {
    return "latexmk";
  }

  // Lua code → lualatex
  if (/\\begin\{luacode\}|\\directlua\{/.test(latexSource)) {
    return "lualatex";
  }

  // fontspec → xelatex (or lualatex, but xelatex is faster without Lua)
  if (/\\usepackage\{fontspec\}/.test(latexSource)) {
    return "xelatex";
  }

  // Default: pdflatex — fastest, widest compatibility
  return "pdflatex";
}

async function compileWithAutoEngine(latexSource: string): Promise<Buffer> {
  const engine = detectEngine(latexSource);

  const response = await fetch("https://api.formatex.io/api/v1/compile", {
    method: "POST",
    headers: {
      "X-API-Key": process.env.FORMATEX_KEY!,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ content: latexSource, engine }),
  });

  if (!response.ok) {
    const error = await response.json();
    throw new Error(`[${engine}] ${error.log ?? error.error}`);
  }

  return Buffer.from(await response.arrayBuffer());
}

pdflatex is available on the free plan. XeLaTeX, LuaLaTeX, and latexmk require Pro plan or above. Check your plan in the dashboard before using advanced engines.

Plan Requirements by Engine

EngineFreeProMaxEnterprise
pdflatexYesYesYesYes
xelatexNoYesYesYes
lualatexNoYesYesYes
latexmkNoYesYesYes

Get Started

\end{article}

Back to blog

\related{posts}

One quick thing

We track anonymous usage — page views, feature usage, compilation events — to understand what works and what doesn't. No ads, no personal data, no third-party sharing.

Cookie policy