---
title: "Fork a project"
method: POST
path: "/v1/apps/{appId}/forks"
tags: ["Projects"]
deprecated: true
---

# Fork a project

`POST /v1/apps/{appId}/forks`

## Request

- Base URL: `https://api.spice.ai`
- URL: `https://api.spice.ai/v1/apps/{appId}/forks`
- Auth: HTTP bearer

> **Deprecated.**

Legacy alias of `/v1/projects/{projectId}/forks`. Projects were previously called apps. Creates a new project from this project's configuration and records this project as its source. The fork copies the spicepod the project deploys, its linked connections, project secrets, linked organization secrets, update channel, version range, replica and executor counts, storage size, description, and tags. It does not copy API keys (new ones are generated), deployments, the GitHub repository link, the instance size, or visibility (forks are private). The fork is not deployed: deploy it with POST /v1/projects/{projectId}/deployments. Requires `apps:write`. The server copies secret values without returning them, so no secrets scope is needed. A source connected to a GitHub repository is read from that repository, and its spicepod is copied only when it loads no other file from the repository; to deploy a fork from a fork of the repository, fork the project in the Spice portal.

## Path parameters

- `appId` integer, required

## Headers

- `X-Org-Name` string

## Request body

- object
  - `name` string: Name of the fork. Defaults to the source name with `-fork`, then `-fork-2` and so on, whichever is free.
  - `region` 'us-east-1' | 'us-west-2': Region to place the fork in. Omit it and `cluster_name` to place the fork where the source runs.
  - `cluster_name` string: Dedicated cluster to place the fork on, as listed by `GET /v1/clusters`. If `region` is also set, it must match the cluster's region.
  - `scheduler_state_location` string: s3:// URI for the fork's scheduler state. Required when the source spicepod sets `runtime.scheduler.state_location`, and must not overlap it: two schedulers cannot share a location.
  - `default_alerts` boolean: Create default monitoring alerts for the new managed fork. False skips initial setup. Manual alert creation remains available.

## Response `201`

Project forked. It has not been deployed yet.

- object
  - `id` integer: Unique identifier for the project
  - `name` string: Name of the project
  - `kind` 'managed' | 'standalone' | 'byoc': Resolved project hosting model
  - `description` string, nullable: Description of the project
  - `visibility` 'public' | 'private': Visibility setting for the project
  - `created_at` string, date-time: Timestamp when the project was created
  - `cname` string, nullable: Region identifier
  - `cluster_name` string, nullable: Resolved dedicated cluster name; null for projects not assigned to a dedicated cluster.
  - `endpoint` string, nullable: The data-plane endpoint the project connects to, or null before a standalone instance is attached.
  - `production_branch` string, nullable: Production branch for the project
  - `api_key` string: Deprecated. Use the API Keys endpoints instead.
  - `tags` object, nullable: Key-value tags for the project
  - `forked_from` object, nullable: The project this project was forked from, while that project is live in the same organization. Null for a project that was not created as a fork.
    - `id` integer, required: ID of the source project
    - `name` string, required: Name of the source project
  - `paused_at` string, date-time, nullable: Timestamp when the project was paused; null while running
  - `warning` string, nullable: Present when the project was created but initial configuration could not be applied
  - `config` object, nullable: Runtime configuration; null for an unattached standalone project.
    - `spicepod` object, nullable: Spicepod configuration
    - `registry` string, nullable: Container registry for the runtime image
    - `image_tag` string, nullable: Runtime image tag
    - `update_channel` 'stable' | 'preview' | 'nightly' | 'null', nullable: Update channel for the runtime
    - `replicas` integer: Number of replicas
    - `resources` object, nullable: Resource requests and limits for the project container
      - `limits` object
        - `cpu` string: Whole-number vCPU limit, or '-' for no CPU limit
        - `memory` string: Memory limit in Gi (for example, 16Gi)
        - `ephemeral-storage` string
      - `requests` object
        - `cpu` string: CPU request. Minimum 100 millicores (for example, 100m or 0.1).
    - `executor` object, nullable: Executor container configuration
      - `replicas` integer: Number of executor replicas
      - `resources` object: Resource requests and limits for the executor container
        - `limits` object
          - `cpu` string: Whole-number vCPU limit, or '-' for no CPU limit
          - `memory` string: Memory limit in Gi (for example, 16Gi)
          - `ephemeral-storage` string
        - `requests` object
          - `cpu` string: CPU request. Minimum 100 millicores (for example, 100m or 0.1).
    - `region` string, nullable: Cloud region code (e.g., us-east-1)
    - `node_group` string, nullable: Node group for scheduling the project runtime
    - `storage_claim_size_gb` number, nullable: Storage claim size in GB
  - `shared_state` object[], required: Settings copied as they are that name external state the source also uses: a replication slot or Kafka consumer group the spicepod names, or a snapshot location. Change them in the fork's spicepod before deploying it if the two projects should not share that state.
    - `component` string, required: The dataset, or `snapshots`
    - `setting` string, required
    - `value` string, required

## Other responses

- `400`: Invalid project ID or request body, an unknown region or cluster, no `region` or `cluster_name` set for a source whose placement a fork cannot reuse (a BYOC cluster, a self-hosted runtime, or a region or cluster that is no longer available; `code: fork_placement_required`), or a missing or unusable `scheduler_state_location` (`code: scheduler_state_location_required`, `scheduler_state_location_unsupported`, `scheduler_state_location_overlaps_source`, or `scheduler_state_location_not_applicable`).
- `401`: Unauthorized
- `402`: The source runs models on hosted AI credits, which the organization has used up (`code: ai_credits_exhausted`).
- `403`: Insufficient scope, a viewer role, or the source runs more replicas or executors than the plan or the dedicated cluster allows
- `404`: Project or organization not found
- `409`: A project with the requested name already exists, another project creation is in progress, or every default name is taken (`code: fork_name_unavailable`)
- `413`: Request body too large
- `422`: The source has no spicepod (`code: fork_source_has_no_spicepod`), its spicepod is not valid (`code: fork_source_spicepod_invalid`), or its spicepod loads files from its GitHub repository besides spicepod.yaml (`code: fork_source_loads_repository_files`)
- `429`: Too many project creation requests (rate limited)
- `500`: The fork could not be created. When the failure comes after the project row is created, the fork is deleted again with its spicepod, secrets, and organization secret links. If the project itself cannot be deleted, the response has `code: fork_rollback_failed` and names the partially created project in `project` (`id` and `name`). Delete that project, by `project.id`, before reusing its name.
- `502`: The source is connected to a GitHub repository, and its spicepod could not be read from it (`code: fork_source_repository_unreadable`)

---

[API](https://skmtc.dev/spice/apis/spice-cloud-control-plane-api.md) - [All operations](https://skmtc.dev/spice/apis/spice-cloud-control-plane-api/llms.txt) - [OpenAPI document](https://skmtc.dev/spice/apis/spice-cloud-control-plane-api/revisions/5f3b75dd847d?raw)
