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.
curl -X POST https://api.pdfgine.com/api/v1/assets \
-H "X-PDFgine-Key: $PDFGINE_KEY" \
-F "file=@logo.png" \
-F "altText=Company logo"
{
"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.
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.
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 |
|---|---|
installable | No restriction; embedded in both PDF and Word. |
editable | Embedded in both PDF and Word. |
preview-print | Embedded in the PDF. Not embedded in Word, because a Word document can be edited; Word substitutes a font. |
restricted | Not embedded anywhere. The document is still produced and the reader's own font is used instead. |
bitmap-only | Only bitmap embedding is permitted, which a document cannot use. Not embedded. |
unstated | The 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.
{
"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"
}
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.