Kalpana Docs
Resources

Upload a font

Upload a font file as base64 so templates can use its family.

POST /api/fonts

Requires assets:create. Returns 201 with the font.

Request body

FieldRequiredDescription
workspaceIdYesWorkspace id or slug.
familyYesFamily name, as templates refer to it.
styleYesStyle name such as Regular or Bold Italic.
contentHashYesA hash that identifies the bytes. Use the SHA-256 hex digest of the file.
fontBytesYesThe font file, base64 encoded.
weightNoFallback numeric weight, 400 by default. The weight read from the font file, or implied by style, takes precedence.
italicNoFallback, false by default. The font file's own italic flag takes precedence.
filenameNoFile name. It must end in .ttf, .otf, .woff or .woff2. Defaults to {family}-{style}.ttf.
curl --request POST "https://app.kalpana.one/api/fonts" \
  --header "x-api-key: $KALPANA_API_KEY" \
  --header "content-type: application/json" \
  --data '{
    "workspaceId": "acme",
    "family": "Inter",
    "style": "Bold",
    "weight": 700,
    "contentHash": "'"$(shasum -a 256 Inter-Bold.ttf | cut -d' ' -f1)"'",
    "fontBytes": "'"$(base64 < Inter-Bold.ttf | tr -d '\n')"'",
    "filename": "Inter-Bold.ttf"
  }'

The response is the font object shown in List fonts. If the workspace already holds a font with the same contentHash, that font is returned unchanged.

For large files, or many at once, use Upload fonts directly, which avoids sending the bytes inside JSON.

Errors

StatusCause
400The file name does not end in a supported font extension.
403Your role or key lacks assets:create.
500The workspace already has a font with the same family, style, weight and italic flag from a different file. The message is Failed to upload font.
Was this page helpful?

Updated 4 Nov 2026

On this page