The renderer never touches the network while it prints, so a document can only use a typeface we bundle. This endpoint is that list. It needs no API key — the catalogue is not account data, and an agent that just received a 400 unknown_font has to be able to read it immediately.
/v1/fontsPublicResponse
{
"default": "Inter",
"count": 62,
"families": ["Abril Fatface", "Albert Sans", "Alex Brush", "…"],
"note": "…"
}families is sorted alphabetically and is the whole truth: a family that is not in it is not on the machine. The response is cacheable for an hour.
Example request
curl -s https://api.pixldocs.com/v1/fontsWhich rule applies to you
There are two behaviours, and the one you get depends on where the markup came from. The difference is deliberate.
A saved template — created through POST /v1/templates or edited in our editor — is resolved once, at save time. If the markup you send names a family we do not bundle, the stack is read the way a browser reads it and pinned to a single bundled family in the STORED source, and the write response carries a font_substitutions array naming every rewrite. What you then read in the editor is exactly what renders, on the first render and every one after. Renders themselves stay strict: a saved source that still names an unbundled family is 400 unknown_font.
Ad-hoc markup sent to POST /v1/render/html or POST /v1/render/url is read as CSS defines it. font-family: Helvetica, Arial, sans-serif is an ordered list of preferences ending in a generic, not a demand for Helvetica — so we resolve it the way a browser would (first bundled family wins, the generic tail decides the class) and pin the result to one literal family. That resolution is deterministic and it is never silent: every stack we rewrite comes back on X-Pixldocs-Font-Substituted.
The generic classes land on sans-serif → Inter, serif → Lora, monospace → JetBrains Mono, cursive → Dancing Script.
Characters, not just families
A bundled family still has to contain the glyphs you send it. Text in a script the chosen family does not cover is refused before it renders rather than printed as boxes, and the error names the characters. Devanagari, CJK and similar scripts need a family that covers them — Noto Sans is the broadest one bundled.