> ## Documentation Index
> Fetch the complete documentation index at: https://docs.overlap.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Custom Fonts

> Add, list and delete the custom brand fonts available to your company's subtitles and titles

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.

### Authentication

```http theme={null}
Authorization: Bearer YOUR_API_KEY
```

### Supported files

| Format | Extension |
| - | - |
| TrueType | `.ttf` |
| OpenType | `.otf` |
| WOFF | `.woff` |
| WOFF2 | `.woff2` |

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 `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

```http theme={null}
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. |

Returns `201` with the new font:

```json theme={null}
{
  "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.

```bash cURL theme={null}
curl -X POST "https://api.joinoverlap.com/companies/$OVERLAP_COMPANY_ID/fonts" \
     -H "Authorization: Bearer $OVERLAP_API_KEY" \
     -F "file=@AcmeSans.otf" \
     -F "name=Acme Sans"
```

```javascript javascript theme={null}
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

```http theme={null}
GET https://api.joinoverlap.com/companies/{companyId}/fonts
```

Returns every custom font for the company, newest first.

```json theme={null}
{
  "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

```http theme={null}
DELETE https://api.joinoverlap.com/companies/{companyId}/fonts/{fontId}
```

Removes the font from your library so it no longer appears in the font picker or in the list above.

```json theme={null}
{ "deleted": true, "id": "7f3c1e9a5b2d4c8e9a1b6d0f2e4c8a31" }
```

> [!NOTE]
>
> 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's `fontFamily` and `fontUrl` in a [`subtitleConfig` or `titleConfig`](/api-reference/update-clip), or in [node config overrides](/api-reference/node-config-overrides):

```json theme={null}
{
  "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`. |


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.