API
Every feature of the site is a plain HTTP request. No key required for the public catalogue.
Stylesheet
Request a family and the weights you need. The response contains a single src per face, negotiated for the requesting browser.
<link rel="stylesheet" href="https://v2.fontapi.ir/css/vazirmatn:400,700">Several families, one stylesheet
Repeat family to load several families with one request and one <link>. Each takes the same weight syntax as the path form, and d and ur apply to all of them. A collection on this site builds exactly this URL. A custom family name (n) renames one family, so it is accepted only when a single family is requested.
<link rel="stylesheet" href="https://v2.fontapi.ir/css?family=inter:400,700&family=vazirmatn:400&d=swap">
# and the structured equivalent:
curl "https://v2.fontapi.ir/json?family=inter:400,700&family=vazirmatn:400"Weights and italics
Comma-separate weights. Suffix a weight with i for italic. A weight the family does not ship resolves by the CSS Fonts Level 4 matching rules rather than failing.
https://v2.fontapi.ir/css/ibm-plex-sans:400,400i,700Weight aliasing
Ask for a source weight but choose how it is labelled in the emitted CSS. Useful when your stylesheet expects font-weight: bold but the face you want is 600.
https://v2.fontapi.ir/css/ibm-plex-sans:600@bold
/* emits: font-weight: bold; using the 600 face */Custom family name
Serve a font under a different CSS family name, so you can swap the underlying face without touching your stylesheet.
https://v2.fontapi.ir/css/vazirmatn:400?n=Brand%20Sans
/* then: font-family: "Brand Sans", sans-serif; */font-display
Any value from the CSS enum: auto, block, swap, fallback, optional. Invalid values are rejected with 400 rather than silently ignored.
https://v2.fontapi.ir/css/vazirmatn:400?d=swapSubsetting
By default each script is a genuinely separate, smaller file with an accurate unicode-range, so the browser downloads only what your page text needs. Latin is typically under 10% of the full face.
/* automatic: the CSS lists one @font-face per subset */
https://v2.fontapi.ir/css/vazirmatn:400unicode-range override
Request an exact range. If a pre-built subset matches it is served directly; if not, the nearest covering file is used and the JSON response reports subset_fallback so you always know whether you got byte-optimal output.
https://v2.fontapi.ir/css/vazirmatn:400?ur=U%2B0600-06FF
# check what actually happened:
curl "https://v2.fontapi.ir/json/vazirmatn:400?ur=U%2B0600-06FF" | jq .subset_fallbackJSON
The same resolution as CSS, but structured — and unlike CSS it exposes the full format matrix plus the resolved user agent, so you can build your own @font-face rules and see why a format was chosen.
curl "https://v2.fontapi.ir/json/vazirmatn:400,700"Catalogue
Browse, search and filter the public library. No key required. A filter can repeat: several categories or languages list families in any of them, several scripts list only families that cover all of them. Each listing carries facet counts for its own filters — how many families each value would list if it were added.
https://v2.fontapi.ir/v1/fonts?search=vazir&language=fa
https://v2.fontapi.ir/v1/fonts?category=serif&category=display
https://v2.fontapi.ir/v1/fonts?subset=latin&subset=arabic
https://v2.fontapi.ir/v1/fonts/vazirmatn
https://v2.fontapi.ir/v1/facetsCaching
Font files are immutable: every URL carries a version segment, so the bytes at a
given URL never change meaning and responses are served with max-age=31536000, immutable. Stylesheets use a
shorter window and are invalidated explicitly when a font is republished, rather than
waiting for a TTL to lapse. Byte-range and conditional requests are supported, so a
client on a poor connection can resume rather than restart.