Developer Dashboard

Font Generation API

Generate custom fonts from a text prompt or a style reference image. Version 3.

Base URL

https://api.lipi.ai/v3

Postman Collection

Authentication

All requests require an API key passed in the x-api-key header.

curl https://api.lipi.ai/v3/credits \
  -H "x-api-key: lpi_your_api_key_here"
Keep your key secret

Never expose your API key in client-side code or public repositories. Use environment variables.

Endpoints

POST/v3/font-generate/from-textGenerate a font from a text prompt10 credits
POST/v3/font-generate/from-imageGenerate a font from a style image10 or 30 credits
GET/v3/font-generate/:idPoll job status and download URLs

POST /v3/font-generate/from-text

Generate a font from a prose description. The job runs asynchronously. Poll the returned job_id for the finished font files. Typical processing time is 2 to 5 minutes.

Request fields

FieldRequiredDescription
promptyesFont description, 1 to 500 characters
font_namenoDisplay name for the font (defaults to a generated name)
seednoInteger 0 to 4294967295 for reproducible results

Request

curl -X POST https://api.lipi.ai/v3/font-generate/from-text \
  -H "x-api-key: lpi_your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "prompt": "gothic blackletter with ornate capitals",
    "font_name": "MyFont",
    "seed": 42
  }'

Response (201)

{
  "job_id": "550e8400-e29b-41d4-a716-446655440000",
  "status": "pending",
  "mode": "text",
  "credits_charged": 10,
  "credits_remaining": 90,
  "free_credits_remaining": 0,
  "poll_url": "/v3/font-generate/550e8400-e29b-41d4-a716-446655440000"
}

POST /v3/font-generate/from-image

Generate a font from a style or handwriting reference image. Set character_set to"standard" (90 glyphs, 10 credits) or "extended" (260 glyphs, 30 credits).

Images larger than 1536px on either dimension are automatically resized (aspect ratio preserved). Maximum request body is 6MB, which is roughly a 4MB raw image. Resize client-side for larger files.

Request fields

FieldRequiredDescription
style_imageyesBase64 data URL (data:image/png;base64,...). PNG, JPEG, or WebP
font_namenoDisplay name for the font (defaults to a generated name)
character_setno"standard" (default, 10 credits) or "extended" (30 credits)

Request

curl -X POST https://api.lipi.ai/v3/font-generate/from-image \
  -H "x-api-key: lpi_your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "style_image": "data:image/png;base64,iVBORw0KGgo...",
    "font_name": "MyHandwriting",
    "character_set": "standard"
  }'

Response (201)

{
  "job_id": "550e8400-e29b-41d4-a716-446655440000",
  "status": "pending",
  "mode": "image",
  "character_set": "standard",
  "credits_charged": 10,
  "credits_remaining": 90,
  "free_credits_remaining": 0,
  "poll_url": "/v3/font-generate/550e8400-e29b-41d4-a716-446655440000"
}

GET /v3/font-generate/:id

Poll for job completion. Poll every 3 to 5 seconds. Download URLs are valid for 24 hours and are re-issued fresh on every poll, so a job can be re-polled at any time to get working links.

Response (running)

{
  "job_id": "550e8400-e29b-41d4-a716-446655440000",
  "status": "running",
  "mode": "text",
  "progress": 42,
  "stage": "sd_running",
  "font_name": "MyFont",
  "created_at": "2026-05-15T19:00:00Z",
  "completed_at": null
}

Response (succeeded)

{
  "job_id": "550e8400-e29b-41d4-a716-446655440000",
  "status": "succeeded",
  "mode": "text",
  "progress": 100,
  "stage": "completed",
  "font_name": "MyFont",
  "created_at": "2026-05-15T19:00:00Z",
  "completed_at": "2026-05-15T19:03:30Z",
  "download_urls": {
    "otf": "https://fontbuster-job-outputs-prod.s3.amazonaws.com/...",
    "ttf": "https://fontbuster-job-outputs-prod.s3.amazonaws.com/...",
    "woff": "https://fontbuster-job-outputs-prod.s3.amazonaws.com/..."
  },
  "download_urls_expire_at": "2026-05-16T19:03:30Z"
}

