Project Access
Every project folder is open by default: any member of the workspace can open it and see the videos filed inside. A project can instead be limited in one of two ways: restricted, which hides it and everything in it from everyone not listed, or read-only, which leaves it visible to the whole workspace while only the listed people can change anything in it.
Visibility and write rights are two separate axes. restricted answers "who can see this"; readonly answers "who can change this".
Access is reported and set through the access object on the create and update endpoints, and returned by get and list.
The access object
| Field | Type | Description |
|---|---|---|
mode | "workspace" | "restricted" | "readonly" | workspace (the default) means every member can open the project and change what's in it. restricted limits both to memberIds. readonly lets every member open and download what's in it, and limits changes to memberIds. |
memberIds | string[] | User IDs. Who may see the project when mode is restricted, and who may change it when mode is readonly. Not read when mode is workspace. |
{
"id": "0f7c1d8a-2c4b-4a9c-9f2a-1b8a3a5e0c11",
"name": "SOPs in review",
"access": {
"mode": "restricted",
"memberIds": ["68b4c2e1f0a9d4c7b2e10345", "68b4c2e1f0a9d4c7b2e10399"]
}
}
What a read-only project covers
A read-only project behaves exactly like an open one for reading. It appears in listings and search, its videos open in the editor, its articles and training material are readable, and the package ZIP still downloads — a viewer is expected to consume the content, that is the point of the mode.
What refuses, with 403 folder_read_only and a message saying why:
- Editing a video, its script, subtitles, article or training module, and generating or regenerating any of them
- Translating, generating voiceover, or re-analyzing
- Renaming, moving, duplicating or deleting a video, and filing anything new into the project
- Locking, unlocking, archiving and requesting approval
- Publishing: share links, Knowledge Center articles and external help centers
- Renaming or deleting the project itself
Two things deliberately stay open to everyone who can see the project, because neither changes the package: deciding an approval — approvers are named explicitly, and in a quality workflow the reviewer is often someone who reads a folder but never writes to it — and commenting, which is feedback about a package rather than part of it.
The refusal is 403, not 404, because the caller can see the item. A restricted project answers 404 instead, so its existence never leaks.
What a restriction covers
A restricted project disappears from project listings, video listings, and search for anyone not on the list. Requests for the project itself, or for a video filed inside it, return 404 not_found rather than 403 — someone who can't reach a project shouldn't learn that it exists.
Three things are deliberately not covered:
- Workspace owners and admins always have access, listed or not. Without that exemption a project could be stranded with nobody able to reach or repair it once its last listed member left the workspace.
- Videos that aren't filed in a project stay visible to the whole workspace. There is no folder to restrict them against, so content that needs protecting has to live in a restricted project.
- Public share links keep working. A share link is a deliberate act of publishing; restricting the project afterwards does not revoke links already handed out. Delete the share link to do that.
Where the check applies
Every endpoint that reads or acts on a video enforces it, not just the listings: analyze, export, translate, voiceover, article, subtitles, script, download, update, delete, the governance endpoints, and job polling for any of them. So do the endpoints that pull a video's content into something else - creating a remix, generating a training module, building a course, and publishing a Knowledge Center article from a video.
Moving a video into a restricted project is checked too, and so is filing anything new into one — a video, a studio project or a remix. Filing content somewhere you can't see is otherwise a way to hide it from the people who can, and filing into a read-only project is a change to a project you were only given read rights on.
Videos aren't the only thing filed in a project. Studio projects, remixes, and courses carry a project too, and hide with it on both the list and single-item endpoints.
API keys vs OAuth tokens
An API key authenticates as a workspace, not as a person, so it is not subject to project restrictions and can read every project in its workspace. Gate integrations with scopes rather than project access.
An OAuth token represents a real user, so it sees exactly what that user sees in the app: restricted projects they aren't on are filtered out of every response. Vidocu staff accounts are the exception, and keep the access they have in the dashboard.
Changing access
Setting access requires the workspace permission to manage members — the same right that governs inviting and removing people. Owners and admins have it; creators, editors, and viewers do not, and get 403 insufficient_role if they try.
An update that doesn't mention access leaves the existing setting alone, so renaming a project can never quietly open it up.
curl -X PATCH https://api.vidocu.ai/v1/projects/0f7c1d8a-2c4b-4a9c-9f2a-1b8a3a5e0c11 \
-H "Authorization: Bearer vdo_live_your_key_here" \
-H "Content-Type: application/json" \
-d '{
"access": {
"mode": "restricted",
"memberIds": ["68b4c2e1f0a9d4c7b2e10345"]
}
}'
To open a project back up, set mode to workspace:
curl -X PATCH https://api.vidocu.ai/v1/projects/0f7c1d8a-2c4b-4a9c-9f2a-1b8a3a5e0c11 \
-H "Authorization: Bearer vdo_live_your_key_here" \
-H "Content-Type: application/json" \
-d '{ "access": { "mode": "workspace" } }'
To make a project readable by everyone but editable by a few, use readonly with the people who may edit it:
curl -X PATCH https://api.vidocu.ai/v1/projects/0f7c1d8a-2c4b-4a9c-9f2a-1b8a3a5e0c11 \
-H "Authorization: Bearer vdo_live_your_key_here" \
-H "Content-Type: application/json" \
-d '{
"access": {
"mode": "readonly",
"memberIds": ["68b4c2e1f0a9d4c7b2e10345"]
}
}'