---
title: "Create a project"
method: POST
path: "/v2/projects"
tags: ["Projects"]
---

# Create a project

`POST /v2/projects`

Creates a project and returns its `id`. Pass that `id` as `projectId` on `POST /v2/generate` or `POST /v2/assets` to group generations and assets under it in Studio. Supply your own `id` for idempotent creation: re-sending the same `id` returns the existing project (also as 201, indistinguishable from a fresh create) instead of creating a duplicate. On such a replay the other request fields are ignored; the first successful create wins.

## Request body

- CreateProjectDto
  - `id` string, uuid — Optional client-supplied project id (UUID) for idempotent creation. Re-sending the same id returns the existing project instead of creating a duplicate; the other request fields are ignored on such a replay. If the id is already used by a different user or organization, or by a deleted project, the request fails with 409.
  - `name` string, required
  - `description` string
  - `visibility` 'USER' | 'ORGANIZATION' — Who can see the project. Defaults to USER (visible only to the owner).
  - `mode` 'CREATOR' | 'DEVELOPER' — Project mode. Defaults to CREATOR.
  - `defaultWorkflow` 'lipsync' | 'translate_and_dub' | 'change_appearance' | 'image_to_video' | 'edit_dialogue' | 'assistant' | 'timeline' — Default top-level creator workflow for this project.

## Response `201`

Project created successfully, or the existing project when the supplied `id` was already created by the same user

