Skip to content

Developer docs

FontPreview has two parts: drop-in widgets for your pages, and the render API they're built on. Widgets and the render API live at https://render.fontpreview.app; the account API used by the dashboard lives at https://api.fontpreview.app.

Quickstart

  1. 1
    Create an account
    Sign up and confirm your email address.
  2. 2
    Upload a font
    In Fonts → Upload, add TTF, OTF or WOFF files (up to 10 MB each). Each font gets an ID like fnt_….
  3. 3
    Create a widget key
    In API Keys, create a widget key and add your site's origin, e.g. https://shop.example.com. Copy the key when it's shown; it is displayed once.
  4. 4
    Create a widget and embed it
    In Widgets, create a widget, then copy its embed code. Paste your widget key into data-key and put the snippet on your page.
  5. 5
    Check it renders
    Open the page on the origin you listed. If nothing appears, the browser console shows the error (most often an origin that isn't on the key).
Embed a tester
<div id="font-tester"></div>
<script src="https://render.fontpreview.app/v1/tester.js"
        data-key="fp_widget_…"
        data-widget-id="wgt_…"
        data-container="#font-tester"
        defer></script>

API keys

There are two kinds of key. Use the right one for where it runs.

KeyUse itRestrictions
fp_widget_…In public HTML: widget embeds and browser requests.Works only from the origins you list on the key, and only for rendering. Requests without an Origin header are refused.
fp_live_…On your server only: render requests from backend code and minting signed URLs.Full access to your account's rendering. Never put a live key in HTML, JavaScript bundles or a public repo.

Keys are shown once when created and stored only as a hash, so we can't show them again. If you lose one, revoke it and create a new one. Send keys in the X-API-Key header (or the api_key query parameter for image URLs in HTML).

Origins are matched exactly on scheme, host and port: https://example.com does not cover https://www.example.com, so add both if you use both. Wildcards aren't supported. Allowed origins per key: Free 1, Starter 5, Pro unlimited, Enterprise unlimited.

Widgets

Each widget is a script at https://render.fontpreview.app/v1/<name>.js that renders inside a Shadow DOM, so your CSS and the widget's can't affect each other. Settings come from data-* attributes. With data-widget-id, the widget loads the configuration saved in the dashboard. Colours are 6-digit hex without #.

Script-tag embed

One widget per script tag, pointed at a container. Best for plain HTML and CMS embeds (see the quickstart snippet above).

Element embed

For single-page apps or several widgets on one page, put the settings on the container and load the bundle once. Call window.FontPreview.init() after adding containers dynamically; it only mounts containers that aren't mounted yet.

Element embed
<div data-fp-widget="tester" data-key="fp_widget_…" data-font="fnt_a"></div>
<div data-fp-widget="tester" data-key="fp_widget_…" data-font="fnt_b"></div>
<script src="https://render.fontpreview.app/v1/tester.js" async></script>

Attributes for every widget

AttributeDefaultMeaning
data-key—Required. A widget key (fp_widget_…) whose allowed origins include this page's origin.
data-container—Script-tag embeds: CSS selector of the element to render into (required).
data-fp-widget—Element embeds: the widget name (tester, badge, picker, …), set on the container itself.
data-widget-id—Load the configuration saved in the dashboard. Inline attributes fill in anything it doesn't set.
data-themelightlight, dark, or auto (follows the visitor's colour scheme).
data-color000000Text colour, 6-digit hex (a leading # is ignored).
data-bgffffffBackground colour, 6-digit hex or transparent.
data-debounce250Milliseconds to wait after typing before re-rendering.
data-render-url—Override the render service URL. Script-tag embeds only; normally derived from the script's own src.

Tester /v1/tester.js

Font: data-font (or set it in the dashboard).

AttributeDefaultMeaning
data-default-textType something...Initial text.
data-default-size48Initial size in px.
data-default-color000000Text colour (the tester uses this instead of data-color).
data-show-size-slidertrueShow the size slider.
data-show-color-pickerfalseShow a colour picker.
data-min-size12Slider minimum.
data-max-size200Slider maximum.
data-max-length100Maximum characters a visitor can type.
data-stroke-width—Stroke width (0.5–10) for single-line fonts. Defaults to the font's setting.

Badge /v1/badge.js

Font: data-font (or set it in the dashboard).

AttributeDefaultMeaning
data-textPreviewThe sample text.
data-size32Size in px.
data-border-radius4Corner radius in px.

Picker /v1/picker.js

Font: data-font-ids (or set it in the dashboard). data-font-ids is a comma- or space-separated list. data-font-names (comma list, same order) sets the labels.

AttributeDefaultMeaning
data-default-textThe quick brown foxSample text.
data-layoutlistlist or grid.
data-columns2Grid columns, 1–6.
data-size36Size in px.
data-page-size10Fonts per page, 1–50.
data-show-inputtrueLet visitors edit the text.
data-show-font-nametrueLabel each sample.
data-searchfalseShow a filter box.
data-selectablefalseLet visitors select fonts (fires fontpreview:select).
data-multi-selectfalseAllow more than one selection.

Specimen /v1/specimen.js

Font: data-font (or set it in the dashboard).

AttributeDefaultMeaning
data-sections-ordermetadata,tester,waterfall,paragraph,charsetComma-separated section order.
data-show-metadatatrueInclude name, family, weight and style.
data-show-testertrueInclude the type tester section.
data-show-waterfalltrueInclude the waterfall section.
data-show-paragraphtrueInclude the paragraph section.
data-show-charsettrueInclude the character set.
data-waterfall-sizes72,48,36,24,18,14Sizes for the waterfall section.
data-waterfall-textThe quick brown fox jumps over the lazy dogText for the waterfall section.
data-paragraph-text—Text for the paragraph section.
data-charsetlatin-basiclatin-basic, latin-extended, cyrillic or custom.
data-custom-chars—Characters to show when data-charset is custom.

Waterfall /v1/waterfall.js

Font: data-font (or set it in the dashboard).

AttributeDefaultMeaning
data-textHamburgevonsSample text.
data-sizes72,60,48,36,24,18,14,12Comma-separated sizes in px (8–400, up to 20).
data-show-size-labelstrueLabel each row with its size.
data-label-positionleftleft or right.
data-show-inputfalseLet visitors edit the text.

Paragraph /v1/paragraph.js

Font: data-heading-font (or set it in the dashboard). Add data-body-font for a second font; it defaults to the heading font.

AttributeDefaultMeaning
data-heading-textThe Art of TypographyHeading text.
data-body-text—Body text.
data-heading-size48Heading size in px.
data-body-size16Body size in px.
data-line-height1.5Body line height.
data-editabletrueLet visitors edit the text.
data-show-font-namestrueLabel the fonts.
data-heading-font-nameHeadingLabel for the heading font.
data-body-font-nameBodyLabel for the body font.

Customizer /v1/customizer.js

Font: data-font-ids (or set it in the dashboard). Also requires data-bg-image (https URL of the product photo) and data-text-area (x,y,width,height in the photo's pixels).

AttributeDefaultMeaning
data-font-names—Comma list of labels for the font menu, same order as data-font-ids.
data-default-font-id—Font selected first. Defaults to the first in the list.
data-default-textYour text hereInitial text.
data-default-size36Initial size in px.
data-default-color000000Initial text colour.
data-max-length50Maximum characters.
data-show-font-selectortrueShow the font menu.
data-show-color-pickertrueShow the colour picker.
data-show-size-slidertrueShow the size slider.
data-cart-integration—shopify, woocommerce or custom: adds an Add to cart button that fires fontpreview:add-to-cart.

Font: data-family-id (or set it in the dashboard). data-family-id is the family name as shown in the dashboard. Or pass data-font-ids (and optional data-font-names) instead.

AttributeDefaultMeaning
data-default-textTypographySample text.
data-layoutgridgrid or list.
data-columns2Grid columns, 1–6.
data-size36Size in px.
data-sortweightweight or name.
data-show-weight-labelstrueLabel weights.
data-show-style-labelstrueLabel styles.
data-show-inputtrueLet visitors edit the text.

Widgets dispatch DOM events on the container element (bubbling): fontpreview:select from the picker and fontpreview:add-to-cart from the customizer.

Render API

GET https://render.fontpreview.app/v1/render/{fontId}?text=…

Returns image/png or image/webp. Responses carry Cache-Control: public, max-age=3600 and X-Render-Cache: HIT|MISS. Only misses count toward your monthly render allowance. Your watermark is applied server-side according to your plan and settings; it can't be changed with a query parameter.

ParameterTypeDefaultMeaning
textstring, 1–500 chars—Required. The text to set. A newline (%0A) starts a new line.
sizeinteger 8–40048Font size in CSS pixels.
colorhex, 6 digits, no #000000Text colour.
bghex or transparenttransparentBackground colour.
widthinteger 1–4000—Canvas width in pixels. Defaults to the text's width.
heightinteger 1–4000—Content height in pixels (the watermark band is added on top of this). Defaults to the text's height.
paddinginteger 0–20016Space around the text in pixels.
alignleft | center | rightleftHorizontal alignment inside the canvas.
formatpng | webppngImage format. WebP is lossless.
qualityinteger 1–10090Reserved for lossy output; has no effect on PNG or WebP today.
dprinteger 1–31Device pixel ratio. 2 renders at double resolution for retina screens.
line_heightnumber 1–31.3Line spacing for multi-line text, as a multiple of the size.
stroke_widthnumber 0.5–10—Stroke width for single-line (engraving) fonts. Defaults to the font's setting, or 1.5.
featurescomma-separated tags—OpenType features to switch on, e.g. smcp,ss01,liga. Unknown tags are ignored.
Server-side request
curl "https://render.fontpreview.app/v1/render/fnt_…?text=Hello%20world&size=72&color=1c2140&dpr=2" \
  -H "X-API-Key: fp_live_…" \
  -o hello.png

Signed URLs

To put a render in an <img> tag without exposing any key, mint a short-lived signed URL from your server with a live key. The signature covers the font and every parameter, so the URL can't be edited to render different text.

Mint (server-side)
curl -X POST "https://api.fontpreview.app/render-tokens" \
  -H "X-API-Key: fp_live_…" -H "Content-Type: application/json" \
  -d '{"fontId":"fnt_…","text":"Hello","size":64,"expiresIn":300}'

# → {"data":{"url":"https://render.fontpreview.app/v1/render/fnt_…?…&sig=…","exp":1767225600}}

The body takes the same options as the render API in camelCase (lineHeight, strokeWidth) plus expiresIn (30–3600 seconds, default 300). Widget keys can't mint signed URLs.

Errors

Errors are JSON with a stable code:

{ "error": { "code": "RATE_LIMITED", "message": "…", "details": { "retryAfter": 12 } } }
StatusCodeWhen
400VALIDATION_FAILEDA parameter is missing or out of range, or the final image would exceed 2048×2048 device pixels.
401UNAUTHORIZEDNo API key, or the key is unknown or revoked.
401SIGNATURE_INVALIDA signed URL was altered or signed with the wrong secret.
401SIGNATURE_EXPIREDA signed URL is past its exp time.
403FORBIDDENA widget key was used from an origin that isn't on its list, or without an Origin header.
404NOT_FOUNDThe font doesn't exist or belongs to another account.
422RENDER_FAILEDThe font couldn't render this text.
422FONT_UNSUPPORTEDThe stored font file can't be rendered (for example a legacy WOFF2 upload).
429RATE_LIMITEDToo many requests this minute. Wait for Retry-After seconds.
429QUOTA_EXCEEDEDThe monthly render allowance is used up.
5xxSERVER_ERROR / RENDER_TIMEOUTTemporary failure. Retry with backoff.

Rate limits

Requests are limited per minute by plan. Every response carries X-RateLimit-Remaining and X-RateLimit-Reset (Unix seconds); a 429 also carries Retry-After.

PlanRequests / minuteRenders / month
Free105,000
Starter100100,000
Pro1,0001,000,000
Enterprise10,000100,000,000