Projects
By default, a generation created from the API isn’t filed under anything in particular. Projects let you group related generations and assets together so they appear under one project in the Studio — and so you can list them back out from the API. It’s a two-way road: create a project from the API, attach work to it, and it’s visible in the Studio UI; create a project in Studio, and the API can attach to it too.
A project is lightweight — only a name is required.
Create a project
POST /v2/projects returns the new project’s id. visibility defaults to USER (visible only to the key owner) and mode to CREATOR; both are optional.
To make project creation safe to retry, send your own UUID in id. Reusing it returns the existing project and ignores the other fields. An ID belonging to another user or organization, or to a deleted project, returns 409.
You can set defaultWorkflow when creating or updating a project. It selects the Studio workflow, such as lipsync, translate_and_dub, image_to_video, or edit_dialogue; it does not change generation inputs.
Attach generations and assets
Pass the project’s id as projectId when you create a generation or register an asset. The field is optional on both endpoints — omit it and the work simply isn’t grouped under a project.
The generation and asset responses echo back the projectId they were filed under (or null when none was given).
projectId must reference a project in your organization. If it doesn’t (wrong id, or a project from another org), the create request is rejected with 422 Unprocessable Entity — the generation or asset is not created. A missing or null projectId is always fine.
Attach an existing asset
If an asset already exists — say, one you uploaded earlier or picked from your library — you can attach it to a project after the fact with POST /v2/projects/{id}/assets, passing the asset’s id as assetId in the body. The asset must belong to your organization. This is the counterpart to setting projectId at creation time: use it to file work you didn’t group up front.
The call is idempotent — attaching an asset that is already linked to the project succeeds without creating a duplicate — and returns 204 No Content on success. A project or asset that isn’t in your organization returns 404 Not Found.
List a project’s generations
To pick up a project’s work again from the API, pass its id as projectId to GET /v2/generations. Add limit to get results newest first in pages of up to 100, then pass the last generation’s id as cursor to fetch the next page.
The filter returns every generation in the project, including ones created with any API key in your organization. Which projects you can read depends on their visibility:
If the project is private to someone else, deleted, or in another organization, the request returns an empty list instead of an error. A projectId that isn’t a UUID returns 400 Bad Request.
See it in Studio
Once attached, generations and assets show up under the project in the Studio. This works in both directions — a project you create in Studio can be targeted from the API by its id, and a project you create from the API appears in Studio. Deleting a project soft-deletes the project and its generations and removes its asset links. Assets with no other active project are also soft-deleted. Assets linked to another active project are retained. Soft-deleted records are no longer available through normal API reads.
You can’t delete a project while any of its generations are still queued or processing — the request is rejected with 409 Conflict and nothing is deleted. Wait for those generations to reach a terminal state (COMPLETED, FAILED, or REJECTED), then retry the delete. Once all of a project’s generations are terminal, deletion works normally.
Detach an asset from draft content
DELETE /v2/projects/{id}/assets/{assetId} returns 204 with no body. It removes the asset from the project’s draft content, including its thumbnail, while preserving the asset in the project asset library and retaining its access grants. Reattaching the asset restores the link.
The operation is idempotent: detaching an absent or already detached link also succeeds. An inaccessible project returns 404. An API key without an owner returns 422. This is different from deleting a project or deleting an asset.
Manage projects
GET /v2/projects is cursor-paginated (limit, cursor) and supports searchQuery (by name) and sortBy (updatedAt or name). PATCH only changes the fields you send.

