Product and API guide

Assets

Uploading an asset

Logos, signatures and fonts are uploaded once and then referenced by id. The request is multipart; the file goes in a field named file, and altText is optional.

Request
curl -X POST https://api.pdfgine.com/api/v1/assets \
  -H "X-PDFgine-Key: $PDFGINE_KEY" \
  -F "file=@logo.png" \
  -F "altText=Company logo"
HTTP 201
{
  "assetId": "ast_985f87e2b22d486db2d6d8bacd29288e",
  "fileName": "logo.png",
  "contentType": "image/png",
  "length": 20184,
  "altText": "Company logo",
  "createdAt": "2026-09-26T15:29:44.8420041+00:00",
  "expiresAt": null,
  "fontEmbedding": null
}

The type is read from the first bytes of the file, not from the Content-Type you send: a .png that is really a PDF is refused. PNG, JPEG, WebP, TTF and OTF are accepted, up to 10 MB per file.

Using it in a document

Send the id wherever the template expects an image. The same field also accepts a data: URI, but an uploaded asset is smaller on the wire and can be reused.

Request
curl -X POST https://api.pdfgine.com/api/v1/render \
  -H "X-PDFgine-Key: $PDFGINE_KEY" \
  -H "Content-Type: application/json" \
  -d '{
        "templateCode": "invoice",
        "format": "pdf",
        "data": { "logo": "ast_985f87e2b22d486db2d6d8bacd29288e" }
      }'

Temporary assets, listing and deleting

An image needed for a single document does not have to be cleaned up by hand: give expiresInMinutes between 1 and 10080 (seven days) and the asset removes itself.

Request
curl -X POST https://api.pdfgine.com/api/v1/assets \
  -H "X-PDFgine-Key: $PDFGINE_KEY" \
  -F "file=@signature.png" \
  -F "expiresInMinutes=60"

# Listing, one asset's content and deleting
curl https://api.pdfgine.com/api/v1/assets -H "X-PDFgine-Key: $PDFGINE_KEY"
curl https://api.pdfgine.com/api/v1/assets/ast_985f87e2b22d486db2d6d8bacd29288e/content \
  -H "X-PDFgine-Key: $PDFGINE_KEY" -o logo.png
curl -X DELETE https://api.pdfgine.com/api/v1/assets/ast_985f87e2b22d486db2d6d8bacd29288e \
  -H "X-PDFgine-Key: $PDFGINE_KEY"

Fonts and what may be embedded

A font file states in its own fsType bits what a document may do with it. PDFgine reads that at upload time and answers with fontEmbedding, so you learn the answer before you produce a document rather than after opening it.

fontEmbedding What the document may do
installableNo restriction; embedded in both PDF and Word.
editableEmbedded in both PDF and Word.
preview-printEmbedded in the PDF. Not embedded in Word, because a Word document can be edited; Word substitutes a font.
restrictedNot embedded anywhere. The document is still produced and the reader's own font is used instead.
bitmap-onlyOnly bitmap embedding is permitted, which a document cannot use. Not embedded.
unstatedThe file states no permission. Treated as embeddable, which is what the OpenType specification asks for.

WOFF and WOFF2 are refused on upload. They cannot be embedded in a Word document, and the same template would then come out right in PDF and wrong in Word - a difference you would only notice after sending the document.

Built-in fonts

These families ship with the product; use them by name in style.fontFamily and page.defaultFont. The same face goes to the PDF, to Word and to the editor. A weight the family lacks is not refused; the nearest face prints it.

Family Group Weights Scripts
Inter sans 100, 200, 300, 400, 500, 600, 700, 800, 900 latin, latin-ext, greek, cyrillic, vietnamese
Roboto sans 100, 200, 300, 400, 500, 600, 700, 800, 900 latin, latin-ext, greek, cyrillic, vietnamese
Montserrat sans 100, 200, 300, 400, 500, 600, 700, 800, 900 latin, latin-ext, cyrillic, vietnamese
Poppins sans 100, 200, 300, 400, 500, 600, 700, 800, 900 latin
DM Sans sans 100, 200, 300, 400, 500, 600, 700, 800, 900 latin
Nunito sans 200, 300, 400, 500, 600, 700, 800, 900 latin, cyrillic, vietnamese
Manrope sans 200, 300, 400, 500, 600, 700, 800 latin, greek, cyrillic, vietnamese
Noto Sans sans 100, 200, 300, 400, 500, 600, 700, 800, 900 latin, latin-ext, greek, cyrillic, vietnamese
Plus Jakarta Sans sans 200, 300, 400, 500, 600, 700, 800 latin, vietnamese
Work Sans sans 100, 200, 300, 400, 500, 600, 700, 800, 900 latin, latin-ext, vietnamese
Roboto Condensed condensed 100, 200, 300, 400, 500, 600, 700, 800, 900 latin, latin-ext, greek, cyrillic, vietnamese
Oswald condensed 200, 300, 400, 500, 600, 700 latin, latin-ext, cyrillic, vietnamese
Noto Serif serif 100, 200, 300, 400, 500, 600, 700, 800, 900 latin, latin-ext, greek, cyrillic, vietnamese
EB Garamond serif 400, 500, 600, 700, 800 latin, latin-ext, greek, cyrillic, vietnamese
Newsreader serif 200, 300, 400, 500, 600, 700, 800 latin, vietnamese
Literata serif 200, 300, 400, 500, 600, 700, 800, 900 latin, greek, cyrillic, vietnamese
Tinos serif 400, 700 latin, latin-ext, greek, cyrillic, vietnamese
Rokkitt serif 100, 200, 300, 400, 500, 600, 700, 800, 900 latin, vietnamese
Inconsolata mono 200, 300, 400, 500, 600, 700, 800, 900 latin, vietnamese
Noto Sans Mono mono 100, 200, 300, 400, 500, 600, 700, 800, 900 latin, latin-ext, greek, cyrillic, vietnamese
Arial system 400, 700
Georgia system 400, 700

When an upload is refused

Every refusal is a 400 with the reason under errors.file. Show that sentence to the person uploading; it already says what to do.

HTTP 400
{
  "type": "https://tools.ietf.org/html/rfc9110#section-15.5.1",
  "title": "One or more validation errors occurred.",
  "status": 400,
  "errors": {
    "file": ["Upload a TTF or OTF font so the Word output can use it. WOFF and WOFF2 files cannot be embedded in a Word document."]
  },
  "correlationId": "505aac87e234a7b4669e6203ac7ffcd5"
}
Errors →

What usually goes wrong

  • The type is read from the first bytes, not from the file name. Renaming a PDF to .png does not make it an image; the upload is refused.
  • WOFF and WOFF2 are refused on purpose. They cannot be embedded in Word, and the same template would then be right in PDF and wrong in Word - upload TTF or OTF.
  • The upload answers with fontEmbedding. Ignoring it means you learn that the font was substituted after the document has already gone out.
  • A data: URI travels with every single request. For a logo that appears on every document, upload it once and send the id.
  • An image needed for one document does not need cleaning up by hand. Give expiresInMinutes and it removes itself.