- ProjectDto
  - `id` string, required
  - `createdAt` string, date-time, required
  - `updatedAt` string, date-time, required
  - `organizationId` string, required
  - `userId` string, nullable, required
  - `name` string, nullable, required
  - `description` string, nullable, required
  - `visibility` 'USER' | 'ORGANIZATION', required
  - `deletedAt` string, date-time, nullable, required
  - `mode` 'CREATOR' | 'DEVELOPER', required
  - `defaultWorkflow` 'lipsync' | 'translate_and_dub' | 'change_appearance' | 'image_to_video' | 'edit_dialogue' | 'assistant' | 'timeline' | 'null', nullable
  - `generations` object[], required
    - `id` string, required
    - `organizationId` string, required
    - `userId` string, nullable, required
    - `apiKeyId` string, nullable, required
    - `createdAt` string, date-time, required
    - `updatedAt` string, date-time, required
    - `startedAt` string, date-time, nullable, required
    - `finishedAt` string, date-time, nullable, required
    - `status` 'PENDING' | 'PROCESSING' | 'COMPLETED' | 'FAILED' | 'REJECTED', required
    - `model` object, required
      - `id` string, required
      - `name` string, required
      - `description` string, nullable, required
      - `type` string, required
      - `version` string, required
      - `features` string[]
      - `deprecatedAt` string, date-time, nullable, required
    - `modelName` string, required
    - `inputs` object[], required
      - `url` string, uri
      - `assetId` string
      - `type` 'video' | 'image' | 'audio' | 'text', required
      - `refId` string
      - `generatedBy` 'tts'
      - `segments_secs` array[]
        - number[]
      - `segments_frames` array[]
        - number[]
      - `trim_secs` number[]
      - `provider` object
        - `name` string, required
        - `script` string, required
        - `voiceId` string, required
        - `stability` number
        - `similarityBoost` number
    - `webhookUrl` string, nullable, required
    - `thumbnailUrl` string, nullable, required
    - `frameCount` number, nullable, required
    - `options` object, required
      - `prompt` union
        - 'happy' | 'sad' | 'angry' | 'disgusted' | 'surprised' | 'neutral'
        - string
      - `prompt_image_uris` string[]
      - `i2v_prompt` string
      - `system_prompt` string
      - `temperature` number, nullable
      - `sync_mode` 'cut_off' | 'bounce' | 'loop' | 'silence' | 'remap'
      - `model_mode` union
        - string
        - string
      - `active_speaker_detection` union
        - object
          - `auto_detect` boolean
          - `use_v2` boolean
          - `v3` boolean
          - `frame_number` number
          - `coordinates` number[]
          - `bounding_boxes` array[]
            - number[], nullable
          - `bounding_boxes_url` string
          - `face_image` string
        - boolean
      - `face_boxes_url` string
      - `occlusion_detection_enabled` boolean
      - `reasoning_enabled` boolean
      - `refinement_enabled` boolean
      - `blending_mode` 'default' | 'advanced' | 'disabled'
      - `output_file_name` string
      - `output_bucket_name` string
      - `output_bucket_path` string
      - `disable_blending` boolean
      - `pad_percent` number
      - `mask_uri` string
      - `mask_inner_box` integer[], nullable
      - `audio_guidance_scale` number, nullable
      - `num_steps` integer, nullable
      - `use_retinaface` boolean
      - `use_insightface` boolean
      - `disable_scene_detection` boolean
      - `extra_services_options` object
      - `original_audio_url` string
      - `occlusion_prompt` string
      - `rotate` number
      - `active_speaker` boolean
      - `speedup` number, nullable
      - `output_format` 'mp4' | 'mov'
      - `fps` number, nullable
      - `output_resolution` number[], nullable
      - `pads` number[]
      - `gb` number, nullable
      - `mb` number, nullable
      - `quality` string, nullable
      - `img_size` number[], nullable
      - `pickle_mode` string, nullable
      - `cf_batch_size` number, nullable
      - `resize_factor` number, nullable
      - `expressiveness` number, nullable
      - `inp_batch_size` number, nullable
      - `fidelity_weight` number, nullable
      - `wav2lip_batch_size` number, nullable
      - `face_det_batch_size` number, nullable
    - `segments` object[], nullable
      - `startTime` number
      - `endTime` number
      - `startFrame` number
      - `endFrame` number
      - `audioInput` object
        - `refId` string, required
        - `startTime` number
        - `endTime` number
      - `optionsOverride` object
        - `active_speaker_detection` object
          - `auto_detect` boolean
          - `use_v2` boolean
          - `v3` boolean
          - `frame_number` number
          - `coordinates` number[]
          - `bounding_boxes` array[]
            - number[], nullable
          - `bounding_boxes_url` string
          - `face_image` string
        - `sync_mode` 'cut_off' | 'bounce' | 'loop' | 'silence' | 'remap'
        - `occlusion_detection_enabled` boolean
        - `temperature` number
        - `disable_blending` boolean
        - `pad_percent` number
        - `mask_uri` string
        - `use_retinaface` boolean
        - `use_insightface` boolean
    - `outputMediaUrl` string, nullable, required
    - `segmentOutputMediaUrl` string, nullable, required
    - `segmentOutputBucketPath` string, nullable, required
    - `creatorName` string, nullable
    - `outputMediaLength` number, nullable, required
    - `potentialError` object, nullable, required
      - `status` number
      - `message` string, required
      - `errorCode` string
      - `docsLink` string, uri
    - `isPublic` boolean, nullable, required
    - `deletedAt` string, date-time, nullable, required
    - `projectId` string, nullable, required
    - `outputFileName` string, nullable
    - `outputExtension` string, nullable
  - `generationPresets` object[], required
    - `id` string, required
    - `name` string, required
    - `description` string, nullable, required
    - `model` object, required
      - `id` string, required
      - `name` string, required
      - `description` string, nullable, required
      - `type` string, required
      - `version` string, required
      - `features` string[]
      - `deprecatedAt` string, date-time, nullable, required
    - `modelName` string, required
    - `options` object, required
      - `prompt` union
        - 'happy' | 'sad' | 'angry' | 'disgusted' | 'surprised' | 'neutral'
        - string
      - `prompt_image_uris` string[]
      - `i2v_prompt` string
      - `system_prompt` string
      - `temperature` number, nullable
      - `sync_mode` 'cut_off' | 'bounce' | 'loop' | 'silence' | 'remap'
      - `model_mode` union
        - string
        - string
      - `active_speaker_detection` union
        - object
          - `auto_detect` boolean
          - `use_v2` boolean
          - `v3` boolean
          - `frame_number` number
          - `coordinates` number[]
          - `bounding_boxes` array[]
            - number[], nullable
          - `bounding_boxes_url` string
          - `face_image` string
        - boolean
      - `face_boxes_url` string
      - `occlusion_detection_enabled` boolean
      - `reasoning_enabled` boolean
      - `refinement_enabled` boolean
      - `blending_mode` 'default' | 'advanced' | 'disabled'
      - `output_file_name` string
      - `output_bucket_name` string
      - `output_bucket_path` string
      - `disable_blending` boolean
      - `pad_percent` number
      - `mask_uri` string
      - `mask_inner_box` integer[], nullable
      - `audio_guidance_scale` number, nullable
      - `num_steps` integer, nullable
      - `use_retinaface` boolean
      - `use_insightface` boolean
      - `disable_scene_detection` boolean
      - `extra_services_options` object
      - `original_audio_url` string
      - `occlusion_prompt` string
      - `rotate` number
      - `active_speaker` boolean
      - `speedup` number, nullable
      - `output_format` 'mp4' | 'mov'
      - `fps` number, nullable
      - `output_resolution` number[], nullable
      - `pads` number[]
      - `gb` number, nullable
      - `mb` number, nullable
      - `quality` string, nullable
      - `img_size` number[], nullable
      - `pickle_mode` string, nullable
      - `cf_batch_size` number, nullable
      - `resize_factor` number, nullable
      - `expressiveness` number, nullable
      - `inp_batch_size` number, nullable
      - `fidelity_weight` number, nullable
      - `wav2lip_batch_size` number, nullable
      - `face_det_batch_size` number, nullable

## Other responses

- `409` — The supplied `id` is already in use: it belongs to a different user or organization, or to a deleted project
- `422` — API key has no owner to assign as the project owner

## Changes

- **2026-07-31** `7a3982f507c9` — 1 warning, 1 info
  - added the new `edit_dialogue` enum value to the `defaultWorkflow` response property for the response status `201`
  - added the new `edit_dialogue` enum value to the request property `defaultWorkflow`

[Change history](https://skmtc.dev/sync/apis/sync-api-v2/changes/v2/projects/post.md)

---

[API](https://skmtc.dev/sync/apis/sync-api-v2.md) · [All operations](https://skmtc.dev/sync/apis/sync-api-v2/llms.txt) · [OpenAPI document](https://skmtc-service-production.skmtc.workers.dev/v1/apis/sync/sync-api-v2/revisions/7a3982f507c9/schema)
