curl -X POST "https://api.joinoverlap.com/companies/$OVERLAP_COMPANY_ID/fonts" \
-H "Authorization: Bearer $OVERLAP_API_KEY" \
-F "[email protected]" \
-F "name=Acme Sans"
const form = new FormData();
form.append("file", new Blob([fontBytes]), "AcmeSans.otf");
form.append("name", "Acme Sans");
const response = await fetch(
`https://api.joinoverlap.com/companies/${process.env.OVERLAP_COMPANY_ID}/fonts`,
{
method: "POST",
headers: { "Authorization": `Bearer ${process.env.OVERLAP_API_KEY}` },
body: form
}
);
const { font } = await response.json();
Custom Fonts
Add, list and delete the custom brand fonts available to your company’s subtitles and titles
POST
/
companies
/
{companyId}
/
fonts
curl -X POST "https://api.joinoverlap.com/companies/$OVERLAP_COMPANY_ID/fonts" \
-H "Authorization: Bearer $OVERLAP_API_KEY" \
-F "[email protected]" \
-F "name=Acme Sans"
const form = new FormData();
form.append("file", new Blob([fontBytes]), "AcmeSans.otf");
form.append("name", "Acme Sans");
const response = await fetch(
`https://api.joinoverlap.com/companies/${process.env.OVERLAP_COMPANY_ID}/fonts`,
{
method: "POST",
headers: { "Authorization": `Bearer ${process.env.OVERLAP_API_KEY}` },
body: form
}
);
const { font } = await response.json();
Upload your own font files so they can be used in subtitles and titles, the same way fonts added from Brand Assets → Fonts in the Overlap app can. Fonts added here appear in the app’s font picker, and fonts added in the app appear in the list below.
Files can be up to 20 MB. Each file is one weight and style: upload bold or italic variants as separate fonts, each with its own
Returns
Returns every custom font for the company, newest first.
Removes the font from your library so it no longer appears in the font picker or in the list above.
Authentication
Authorization: Bearer YOUR_API_KEY
Supported files
| Format | Extension |
|---|---|
| TrueType | .ttf |
| OpenType | .otf |
| WOFF | .woff |
| WOFF2 | .woff2 |
name.
Uploaded fonts count toward your company’s Brand Assets storage, the same allowance used by Brand Assets in the Overlap app. Deleting a font removes it from your library but keeps its file for clips already using it, so its space stays counted. If your plan has no Brand Assets allowance, or the font would exceed it, the upload is refused.
Each file is checked before it is saved: it must be a complete, readable font with glyph outlines, and include the tables browsers require (cmap, head, hhea, hmtx, maxp, name, OS/2 and post).
Add a font
POST https://api.joinoverlap.com/companies/{companyId}/fonts
Content-Type: multipart/form-data
| Field | Required | Description |
|---|---|---|
file | Yes | The font file. |
name | No | Display name for the font. Defaults to the file name without its extension. Up to 100 characters; quotes, backslashes, braces, semicolons, colons and angle brackets are not allowed. |
201 with the new font:
{
"font": {
"id": "7f3c1e9a5b2d4c8e9a1b6d0f2e4c8a31",
"fontFamily": "Acme Sans (Uploaded)",
"fontUrl": "https://cdn.example.com/fonts/AcmeSans.otf?token=...",
"fileName": "AcmeSans.otf",
"format": "otf",
"sizeBytes": 48212,
"createdAt": "2026-10-21T15:04:05Z"
}
}
(Uploaded) is added to every custom font’s family name so it can never replace a built-in font such as Roboto. Use the returned fontFamily and fontUrl exactly as given.
curl -X POST "https://api.joinoverlap.com/companies/$OVERLAP_COMPANY_ID/fonts" \
-H "Authorization: Bearer $OVERLAP_API_KEY" \
-F "[email protected]" \
-F "name=Acme Sans"
const form = new FormData();
form.append("file", new Blob([fontBytes]), "AcmeSans.otf");
form.append("name", "Acme Sans");
const response = await fetch(
`https://api.joinoverlap.com/companies/${process.env.OVERLAP_COMPANY_ID}/fonts`,
{
method: "POST",
headers: { "Authorization": `Bearer ${process.env.OVERLAP_API_KEY}` },
body: form
}
);
const { font } = await response.json();
List fonts
GET https://api.joinoverlap.com/companies/{companyId}/fonts
{
"fonts": [
{
"id": "7f3c1e9a5b2d4c8e9a1b6d0f2e4c8a31",
"fontFamily": "Acme Sans (Uploaded)",
"fontUrl": "https://cdn.example.com/fonts/AcmeSans.otf?token=...",
"fileName": "AcmeSans.otf",
"format": "otf",
"sizeBytes": 48212,
"createdAt": "2026-10-21T15:04:05Z"
}
]
}
Delete a font
DELETE https://api.joinoverlap.com/companies/{companyId}/fonts/{fontId}
{ "deleted": true, "id": "7f3c1e9a5b2d4c8e9a1b6d0f2e4c8a31" }
Deleting a font does not delete the file itself. Clips that were already styled with the font keep rendering correctly. Once a font is deleted, you can add another with the same name.
Use a font in a clip
Pass the font’sfontFamily and fontUrl in a subtitleConfig or titleConfig, or in node config overrides:
{
"titleConfig": {
"text": "Product Launch Highlights",
"fontFamily": "Acme Sans (Uploaded)",
"fontUrl": "https://cdn.example.com/fonts/AcmeSans.otf?token=...",
"fontWeight": "400"
}
}
Errors
Errors use the standard{ "error", "status": "error", "code" } shape.
| Status | code | Meaning |
|---|---|---|
| 400 | MISSING_FILE | No file field was sent. Send multipart/form-data. |
| 400 | INVALID_FONT_FILE | The file is empty, damaged or truncated, is missing tables browsers require, or is not a valid font of the type its extension says. |
| 400 | INVALID_FONT_NAME | name is empty, too long, or contains a disallowed character. |
| 401 | INVALID_API_KEY | Missing or invalid API key for this company. |
| 403 | BRAND_ASSETS_NOT_AVAILABLE | Your plan has no Brand Assets storage allowance. |
| 403 | BRAND_ASSETS_LIMIT_EXCEEDED | The font would exceed your Brand Assets storage limit. The response includes usedBytes and limitBytes. |
| 404 | COMPANY_NOT_FOUND | No company exists for this companyId. |
| 404 | FONT_NOT_FOUND | No font with that id exists (or it was already deleted). |
| 409 | FONT_ALREADY_EXISTS | A font with this name already exists. The response includes it under font. |
| 413 | FONT_TOO_LARGE | The file is larger than 20 MB. |
| 415 | UNSUPPORTED_FONT_TYPE | The extension is not .ttf, .otf, .woff or .woff2. The response lists them under supported. |
Was this page helpful?