OTF, TTF, and WOFF are delivered. WOFF2 is not currently included.

Response (failed)

{
  "job_id": "550e8400-e29b-41d4-a716-446655440000",
  "status": "failed",
  "mode": "text",
  "progress": 0,
  "stage": "failed",
  "font_name": "MyFont",
  "created_at": "2026-05-15T19:00:00Z",
  "completed_at": "2026-05-15T19:01:10Z",
  "error": "Font generation failed: Modal endpoint returned 503",
  "credits_refunded": 10
}

Credits are automatically refunded when a job fails because of an infrastructure error.

Error Codes

StatusError CodeDescription
400missing_promptEmpty or missing "prompt" (from-text)
400missing_imageMissing "style_image" (from-image)
401invalid_api_keyMissing or invalid API key
402insufficient_creditsNot enough credits for this generation
403key_suspendedAPI key has been suspended
404not_foundJob not found or not owned by this key
413payload_too_largeRequest body exceeds the 6MB limit
422prompt_too_longPrompt exceeds 500 characters
422invalid_seedSeed is not an integer in range
422invalid_imageNot a valid PNG, JPEG, or WebP image
422invalid_character_setcharacter_set is not "standard" or "extended"
429rate_limitedExceeded rate limit (see retry_after_seconds)
503service_busyHigh demand, retry shortly

Rate Limits

Per Key

60 req/min

Response Header

429 responses include retry_after_seconds

Pricing

Generation typeCredits
Text to font10
Image to font, standard (90 glyphs)10
Image to font, extended (260 glyphs)30

Credits are charged when the job is submitted. A failed job is automatically refunded. A successful generation is not refundable.

Code Examples

Python

import requests
import time

API_KEY = "lpi_your_api_key_here"
BASE = "https://api.lipi.ai/v3"
HEADERS = {"x-api-key": API_KEY, "Content-Type": "application/json"}

# Submit a text-to-font job
resp = requests.post(f"{BASE}/font-generate/from-text", json={
    "prompt": "gothic blackletter with ornate capitals",
    "font_name": "MyFont",
    "seed": 42
}, headers=HEADERS)
job = resp.json()
print(f"Job {job['job_id']} created. Credits remaining: {job['credits_remaining']}")

# Poll for completion
while True:
    time.sleep(4)
    status = requests.get(f"{BASE}/font-generate/{job['job_id']}", headers=HEADERS).json()
    if status["status"] == "succeeded":
        for fmt, url in status["download_urls"].items():
            data = requests.get(url).content
            with open(f"MyFont.{fmt}", "wb") as out:
                out.write(data)
            print(f"Saved MyFont.{fmt}")
        break
    elif status["status"] == "failed":
        print(f"Failed: {status.get('error')}")
        break

Node.js

const fs = require('fs');

const API_KEY = 'lpi_your_api_key_here';
const BASE = 'https://api.lipi.ai/v3';
const headers = { 'x-api-key': API_KEY, 'Content-Type': 'application/json' };

async function generateFont(prompt) {
  const res = await fetch(`${BASE}/font-generate/from-text`, {
    method: 'POST',
    headers,
    body: JSON.stringify({ prompt, font_name: 'MyFont' })
  });
  const job = await res.json();
  console.log(`Job ${job.job_id} created`);

  while (true) {
    await new Promise(r => setTimeout(r, 4000));
    const status = await fetch(`${BASE}/font-generate/${job.job_id}`, { headers }).then(r => r.json());
    if (status.status === 'succeeded') {
      for (const [fmt, url] of Object.entries(status.download_urls)) {
        const buf = Buffer.from(await fetch(url).then(r => r.arrayBuffer()));
        fs.writeFileSync(`MyFont.${fmt}`, buf);
        console.log(`Saved MyFont.${fmt}`);
      }
      return;
    }
    if (status.status === 'failed') throw new Error(status.error);
  }
}

generateFont('gothic blackletter with ornate capitals');

Ready to start?

Apply for API access and get 10 free credits.

Get API Key