Appearance
Drive
Drive holds every finished generation's media plus files you add, organised in folders, with share links that play in Cinara's player.
- Finished generations are added to Drive when the first page of Drive is read. Results without media (transcripts, voices) aren't added.
- Removing a generated file from Drive keeps it in History.
- Deleting an uploaded file deletes it for good.
Drive is free.
Endpoints:
GET /v1/driveGET /v1/drive/foldersPOST /v1/drive/foldersPATCH /v1/drive/folders/{id}DELETE /v1/drive/folders/{id}POST /v1/drive/filesPATCH /v1/drive/files/{id}DELETE /v1/drive/files/{id}GET /v1/drive/sharesPOST /v1/drive/sharesDELETE /v1/drive/shares/{id}
The file object
json
{
"id": "4b9e2d7a-1c6f-4a3e-8d5b-0f7c3a9e2b61",
"name": "Paper Boats.mp3",
"source": "generation",
"module": "music",
"folderId": null,
"contentType": "audio/mpeg",
"sizeBytes": 3538944,
"createdAt": "2026-09-15T10:44:01.207733+00:00",
"generationId": "0b8f6d2e-5c1a-4e7b-9f3d-2a6c8e1b4d70",
"url": "https://api.cinara.ai/media/1789525441/k3JH9…/workspaces/…/music/…/song.mp3",
"downloadUrl": "https://api.cinara.ai/media/1789525441/k3JH9…/workspaces/…/music/…/song.mp3?download=Paper%20Boats.mp3",
"shared": false
}| Field | Type | Description |
|---|---|---|
id | string | The file's UUID. |
name | string | Display name. Generated files are named from the generation's own words (title, text, prompt, first line or file name), plus the file's label when a generation made several files. |
source | string | generation or upload. |
module | string or null | The feature that made it. null for uploads. |
folderId | string or null | null at the top level. |
contentType | string | An audio, video or image type. |
sizeBytes | integer | Size in bytes. 0 for speech and dialogue audio. |
createdAt | string | When the generation finished, or the file was added. |
generationId | string or null | The generation it came from. |
url | string | A signed link that plays the file. Expires after 6 hours. |
downloadUrl | string | The same link, saving the file under name. |
shared | boolean | Whether the file has an open share link. |
List a folder
GET /v1/drive
Lists a folder's subfolders and files. Reading the first page also adds generations finished since the last read.
Query parameters
| Name | Required | Description |
|---|---|---|
folderId | no | The folder to list. Omit for the top level. |
q | no | Only files and folders in this folder whose name contains these words (up to 100 characters). |
kind | no | Only one kind of file: audio, video, image, or upload (files you uploaded). Folders are left out. |
before | no | The previous page's nextBefore, to get the next page of files. Keep the same q and kind. |
Files are listed newest first, 100 per page. Folders are sorted by name and returned only on the first page.
An unknown kind returns 400 with kind must be one of audio, video, image, upload.
Response
200 OK
json
{
"path": [{ "id": "8d1f5a3c-7b2e-4c9a-a6d4-3e0b9f1c7a25", "name": "Course videos" }],
"folders": [
{ "id": "2a6c9e1f-4d7b-4e3a-b8c5-1f0d6a9e3b72", "name": "Week 1", "createdAt": "2026-09-14T11:02:44.093117+00:00", "shared": true }
],
"files": [
{
"id": "4b9e2d7a-1c6f-4a3e-8d5b-0f7c3a9e2b61",
"name": "Paper Boats.mp3",
"source": "generation",
"module": "music",
"folderId": "8d1f5a3c-7b2e-4c9a-a6d4-3e0b9f1c7a25",
"contentType": "audio/mpeg",
"sizeBytes": 3538944,
"createdAt": "2026-09-15T10:44:01.207733+00:00",
"generationId": "0b8f6d2e-5c1a-4e7b-9f3d-2a6c8e1b4d70",
"url": "https://api.cinara.ai/media/1789525441/k3JH9…/workspaces/…/song.mp3",
"downloadUrl": "https://api.cinara.ai/media/1789525441/k3JH9…/workspaces/…/song.mp3?download=Paper%20Boats.mp3",
"shared": false
}
],
"nextBefore": null
}path lists the folder and its parents, top level first. It's empty at the top level.
Errors
| Status | error | Message |
|---|---|---|
| 400 | invalid_request | That page of Drive can't be found |
| 404 | not_found | Folder not found |
Example
bash
curl "https://api.cinara.ai/v1/drive?folderId=8d1f5a3c-7b2e-4c9a-a6d4-3e0b9f1c7a25" \
-H "Authorization: Bearer $CINARA_API_KEY"Next page:
bash
curl "https://api.cinara.ai/v1/drive?before=$(jq -rn --arg b "$NEXT_BEFORE" '$b|@uri')" \
-H "Authorization: Bearer $CINARA_API_KEY"List all folders
GET /v1/drive/folders
Lists every folder in the workspace (up to 2,000), sorted by name. Useful for a folder picker.
Response
200 OK
json
{
"folders": [
{ "id": "8d1f5a3c-7b2e-4c9a-a6d4-3e0b9f1c7a25", "name": "Course videos", "parentId": null },
{ "id": "2a6c9e1f-4d7b-4e3a-b8c5-1f0d6a9e3b72", "name": "Week 1", "parentId": "8d1f5a3c-7b2e-4c9a-a6d4-3e0b9f1c7a25" }
]
}Example
bash
curl https://api.cinara.ai/v1/drive/folders \
-H "Authorization: Bearer $CINARA_API_KEY"Create a folder
POST /v1/drive/folders
Request body
| Field | Type | Required | Description |
|---|---|---|---|
name | string | yes | 1–120 characters. |
parentId | string | no | The parent folder. Omit or "" for the top level. |
Response
201 Created
json
{
"folder": {
"id": "2a6c9e1f-4d7b-4e3a-b8c5-1f0d6a9e3b72",
"name": "Week 1",
"parentId": "8d1f5a3c-7b2e-4c9a-a6d4-3e0b9f1c7a25",
"createdAt": "2026-09-14T11:02:44.093117+00:00"
}
}Errors
| Status | error | Message |
|---|---|---|
| 400 | invalid_request | Name the folder (up to 120 characters) |
| 404 | not_found | Folder not found |
Example
bash
curl -X POST https://api.cinara.ai/v1/drive/folders \
-H "Authorization: Bearer $CINARA_API_KEY" \
-H "Content-Type: application/json" \
-d '{"name": "Week 1", "parentId": "8d1f5a3c-7b2e-4c9a-a6d4-3e0b9f1c7a25"}'Update a folder
PATCH /v1/drive/folders/{id}
Renames or moves a folder.
Request body
Send at least one field.
| Field | Type | Description |
|---|---|---|
name | string | 1–120 characters. |
parentId | string or null | The new parent. null or "" moves it to the top level. A folder can't go inside itself or its own subfolders. |
Response
200 OK
json
{
"folder": {
"id": "2a6c9e1f-4d7b-4e3a-b8c5-1f0d6a9e3b72",
"name": "Week 1 – Basics",
"parentId": null,
"createdAt": "2026-09-14T11:02:44.093117+00:00"
}
}Errors
| Status | error | Message |
|---|---|---|
| 404 | not_found | Folder not found |
| 400 | invalid_request | Name the folder (up to 120 characters) |
| 400 | invalid_request | A folder can't go inside itself |
| 400 | invalid_request | Nothing to change |
Example
bash
curl -X PATCH "https://api.cinara.ai/v1/drive/folders/2a6c9e1f-4d7b-4e3a-b8c5-1f0d6a9e3b72" \
-H "Authorization: Bearer $CINARA_API_KEY" \
-H "Content-Type: application/json" \
-d '{"name": "Week 1 – Basics", "parentId": null}'Delete a folder
DELETE /v1/drive/folders/{id}
Deletes a folder. Its files and subfolders move up to its parent.
Response
200 OK
json
{ "ok": true, "movedTo": "8d1f5a3c-7b2e-4c9a-a6d4-3e0b9f1c7a25" }movedTo is the parent folder's id, or null for the top level.
Errors
| Status | error | Message |
|---|---|---|
| 404 | not_found | Folder not found |
Example
bash
curl -X DELETE "https://api.cinara.ai/v1/drive/folders/2a6c9e1f-4d7b-4e3a-b8c5-1f0d6a9e3b72" \
-H "Authorization: Bearer $CINARA_API_KEY"Add an uploaded file
POST /v1/drive/files
Adds a finished upload to Drive. Adding the same upload again returns the existing file.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
key | string | yes | The storage key of a finished audio, video or image upload. |
folderId | string | no | The folder. Omit or "" for the top level. |
name | string | no | Up to 200 characters. Defaults to the upload's file name. |
Response
201 Created, or 200 OK when the upload was already in Drive.
json
{
"file": {
"id": "9e4a1c7d-3b8f-4d2e-a6c9-5f0b2e8d1a47",
"name": "intro-music.mp3",
"source": "upload",
"module": null,
"folderId": null,
"contentType": "audio/mpeg",
"sizeBytes": 2210304,
"createdAt": "2026-09-15T22:01:33.580114+00:00",
"generationId": null,
"url": "https://api.cinara.ai/media/1789574493/Ty7uW…/workspaces/…/uploads/…/intro-music.mp3",
"downloadUrl": "https://api.cinara.ai/media/1789574493/Ty7uW…/workspaces/…/uploads/…/intro-music.mp3?download=intro-music.mp3",
"shared": false
}
}Errors
| Status | error | Message |
|---|---|---|
| 400 | invalid_request | Upload a file first |
| 404 | not_found | That upload isn't finished. Upload the file again. |
| 400 | invalid_request | Drive holds audio, video and images |
| 404 | not_found | Folder not found |
Example
bash
curl -X POST https://api.cinara.ai/v1/drive/files \
-H "Authorization: Bearer $CINARA_API_KEY" \
-H "Content-Type: application/json" \
-d '{"key": "workspaces/3f6b2a1c-8d4e-4b7a-9c2d-5e1f0a9b8c7d/uploads/7d2a9f4c-6e1b-4c8a-b3d7-0a5e9c2f4b18/intro-music.mp3"}'Update a file
PATCH /v1/drive/files/{id}
Renames a file or moves it to another folder.
Request body
Send at least one field.
| Field | Type | Description |
|---|---|---|
name | string | 1–200 characters. |
folderId | string or null | The new folder. null or "" moves it to the top level. |
Response
200 OK with the updated file object: { "file": {…} }. In this response shared is always false.
Errors
| Status | error | Message |
|---|---|---|
| 404 | not_found | File not found |
| 400 | invalid_request | Name the file (up to 200 characters) |
| 404 | not_found | Folder not found |
| 400 | invalid_request | Nothing to change |
Example
bash
curl -X PATCH "https://api.cinara.ai/v1/drive/files/4b9e2d7a-1c6f-4a3e-8d5b-0f7c3a9e2b61" \
-H "Authorization: Bearer $CINARA_API_KEY" \
-H "Content-Type: application/json" \
-d '{"name": "Paper Boats (final).mp3", "folderId": "8d1f5a3c-7b2e-4c9a-a6d4-3e0b9f1c7a25"}'Delete a file
DELETE /v1/drive/files/{id}
Removes a file from Drive and deletes its share links.
- An uploaded file is deleted for good, including the stored media. Jobs that used the same upload can no longer link to it.
- A generated file only leaves Drive. It stays in History and doesn't come back to Drive.
Response
200 OK
json
{ "ok": true }Errors
| Status | error | Message |
|---|---|---|
| 404 | not_found | File not found |
Example
bash
curl -X DELETE "https://api.cinara.ai/v1/drive/files/9e4a1c7d-3b8f-4d2e-a6c9-5f0b2e8d1a47" \
-H "Authorization: Bearer $CINARA_API_KEY"Share links
A share link opens a file or a folder in Cinara's player without signing in. A folder link plays its files (up to 200) as a playlist. Downloads are offered only when allowDownload is true.
The share object
json
{
"id": "6f3b8d1a-2e7c-4a9b-b5d4-9c0e3f7a1b26",
"url": "https://app.cinara.ai/s/Xq7Lm2Pz9Rt4Vw8Ka3Nc5Hd1",
"fileId": null,
"folderId": "2a6c9e1f-4d7b-4e3a-b8c5-1f0d6a9e3b72",
"allowDownload": false,
"expiresAt": "2026-09-22T22:15:08.227Z",
"revokedAt": null,
"views": 14,
"createdAt": "2026-09-15T22:15:08.231905+00:00",
"open": true
}| Field | Description |
|---|---|
url | The link to share. |
fileId / folderId | What's shared. Exactly one is set. |
allowDownload | Whether viewers can download. |
expiresAt | When the link stops working, or null for no expiry. |
revokedAt | When the link was turned off. |
views | How many times the link was opened. |
open | true when not revoked and not expired. |
List share links
GET /v1/drive/shares
Lists every link (open and closed) for one file or folder, newest first.
Query parameters
| Name | Required | Description |
|---|---|---|
fileId | one of | A file's UUID. |
folderId | one of | A folder's UUID. Used when fileId isn't given. |
Response
200 OK
json
{
"shares": [
{
"id": "6f3b8d1a-2e7c-4a9b-b5d4-9c0e3f7a1b26",
"url": "https://app.cinara.ai/s/Xq7Lm2Pz9Rt4Vw8Ka3Nc5Hd1",
"fileId": null,
"folderId": "2a6c9e1f-4d7b-4e3a-b8c5-1f0d6a9e3b72",
"allowDownload": false,
"expiresAt": "2026-09-22T22:15:08.227Z",
"revokedAt": null,
"views": 14,
"createdAt": "2026-09-15T22:15:08.231905+00:00",
"open": true
}
]
}Errors
| Status | error | Message |
|---|---|---|
| 400 | invalid_request | Choose a file or folder |
Example
bash
curl "https://api.cinara.ai/v1/drive/shares?folderId=2a6c9e1f-4d7b-4e3a-b8c5-1f0d6a9e3b72" \
-H "Authorization: Bearer $CINARA_API_KEY"Create a share link
POST /v1/drive/shares
Creates a link for one file or one folder.
Needs a verified phone.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
fileId | string | one of | A file's UUID. |
folderId | string | one of | A folder's UUID. Send exactly one of fileId and folderId. |
expiresInDays | integer | no | 7, 30, or 0 (default) for a link that lasts until you turn it off. |
allowDownload | boolean | no | Let viewers download. Default false. |
Response
201 Created
json
{
"share": {
"id": "6f3b8d1a-2e7c-4a9b-b5d4-9c0e3f7a1b26",
"url": "https://app.cinara.ai/s/Xq7Lm2Pz9Rt4Vw8Ka3Nc5Hd1",
"fileId": null,
"folderId": "2a6c9e1f-4d7b-4e3a-b8c5-1f0d6a9e3b72",
"allowDownload": false,
"expiresAt": "2026-09-22T22:15:08.227Z",
"revokedAt": null,
"views": 0,
"createdAt": "2026-09-15T22:15:08.231905+00:00",
"open": true
}
}Errors
| Status | error | Message |
|---|---|---|
| 400 | invalid_request | Share one file or one folder |
| 404 | not_found | File not found |
| 404 | not_found | Folder not found |
| 400 | invalid_request | Links can last 7 days, 30 days or until you turn them off |
| 403 | phone_unverified | Verify your phone number to start creating. |
Example
bash
curl -X POST https://api.cinara.ai/v1/drive/shares \
-H "Authorization: Bearer $CINARA_API_KEY" \
-H "Content-Type: application/json" \
-d '{"folderId": "2a6c9e1f-4d7b-4e3a-b8c5-1f0d6a9e3b72", "expiresInDays": 7}'Turn off a share link
DELETE /v1/drive/shares/{id}
Turns a link off. The link stays in the list with revokedAt set.
Response
200 OK
json
{
"share": {
"id": "6f3b8d1a-2e7c-4a9b-b5d4-9c0e3f7a1b26",
"url": "https://app.cinara.ai/s/Xq7Lm2Pz9Rt4Vw8Ka3Nc5Hd1",
"fileId": null,
"folderId": "2a6c9e1f-4d7b-4e3a-b8c5-1f0d6a9e3b72",
"allowDownload": false,
"expiresAt": "2026-09-22T22:15:08.227Z",
"revokedAt": "2026-09-16T08:00:41.019Z",
"views": 14,
"createdAt": "2026-09-15T22:15:08.231905+00:00",
"open": false
}
}Errors
| Status | error | Message |
|---|---|---|
| 404 | not_found | Link not found (unknown or already turned off) |
Example
bash
curl -X DELETE "https://api.cinara.ai/v1/drive/shares/6f3b8d1a-2e7c-4a9b-b5d4-9c0e3f7a1b26" \
-H "Authorization: Bearer $CINARA_API_KEY"