Workspace API

Media library

Media library endpoints of the Zanfia Workspace API, with schemas and code samples.

10 min readLast updated Oct 8, 2026

Upload files and videos for use in lessons and pages. Videos transcode after upload — poll the media item until uploadStatus is ready. You can also generate images with AI (synchronous; spends the workspace's AI credits) and start video transcription (spends transcription minutes; returns 202 — poll GET /media/{mediaId}/transcript for the result). All routes require a Authorization: Bearer header — see Authentication.

List media

GET/media

Authorization

bearerAuth
AuthorizationBearer <token>

API key from Dashboard → Integrations → API, MCP and CLI.

In: header

Query Parameters

folder?string

Response Body

application/json

application/json

curl -X GET "https://example.com/media"
{  "count": 0,  "media": [    {      "id": "string",      "name": "string",      "type": "string",      "mimeType": "string",      "size": 0,      "url": "string",      "thumbnailUrl": "string",      "video": {        "bunnyLibraryId": "string",        "bunnyVideoId": "string"      },      "folder": "string",      "uploadStatus": "string",      "createdAt": "string"    }  ]}
{  "error": "string",  "message": "string"}

Upload a file

POST/media

Authorization

bearerAuth
AuthorizationBearer <token>

API key from Dashboard → Integrations → API, MCP and CLI.

In: header

Request Body

application/json

TypeScript Definitions

Use the request body type in TypeScript.

Response Body

application/json

application/json

curl -X POST "https://example.com/media" \  -H "Content-Type: application/json" \  -d '{    "name": "string",    "mimeType": "string",    "data": "string"  }'
{  "mediaId": "string",  "url": "string",  "storagePath": "string"}
{  "error": "string",  "message": "string"}

Start a video upload

POST/media/videos/initiate-upload

Authorization

bearerAuth
AuthorizationBearer <token>

API key from Dashboard → Integrations → API, MCP and CLI.

In: header

Request Body

application/json

TypeScript Definitions

Use the request body type in TypeScript.

Begin a Bunny video upload: provisions a Bunny video object + a Pending MediaDocument, and returns a signed TUS credential. The caller then uploads the bytes DIRECTLY to Bunny (the file never passes through the API), and polls GET /media/:mediaId until uploadStatus is ready (Bunny finalizes via webhook).

Response Body

application/json

application/json

curl -X POST "https://example.com/media/videos/initiate-upload" \  -H "Content-Type: application/json" \  -d '{    "title": "string",    "sourceSizeBytes": 0  }'
{  "mediaId": "string",  "bunnyVideoId": "string",  "bunnyLibraryId": "string",  "signature": "string",  "expire": 0}
{  "error": "string",  "message": "string"}

Generate an AI image

POST/media/ai-images

Authorization

bearerAuth
AuthorizationBearer <token>

API key from Dashboard → Integrations → API, MCP and CLI.

In: header

Request Body

application/json

TypeScript Definitions

Use the request body type in TypeScript.

Generate ONE AI image into the Media Library. Synchronous (up to ~1 min); spends the workspace's AI credits. 402 no-credits, 413 storage-quota-exceeded, 502 image-generation-failed.

Response Body

application/json

application/json

curl -X POST "https://example.com/media/ai-images" \  -H "Content-Type: application/json" \  -d '{    "prompt": "string",    "aspectRatio": "1:1",    "quality": "1K"  }'
{  "mediaId": "string",  "url": "string",  "name": "string"}
{  "error": "string",  "message": "string"}

Move media into a folder

POST/media/move

Authorization

bearerAuth
AuthorizationBearer <token>

API key from Dashboard → Integrations → API, MCP and CLI.

In: header

Request Body

application/json

TypeScript Definitions

Use the request body type in TypeScript.

Files the items into folder (by NAME); folder: null unfiles them.

Response Body

application/json

application/json

curl -X POST "https://example.com/media/move" \  -H "Content-Type: application/json" \  -d '{    "mediaIds": [      "string"    ],    "folder": "string"  }'
{  "updatedCount": 0}
{  "error": "string",  "message": "string"}

Media detail

GET/media/{mediaId}

Authorization

bearerAuth
AuthorizationBearer <token>

API key from Dashboard → Integrations → API, MCP and CLI.

In: header

Path Parameters

mediaId*string

Media id

Response Body

application/json

application/json

curl -X GET "https://example.com/media/string"
{  "media": {    "id": "string",    "name": "string",    "type": "string",    "mimeType": "string",    "size": 0,    "url": "string",    "thumbnailUrl": "string",    "video": {      "bunnyLibraryId": "string",      "bunnyVideoId": "string"    },    "folder": "string",    "uploadStatus": "string",    "createdAt": "string"  }}
{  "error": "string",  "message": "string"}

Update media details

PATCH/media/{mediaId}

Authorization

bearerAuth
AuthorizationBearer <token>

API key from Dashboard → Integrations → API, MCP and CLI.

In: header

Path Parameters

mediaId*string

Media id

Request Body

application/json

TypeScript Definitions

Use the request body type in TypeScript.

Response Body

application/json

application/json

curl -X PATCH "https://example.com/media/string" \  -H "Content-Type: application/json" \  -d '{}'
{  "mediaId": "string",  "updated": true}
{  "error": "string",  "message": "string"}

Delete a media item

DELETE/media/{mediaId}

Authorization

bearerAuth
AuthorizationBearer <token>

API key from Dashboard → Integrations → API, MCP and CLI.

In: header

Path Parameters

mediaId*string

Media id

Response Body

application/json

application/json

curl -X DELETE "https://example.com/media/string"
{  "status": "ok"}
{  "error": "string",  "message": "string"}

Video transcript

GET/media/{mediaId}/transcript

Authorization

bearerAuth
AuthorizationBearer <token>

API key from Dashboard → Integrations → API, MCP and CLI.

In: header

Path Parameters

mediaId*string

Media id

Query Parameters

includeWords?boolean

true includes word-level timings (large payload).

Response Body

application/json

application/json

curl -X GET "https://example.com/media/string/transcript"
{  "transcription": {    "text": "string",    "language": "string",    "createdAt": "string",    "updatedAt": "string",    "words": [      {        "word": "string",        "start": 0,        "end": 0      }    ]  }}
{  "error": "string",  "message": "string"}

Start video transcription

POST/media/{mediaId}/transcribe

Authorization

bearerAuth
AuthorizationBearer <token>

API key from Dashboard → Integrations → API, MCP and CLI.

In: header

Path Parameters

mediaId*string

Media id

Request Body

application/json

TypeScript Definitions

Use the request body type in TypeScript.

Start background transcription for a video. Spends transcription minutes (duration-aware). 202 on accept; poll GET /media/:mediaId/transcript.

Response Body

application/json

application/json

curl -X POST "https://example.com/media/string/transcribe" \  -H "Content-Type: application/json" \  -d '{}'
{  "status": "queued",  "queuedAt": "string"}
{  "error": "string",  "message": "string"}

List caption tracks

GET/media/{mediaId}/captions

Authorization

bearerAuth
AuthorizationBearer <token>

API key from Dashboard → Integrations → API, MCP and CLI.

In: header

Path Parameters

mediaId*string

Media id

Response Body

application/json

application/json

curl -X GET "https://example.com/media/string/captions"
{  "tracks": [    {      "srclang": "string",      "label": "string",      "source": "transcript",      "status": "live",      "updatedAt": "string",      "recorded": true    }  ],  "transcriptLanguage": "string"}
{  "error": "string",  "message": "string"}

Upload a caption track

POST/media/{mediaId}/captions

Authorization

bearerAuth
AuthorizationBearer <token>

API key from Dashboard → Integrations → API, MCP and CLI.

In: header

Path Parameters

mediaId*string

Media id

Request Body

application/json

TypeScript Definitions

Use the request body type in TypeScript.

Upload (or replace) one language's subtitle file. content is the TEXT of a .vtt or .srt file (UTF-8, up to 2 MB; SubRip is converted to WebVTT).

Response Body

application/json

application/json

curl -X POST "https://example.com/media/string/captions" \  -H "Content-Type: application/json" \  -d '{    "srclang": "string",    "content": "string"  }'
{  "track": {    "srclang": "string",    "label": "string",    "source": "transcript",    "status": "live",    "updatedAt": "string",    "recorded": true  }}
{  "error": "string",  "message": "string"}

Re-push the transcript caption track

POST/media/{mediaId}/captions/regenerate

Authorization

bearerAuth
AuthorizationBearer <token>

API key from Dashboard → Integrations → API, MCP and CLI.

In: header

Path Parameters

mediaId*string

Media id

Response Body

application/json

application/json

curl -X POST "https://example.com/media/string/captions/regenerate"
{  "track": {    "srclang": "string",    "label": "string",    "source": "transcript",    "status": "live",    "updatedAt": "string",    "recorded": true  }}
{  "error": "string",  "message": "string"}

Get a caption track

GET/media/{mediaId}/captions/{srclang}

Authorization

bearerAuth
AuthorizationBearer <token>

API key from Dashboard → Integrations → API, MCP and CLI.

In: header

Path Parameters

mediaId*string

Media id

srclang*string

Response Body

application/json

application/json

curl -X GET "https://example.com/media/string/captions/string"
{  "srclang": "string",  "label": "string",  "content": "string"}
{  "error": "string",  "message": "string"}

Delete a caption track

DELETE/media/{mediaId}/captions/{srclang}

Authorization

bearerAuth
AuthorizationBearer <token>

API key from Dashboard → Integrations → API, MCP and CLI.

In: header

Path Parameters

mediaId*string

Media id

srclang*string

Response Body

application/json

application/json

curl -X DELETE "https://example.com/media/string/captions/string"
{  "mediaId": "string",  "srclang": "string",  "deleted": true}
{  "error": "string",  "message": "string"}

List folders

GET/media-folders

Authorization

bearerAuth
AuthorizationBearer <token>

API key from Dashboard → Integrations → API, MCP and CLI.

In: header

Response Body

application/json

application/json

curl -X GET "https://example.com/media-folders"
{  "count": 0,  "folders": [    {      "id": "string",      "name": "string"    }  ]}
{  "error": "string",  "message": "string"}

Create a folder

POST/media-folders

Authorization

bearerAuth
AuthorizationBearer <token>

API key from Dashboard → Integrations → API, MCP and CLI.

In: header

Request Body

application/json

TypeScript Definitions

Use the request body type in TypeScript.

Response Body

application/json

application/json

curl -X POST "https://example.com/media-folders" \  -H "Content-Type: application/json" \  -d '{    "name": "string"  }'
{  "folder": {    "id": "string",    "name": "string"  }}
{  "error": "string",  "message": "string"}

Rename a media folder

PATCH/media-folders/{name}

Authorization

bearerAuth
AuthorizationBearer <token>

API key from Dashboard → Integrations → API, MCP and CLI.

In: header

Path Parameters

name*string

Folder name

Request Body

application/json

TypeScript Definitions

Use the request body type in TypeScript.

Renaming onto an existing folder MERGES into it (the old folder is removed).

Response Body

application/json

application/json

curl -X PATCH "https://example.com/media-folders/string" \  -H "Content-Type: application/json" \  -d '{    "newName": "string"  }'
{  "folder": {    "id": "string",    "name": "string"  },  "updatedItemCount": 0}
{  "error": "string",  "message": "string"}

Delete a folder

DELETE/media-folders/{name}

Authorization

bearerAuth
AuthorizationBearer <token>

API key from Dashboard → Integrations → API, MCP and CLI.

In: header

Path Parameters

name*string

Folder name

Response Body

application/json

application/json

curl -X DELETE "https://example.com/media-folders/string"
{  "docDeleted": true,  "unfiledItemCount": 0}
{  "error": "string",  "message": "string"}

Was this article helpful?

Related articles

Spotted something off? Tell us at support@zanfia.com.