---
title: "Create project"
method: POST
path: "/v1/projects"
tags: ["projects"]
---

# Create project

`POST /v1/projects`

**Plan:** `All plans`

Creates a new project. Pass workspace_id in the request body.

## Request body

- union
  - PublicV1ProjectCreateInputBody
    - `description` string, required — Project description
    - `display_name` string — Human-facing project name
    - `ephemeral_files` V1UnscopedFile[], nullable — Deprecated (ENT-3330): both create-time file fields are slated for removal in favor of a unified attachment mechanism, but this is still the only supported way to attach uploads on create meanwhile. Ephemeral file references returned by POST /v1/files/ephemeral-upload-url; requires initial_message. file_id is the full "ephemeral/{user_id}/{uuid}" path; file_name/mime_type/type are carried through to the promoted file ref so the chat renderer keeps image-vs-file distinction. Copied into the new project's bucket and attached to the initial message after the project is created.
      - `file_id` string, required — Uploaded file ID
      - `file_name` string — Original file name
      - `mime_type` string — MIME type
      - `type` string — File type (e.g. user_upload)
    - `file_urls` string[], nullable — Public HTTPS image or HTML file URLs to fetch server-side and attach to the initial message. Currently supports JPEG, PNG, WebP, and HTML.
    - `files` V1UnscopedFile[], nullable — Deprecated (ENT-3330): both create-time file fields are slated for removal in favor of a unified attachment mechanism; use ephemeral_files meanwhile. Pre-uploaded user-scoped file references ("{user_id}/{uuid}/{name}" from the deprecated POST /v1/files/upload-url endpoint), attached in place without copying; requires initial_message.
      - `file_id` string, required — Uploaded file ID
      - `file_name` string — Original file name
      - `mime_type` string — MIME type
      - `type` string — File type (e.g. user_upload)
    - `headless` boolean — Headless mode for the initial message (no human-in-the-loop or interactive tools). Most workspaces run headless by default; setting false requires interactive API access for the workspace and is rejected with 403 otherwise.
    - `initial_message` string — Initial chat message to send after creation
    - `sandbox_template` string — Sandbox runtime template for the new project. Omit for the default stack; requires a workspace with access to the requested template.
    - `selected_libraries` V1SelectedLibrary[], nullable — Design system library projects to connect to the new project
      - `project_id` string, required — Library project ID
    - `source_project_id` string, nullable — Ignored when null, empty, or whitespace. Set a non-empty value to remix from a source project.
    - `tech_stack` string — Technology stack (default: vite)
    - `template_project_id` string — Template project ID to clone from (from list_template_projects)
    - `visibility` 'draft' | 'private' | 'public' | 'workspace_view' — Project visibility: draft, private, workspace_view, public
    - `workspace_id` string, required — Workspace ID
  - PublicV1ProjectRemixInputBody
    - `description` string — Project description
    - `display_name` string — Human-facing project name
    - `include_custom_knowledge` boolean — Whether remix-style creation should copy custom knowledge
    - `include_history` boolean — Whether remix-style creation should include chat history
    - `initial_message` string — Initial chat message to send after remix
    - `message_id` string — Message ID to remix from
    - `remix_mode` 'before' | 'including' — How to apply message_id: before starts before the message, including includes that message's completed turn. Defaults to including.
    - `skip_initial_remix_message` boolean — Suppress the default remix success message
    - `skip_integrations` boolean — Skip remixing integrations
    - `skip_preview_rebuild` boolean — Skip the post-push preview rebuild
    - `source_project_id` string, required — Source project ID for remix-style creation
    - `workspace_id` string, required — Workspace ID

## Response `200`

OK

- PublicV1CreateProjectResponse
  - `description` string — Description supplied by the caller on create or update
  - `display_name` string — Project display name
  - `id` string — Project ID
  - `is_published` boolean — Whether the project is published
  - `job_id` string — Remix job ID for tracking progress when source_project_id is provided
  - `latest_commit_sha` string — SHA of the latest commit
  - `latest_screenshot_url` string — URL of the latest screenshot
  - `message_id` string — User message ID, present when initial_message was provided
  - `name` string — Project slug
  - `preview_url` string — Static-preview URL for the project, on the workspace's branded host when it has one. Resolves once the first build completes. Absent on remix creates, which return job_id before the project exists.
  - `status` string — Project status. One of: in_progress, completed, failed. More values may be added; clients must tolerate unknown values.
  - `url` string — Published project URL
  - `visibility` string — Project visibility: draft, private, workspace_view, public
  - `workspace_id` string — Workspace ID

## Other responses

- `201` — Created
- `202` — Accepted
- `401` — Missing or invalid API key.
- `402` — This operation or requested configuration requires a workspace plan that includes this feature.
- `403` — The key or caller lacks the required scope or permission.
- `406` — The Accept header excludes every media type this endpoint produces.
- `429` — Too many requests. Retry after the interval in Retry-After when present.
- `default` — Error. The response body uses the standard error envelope; status matches the HTTP status code and type is a machine-readable error code.

---

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