> For the complete documentation index, see [llms.txt](https://docs.spice.ai/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.spice.ai/api/management-api/management/projects.md).

# Projects

Manage projects and their configurations

## List projects

> Returns projects belonging to the authenticated organization. Page with \`limit\` (default 1000, max 1000). Prefer \`after\_id\` for a stable keyset (descending \`id\`). \`offset\` is accepted for compatibility. PostgREST also caps a page at 1000 rows.<br>

```json
{"openapi":"3.1.0","info":{"title":"Spice Cloud Control-Plane API","version":"v1"},"tags":[{"name":"Projects","description":"Manage projects and their configurations"}],"servers":[{"url":"https://api.spice.ai"}],"security":[{"BearerAuth":[]}],"components":{"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"OAuth 2.0 access token obtained from the Spice.ai authentication service"}},"parameters":{"OrgName":{"in":"header","name":"X-Org-Name","required":false,"description":"The organization to act on, by handle. Omit it to act on the organization the credential is bound to; sending it blank is a 400, not the same as omitting it. A user credential may name any organization its owner belongs to; a machine credential is pinned to its own.\n","schema":{"type":"string","pattern":"^[A-Za-z0-9._-]{1,255}$"}}},"schemas":{"Project":{"type":"object","properties":{"id":{"type":"integer","description":"Unique identifier for the project"},"name":{"type":"string","description":"Name of the project"},"kind":{"type":"string","enum":["managed","standalone","byoc"],"description":"Resolved project hosting model"},"description":{"type":"string","nullable":true,"description":"Description of the project"},"visibility":{"type":"string","enum":["public","private"],"description":"Visibility setting for the project"},"created_at":{"type":"string","format":"date-time","description":"Timestamp when the project was created"},"cname":{"type":"string","nullable":true,"description":"Region identifier"},"cluster_name":{"type":"string","nullable":true,"description":"Resolved dedicated cluster name; null for projects not assigned to a dedicated cluster."},"endpoint":{"type":"string","nullable":true,"description":"The data-plane endpoint the project connects to, or null before a standalone instance is attached."},"tags":{"type":"object","additionalProperties":{"type":"string"},"nullable":true,"description":"Key-value tags for the project"}}}}},"paths":{"/v1/projects":{"get":{"summary":"List projects","description":"Returns projects belonging to the authenticated organization. Page with `limit` (default 1000, max 1000). Prefer `after_id` for a stable keyset (descending `id`). `offset` is accepted for compatibility. PostgREST also caps a page at 1000 rows.\n","parameters":[{"in":"query","name":"limit","schema":{"type":"integer","minimum":1,"maximum":1000,"default":1000},"description":"Maximum number of projects to return"},{"in":"query","name":"offset","schema":{"type":"integer","minimum":0,"default":0},"description":"Number of projects to skip when a cursor is not supplied"},{"in":"query","name":"after_id","schema":{"type":"integer","minimum":1},"description":"Return projects with a strictly smaller id than this value."},{"$ref":"#/components/parameters/OrgName"}],"responses":{"200":{"description":"List of projects","content":{"application/json":{"schema":{"type":"object","properties":{"projects":{"type":"array","items":{"$ref":"#/components/schemas/Project"}}}}}}},"400":{"description":"Invalid limit, offset, or after_id"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient scope"}},"tags":["Projects"]}}}}
```

## Create a project

> Creates a new project in the authenticated organization.

```json
{"openapi":"3.1.0","info":{"title":"Spice Cloud Control-Plane API","version":"v1"},"tags":[{"name":"Projects","description":"Manage projects and their configurations"}],"servers":[{"url":"https://api.spice.ai"}],"security":[{"BearerAuth":[]}],"components":{"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"OAuth 2.0 access token obtained from the Spice.ai authentication service"}},"schemas":{"ProjectWithConfig":{"type":"object","properties":{"id":{"type":"integer","description":"Unique identifier for the project"},"name":{"type":"string","description":"Name of the project"},"kind":{"type":"string","enum":["managed","standalone","byoc"],"description":"Resolved project hosting model"},"description":{"type":"string","nullable":true,"description":"Description of the project"},"visibility":{"type":"string","enum":["public","private"],"description":"Visibility setting for the project"},"created_at":{"type":"string","format":"date-time","description":"Timestamp when the project was created"},"cname":{"type":"string","nullable":true,"description":"Region identifier"},"cluster_name":{"type":"string","nullable":true,"description":"Resolved dedicated cluster name; null for projects not assigned to a dedicated cluster."},"endpoint":{"type":"string","nullable":true,"description":"The data-plane endpoint the project connects to, or null before a standalone instance is attached."},"production_branch":{"type":"string","nullable":true,"description":"Production branch for the project"},"api_key":{"type":"string","deprecated":true,"description":"Deprecated. Use the API Keys endpoints instead."},"tags":{"type":"object","additionalProperties":{"type":"string"},"nullable":true,"description":"Key-value tags for the project"},"paused_at":{"type":"string","format":"date-time","nullable":true,"description":"Timestamp when the project was paused; null while running"},"warning":{"type":"string","nullable":true,"description":"Present when the project was created but initial configuration could not be applied"},"config":{"type":"object","nullable":true,"description":"Runtime configuration; null for an unattached standalone project.","properties":{"spicepod":{"type":"object","nullable":true,"description":"Spicepod configuration"},"registry":{"type":"string","nullable":true,"description":"Container registry for the runtime image"},"image_tag":{"type":"string","nullable":true,"description":"Runtime image tag"},"update_channel":{"type":"string","enum":["stable","preview","nightly"],"nullable":true,"description":"Update channel for the runtime"},"replicas":{"type":"integer","description":"Number of replicas"},"resources":{"type":"object","nullable":true,"description":"Resource requests and limits for the project container","properties":{"limits":{"type":"object","properties":{"cpu":{"type":"string","description":"Whole-number vCPU limit, or '-' for no CPU limit"},"memory":{"type":"string","description":"Memory limit in Gi (for example, 16Gi)"},"ephemeral-storage":{"type":"string"}}},"requests":{"type":"object","properties":{"cpu":{"type":"string","description":"CPU request. Minimum 100 millicores (for example, 100m or 0.1)."},"memory":{"type":"string","description":"Memory request. Minimum 192Mi."}}}}},"executor":{"type":"object","nullable":true,"description":"Executor container configuration","properties":{"replicas":{"type":"integer","description":"Number of executor replicas"},"resources":{"type":"object","description":"Resource requests and limits for the executor container","properties":{"limits":{"type":"object","properties":{"cpu":{"type":"string","description":"Whole-number vCPU limit, or '-' for no CPU limit"},"memory":{"type":"string","description":"Memory limit in Gi (for example, 16Gi)"},"ephemeral-storage":{"type":"string"}}},"requests":{"type":"object","properties":{"cpu":{"type":"string","description":"CPU request. Minimum 100 millicores (for example, 100m or 0.1)."},"memory":{"type":"string","description":"Memory request. Minimum 192Mi."}}}}}}},"region":{"type":"string","nullable":true,"description":"Cloud region code (e.g., us-east-1)"},"node_group":{"type":"string","nullable":true,"description":"Node group for scheduling the project runtime"},"storage_claim_size_gb":{"type":"number","nullable":true,"description":"Storage claim size in GB"}}}}}},"parameters":{"OrgName":{"in":"header","name":"X-Org-Name","required":false,"description":"The organization to act on, by handle. Omit it to act on the organization the credential is bound to; sending it blank is a 400, not the same as omitting it. A user credential may name any organization its owner belongs to; a machine credential is pinned to its own.\n","schema":{"type":"string","pattern":"^[A-Za-z0-9._-]{1,255}$"}}}},"paths":{"/v1/projects":{"post":{"summary":"Create a project","description":"Creates a new project in the authenticated organization.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name"],"properties":{"name":{"type":"string","minLength":4,"pattern":"^[a-zA-Z0-9-]+$","description":"Project name (letters, numbers, hyphens only)"},"region":{"type":"string","enum":["us-east-1","us-west-2"],"description":"Cloud region where a managed project will be deployed (e.g. `us-east-1`). Omit this, `cname`, and `cluster_name` to create an unattached standalone project whose placement is resolved when linked.\n"},"cname":{"type":"string","description":"**Deprecated.** Internal region CNAME (e.g. `us-east-1-prod-aws-data`). Use `region` instead. Accepted for backwards compatibility when `region` is omitted. Omit all region sources to create an unattached standalone project.\n"},"cluster_name":{"type":"string","description":"Name of the dedicated cluster to deploy to, as listed by `GET /v1/clusters`. Provide exactly one of `region` or `cluster_name`. When set, the region/routing are derived from the cluster; if `region` is also provided it must match the cluster's region. Omit all region sources to create an unattached standalone project.\n"},"description":{"type":"string","description":"Project description"},"visibility":{"type":"string","enum":["public","private"],"default":"private"},"tags":{"type":"object","additionalProperties":{"type":"string"},"description":"Key-value tags for the project"},"update_channel":{"type":"string","enum":["stable","preview","nightly"],"description":"Update channel for a managed project deployment. A standalone project has no spicepod until linking, so configure its channel after linking."},"replicas":{"type":"integer","minimum":0,"description":"Number of replicas for a managed project. Rejected for standalone projects."},"resources":{"type":"object","description":"Resource requests and limits for a managed project container. Rejected for standalone projects.","properties":{"limits":{"type":"object","properties":{"cpu":{"type":"string","description":"Whole-number vCPU limit, or '-' for no CPU limit"},"memory":{"type":"string","description":"Memory limit in Gi (for example, 16Gi)"},"ephemeral-storage":{"type":"string","description":"Ephemeral storage limit in Gi (for example, 8Gi)"}}},"requests":{"type":"object","properties":{"cpu":{"type":"string","description":"CPU request. Minimum 100 millicores (for example, 100m or 0.1)."},"memory":{"type":"string","description":"Memory request. Minimum 192Mi."}}}}},"executor":{"type":"object","description":"Executor container configuration for a managed project. Rejected for standalone projects.","properties":{"replicas":{"type":"integer","minimum":0,"description":"Number of executor replicas"},"resources":{"type":"object","description":"Resource requests and limits for the executor container","properties":{"limits":{"type":"object","properties":{"cpu":{"type":"string","description":"Whole-number vCPU limit, or '-' for no CPU limit"},"memory":{"type":"string","description":"Memory limit in Gi (for example, 16Gi)"},"ephemeral-storage":{"type":"string","description":"Ephemeral storage limit in Gi (for example, 8Gi)"}}},"requests":{"type":"object","properties":{"cpu":{"type":"string","description":"CPU request. Minimum 100 millicores (for example, 100m or 0.1)."},"memory":{"type":"string","description":"Memory request. Minimum 192Mi."}}}}}}}}}}}},"responses":{"201":{"description":"Project created successfully. The response may include a `warning` field if initial configuration could not be applied.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectWithConfig"}}}},"400":{"description":"Invalid request body or invalid region"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient scope, dedicated-cluster assignment or special-org private-compute ceilings required for resource limits, or requested resources exceed dedicated-cluster capacity"},"409":{"description":"A project with this name already exists"},"429":{"description":"Too many project creation requests (rate limited)"},"500":{"description":"Project creation failed, including when the name-collision check could not be read","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Generic failure reason; the underlying cause stays in the server logs"}}}}}}},"tags":["Projects"],"parameters":[{"$ref":"#/components/parameters/OrgName"}]}}}}
```

## Get a project

> Returns details for a specific project, including its configuration.

```json
{"openapi":"3.1.0","info":{"title":"Spice Cloud Control-Plane API","version":"v1"},"tags":[{"name":"Projects","description":"Manage projects and their configurations"}],"servers":[{"url":"https://api.spice.ai"}],"security":[{"BearerAuth":[]}],"components":{"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"OAuth 2.0 access token obtained from the Spice.ai authentication service"}},"parameters":{"OrgName":{"in":"header","name":"X-Org-Name","required":false,"description":"The organization to act on, by handle. Omit it to act on the organization the credential is bound to; sending it blank is a 400, not the same as omitting it. A user credential may name any organization its owner belongs to; a machine credential is pinned to its own.\n","schema":{"type":"string","pattern":"^[A-Za-z0-9._-]{1,255}$"}}}},"paths":{"/v1/projects/{projectId}":{"get":{"summary":"Get a project","description":"Returns details for a specific project, including its configuration.","parameters":[{"in":"path","name":"projectId","required":true,"schema":{"type":"integer"},"description":"The ID of the project"},{"$ref":"#/components/parameters/OrgName"}],"responses":{"200":{"description":"Project details with configuration","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"integer"},"name":{"type":"string"},"kind":{"type":"string","enum":["managed","standalone","byoc"],"description":"Resolved project hosting model"},"description":{"type":"string"},"visibility":{"type":"string","enum":["public","private"]},"created_at":{"type":"string","format":"date-time"},"cluster_name":{"type":"string","nullable":true,"description":"Resolved dedicated cluster name; null for projects not assigned to a dedicated cluster."},"endpoint":{"type":"string","nullable":true,"description":"The data-plane endpoint the project connects to, or null before a standalone instance is attached."},"production_branch":{"type":"string"},"api_key":{"type":"string","deprecated":true,"description":"Deprecated. Use the API Keys endpoints instead."},"tags":{"type":"object","additionalProperties":{"type":"string"}},"paused_at":{"type":"string","format":"date-time","nullable":true,"description":"Timestamp when the project was paused; null while running"},"config":{"type":"object","properties":{"spicepod":{"type":"object"},"image_tag":{"type":"string","description":"Runtime image tag"},"update_channel":{"type":"string","enum":["stable","preview","nightly"],"nullable":true,"description":"Update channel for the runtime, or null when Spice operates this project's runtime updates."},"version":{"type":"string","description":"Semver range for the runtime version (e.g. 1.x, 2.x)"},"replicas":{"type":"integer"},"resources":{"type":"object","nullable":true,"description":"Resource requests and limits for the project container","properties":{"limits":{"type":"object","properties":{"cpu":{"type":"string","description":"Whole-number vCPU limit, or '-' for no CPU limit"},"memory":{"type":"string","description":"Memory limit in Gi (for example, 16Gi)"},"ephemeral-storage":{"type":"string"}}},"requests":{"type":"object","properties":{"cpu":{"type":"string","description":"CPU request. Minimum 100 millicores (for example, 100m or 0.1)."},"memory":{"type":"string","description":"Memory request. Minimum 192Mi."}}}}},"executor":{"type":"object","nullable":true,"description":"Executor container configuration","properties":{"replicas":{"type":"integer","description":"Number of executor replicas"},"resources":{"type":"object","description":"Resource requests and limits for the executor container","properties":{"limits":{"type":"object","properties":{"cpu":{"type":"string","description":"Whole-number vCPU limit, or '-' for no CPU limit"},"memory":{"type":"string","description":"Memory limit in Gi (for example, 16Gi)"},"ephemeral-storage":{"type":"string"}}},"requests":{"type":"object","properties":{"cpu":{"type":"string","description":"CPU request. Minimum 100 millicores (for example, 100m or 0.1)."},"memory":{"type":"string","description":"Memory request. Minimum 192Mi."}}}}},"storage_size_gb":{"type":"number","nullable":true}}},"region":{"type":"string","nullable":true,"description":"Server-resolved region; null before a standalone instance is attached."},"storage_size_gb":{"type":"number","nullable":true},"storage_claim_size_gb":{"type":"number","deprecated":true,"description":"Deprecated. Use storage_size_gb instead."}}}}}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient scope"},"404":{"description":"Project not found"},"500":{"description":"Internal server error"}},"tags":["Projects"]}}}}
```

## Update a project

> Updates a project's metadata and configuration, including description, visibility, spicepod configuration, replicas, and resource limits.

```json
{"openapi":"3.1.0","info":{"title":"Spice Cloud Control-Plane API","version":"v1"},"tags":[{"name":"Projects","description":"Manage projects and their configurations"}],"servers":[{"url":"https://api.spice.ai"}],"security":[{"BearerAuth":[]}],"components":{"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"OAuth 2.0 access token obtained from the Spice.ai authentication service"}},"parameters":{"OrgName":{"in":"header","name":"X-Org-Name","required":false,"description":"The organization to act on, by handle. Omit it to act on the organization the credential is bound to; sending it blank is a 400, not the same as omitting it. A user credential may name any organization its owner belongs to; a machine credential is pinned to its own.\n","schema":{"type":"string","pattern":"^[A-Za-z0-9._-]{1,255}$"}}},"schemas":{"ProjectWithConfig":{"type":"object","properties":{"id":{"type":"integer","description":"Unique identifier for the project"},"name":{"type":"string","description":"Name of the project"},"kind":{"type":"string","enum":["managed","standalone","byoc"],"description":"Resolved project hosting model"},"description":{"type":"string","nullable":true,"description":"Description of the project"},"visibility":{"type":"string","enum":["public","private"],"description":"Visibility setting for the project"},"created_at":{"type":"string","format":"date-time","description":"Timestamp when the project was created"},"cname":{"type":"string","nullable":true,"description":"Region identifier"},"cluster_name":{"type":"string","nullable":true,"description":"Resolved dedicated cluster name; null for projects not assigned to a dedicated cluster."},"endpoint":{"type":"string","nullable":true,"description":"The data-plane endpoint the project connects to, or null before a standalone instance is attached."},"production_branch":{"type":"string","nullable":true,"description":"Production branch for the project"},"api_key":{"type":"string","deprecated":true,"description":"Deprecated. Use the API Keys endpoints instead."},"tags":{"type":"object","additionalProperties":{"type":"string"},"nullable":true,"description":"Key-value tags for the project"},"paused_at":{"type":"string","format":"date-time","nullable":true,"description":"Timestamp when the project was paused; null while running"},"warning":{"type":"string","nullable":true,"description":"Present when the project was created but initial configuration could not be applied"},"config":{"type":"object","nullable":true,"description":"Runtime configuration; null for an unattached standalone project.","properties":{"spicepod":{"type":"object","nullable":true,"description":"Spicepod configuration"},"registry":{"type":"string","nullable":true,"description":"Container registry for the runtime image"},"image_tag":{"type":"string","nullable":true,"description":"Runtime image tag"},"update_channel":{"type":"string","enum":["stable","preview","nightly"],"nullable":true,"description":"Update channel for the runtime"},"replicas":{"type":"integer","description":"Number of replicas"},"resources":{"type":"object","nullable":true,"description":"Resource requests and limits for the project container","properties":{"limits":{"type":"object","properties":{"cpu":{"type":"string","description":"Whole-number vCPU limit, or '-' for no CPU limit"},"memory":{"type":"string","description":"Memory limit in Gi (for example, 16Gi)"},"ephemeral-storage":{"type":"string"}}},"requests":{"type":"object","properties":{"cpu":{"type":"string","description":"CPU request. Minimum 100 millicores (for example, 100m or 0.1)."},"memory":{"type":"string","description":"Memory request. Minimum 192Mi."}}}}},"executor":{"type":"object","nullable":true,"description":"Executor container configuration","properties":{"replicas":{"type":"integer","description":"Number of executor replicas"},"resources":{"type":"object","description":"Resource requests and limits for the executor container","properties":{"limits":{"type":"object","properties":{"cpu":{"type":"string","description":"Whole-number vCPU limit, or '-' for no CPU limit"},"memory":{"type":"string","description":"Memory limit in Gi (for example, 16Gi)"},"ephemeral-storage":{"type":"string"}}},"requests":{"type":"object","properties":{"cpu":{"type":"string","description":"CPU request. Minimum 100 millicores (for example, 100m or 0.1)."},"memory":{"type":"string","description":"Memory request. Minimum 192Mi."}}}}}}},"region":{"type":"string","nullable":true,"description":"Cloud region code (e.g., us-east-1)"},"node_group":{"type":"string","nullable":true,"description":"Node group for scheduling the project runtime"},"storage_claim_size_gb":{"type":"number","nullable":true,"description":"Storage claim size in GB"}}}}}}},"paths":{"/v1/projects/{projectId}":{"put":{"summary":"Update a project","description":"Updates a project's metadata and configuration, including description, visibility, spicepod configuration, replicas, and resource limits.","parameters":[{"in":"path","name":"projectId","required":true,"schema":{"type":"integer"},"description":"The ID of the project"},{"$ref":"#/components/parameters/OrgName"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"description":{"type":"string"},"visibility":{"type":"string","enum":["public","private"]},"production_branch":{"type":"string"},"tags":{"type":"object","additionalProperties":{"type":"string"},"description":"Key-value tags for the project"},"spicepod":{"oneOf":[{"type":"string","description":"YAML string of the spicepod configuration"},{"type":"object","description":"JSON object of the spicepod configuration"}]},"image_tag":{"type":"string","nullable":true,"description":"Runtime image tag for a managed project; rejected for standalone projects. A non-empty value pins the project. On stable, the pin must be a published stable runtime version. On preview, it must be a published preview or stable runtime version. On stable or preview, send null to clear a pin so deploys resolve from the channel catalog (stable - latest GA for the configured version range; preview - latest RC). null is rejected on nightly and internal channels."},"update_channel":{"type":"string","enum":["stable","preview","nightly"],"description":"Update channel for a managed runtime; rejected for standalone projects."},"version":{"type":"string","description":"Semver range for a managed runtime version (e.g. 1.x, 2.x); rejected for standalone projects."},"replicas":{"type":"integer","minimum":0,"description":"Managed runtime replica count; rejected for standalone projects."},"resources":{"type":"object","description":"Resource requests and limits for a managed project container; rejected for standalone projects.","properties":{"limits":{"type":"object","properties":{"cpu":{"type":"string","description":"Whole-number vCPU limit, or '-' for no CPU limit"},"memory":{"type":"string","description":"Memory limit in Gi (for example, 16Gi)"},"ephemeral-storage":{"type":"string","description":"Ephemeral storage limit in Gi (for example, 8Gi)"}}},"requests":{"type":"object","properties":{"cpu":{"type":"string","description":"CPU request. Minimum 100 millicores (for example, 100m or 0.1)."},"memory":{"type":"string","description":"Memory request. Minimum 192Mi."}}}}},"executor":{"type":"object","description":"Executor container configuration for a managed project; rejected for standalone projects.","properties":{"replicas":{"type":"integer","minimum":0,"description":"Number of executor replicas"},"resources":{"type":"object","description":"Resource requests and limits for the executor container","properties":{"limits":{"type":"object","properties":{"cpu":{"type":"string","description":"Whole-number vCPU limit, or '-' for no CPU limit"},"memory":{"type":"string","description":"Memory limit in Gi (for example, 16Gi)"},"ephemeral-storage":{"type":"string","description":"Ephemeral storage limit in Gi (for example, 8Gi)"}}},"requests":{"type":"object","properties":{"cpu":{"type":"string","description":"CPU request. Minimum 100 millicores (for example, 100m or 0.1)."},"memory":{"type":"string","description":"Memory request. Minimum 192Mi."}}}}},"storage_size_gb":{"type":"number"}}},"region":{"type":"string","description":"Managed project region; standalone placement is resolved during attachment."},"cluster_name":{"type":"string","description":"Reassign the project to a dedicated cluster, as listed by `GET /v1/clusters`. Provide at most one of `region` or `cluster_name`. When set, region/routing are derived from the cluster; if `region` is also provided it must match the cluster's region. Rejected for standalone projects, whose placement is resolved during attachment.\n"},"storage_size_gb":{"type":"number","description":"Managed runtime storage size; rejected for standalone projects."},"storage_claim_size_gb":{"type":"number","deprecated":true,"description":"Deprecated. Use storage_size_gb instead. Rejected for standalone projects."}}}}}},"responses":{"200":{"description":"Project updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectWithConfig"}}}},"400":{"description":"Invalid request body or project ID, including placement or hosted runtime fields that do not apply to standalone projects. When `image_tag` is supplied on stable or preview, a tag that is not a published version for that channel returns `{ error: 'Invalid image_tag for stable channel', code: 'invalid_stable_image_tag' }` (or the preview analog)."},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient scope, viewer role cannot mutate projects, requested replicas or resources exceed plan limits, dedicated-cluster assignment or special-org private-compute ceilings required, requested resources exceed dedicated-cluster capacity, `image_tag` was supplied outside the Enterprise plan (code: `image_tag_requires_enterprise`), or the requested runtime image is not available for the organization plan (code: `image_tag_not_allowed_for_plan`); omitting `image_tag` leaves the configured image unchanged"},"404":{"description":"Project not found"},"409":{"description":"The project's lifecycle state changed while the update was in flight — a pause, resume or restore landing concurrently — so the configuration was not saved (code: `project_state_changed`). Re-read the project before retrying: a configuration update clears `paused_at`, so repeating this request against a project that has since been paused also resumes it."},"500":{"description":"Internal server error"},"502":{"description":"The configuration was stored but could not be published to the spicepod registry (code: `registry_publish_failed`), so the project still deploys its previously published configuration. Retry the request."},"503":{"description":"Runtime version catalog is unavailable"}},"tags":["Projects"]}}}}
```

## Delete a project

> Deletes a project and tears down its runtime resources.

```json
{"openapi":"3.1.0","info":{"title":"Spice Cloud Control-Plane API","version":"v1"},"tags":[{"name":"Projects","description":"Manage projects and their configurations"}],"servers":[{"url":"https://api.spice.ai"}],"security":[{"BearerAuth":[]}],"components":{"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"OAuth 2.0 access token obtained from the Spice.ai authentication service"}},"parameters":{"OrgName":{"in":"header","name":"X-Org-Name","required":false,"description":"The organization to act on, by handle. Omit it to act on the organization the credential is bound to; sending it blank is a 400, not the same as omitting it. A user credential may name any organization its owner belongs to; a machine credential is pinned to its own.\n","schema":{"type":"string","pattern":"^[A-Za-z0-9._-]{1,255}$"}}}},"paths":{"/v1/projects/{projectId}":{"delete":{"summary":"Delete a project","description":"Deletes a project and tears down its runtime resources.","parameters":[{"in":"path","name":"projectId","required":true,"schema":{"type":"integer"},"description":"The ID of the project to delete"},{"$ref":"#/components/parameters/OrgName"}],"responses":{"204":{"description":"Project deleted successfully"},"400":{"description":"Invalid project ID"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient scope or viewer role cannot mutate projects"},"404":{"description":"Project not found"},"500":{"description":"Internal server error"}},"tags":["Projects"]}}}}
```

## Pause a project

> Pauses the project's running spicepod. The runtime is torn down and the\
> spicepod record is marked as paused. Settings and configuration are\
> preserved. Resume with POST /v1/projects/{projectId}/resume. Requires\
> \`apps:write\`.<br>

```json
{"openapi":"3.1.0","info":{"title":"Spice Cloud Control-Plane API","version":"v1"},"tags":[{"name":"Projects","description":"Manage projects and their configurations"}],"servers":[{"url":"https://api.spice.ai"}],"security":[{"BearerAuth":[]}],"components":{"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"OAuth 2.0 access token obtained from the Spice.ai authentication service"}},"parameters":{"OrgName":{"in":"header","name":"X-Org-Name","required":false,"description":"The organization to act on, by handle. Omit it to act on the organization the credential is bound to; sending it blank is a 400, not the same as omitting it. A user credential may name any organization its owner belongs to; a machine credential is pinned to its own.\n","schema":{"type":"string","pattern":"^[A-Za-z0-9._-]{1,255}$"}}}},"paths":{"/v1/projects/{projectId}/pause":{"post":{"summary":"Pause a project","description":"Pauses the project's running spicepod. The runtime is torn down and the\nspicepod record is marked as paused. Settings and configuration are\npreserved. Resume with POST /v1/projects/{projectId}/resume. Requires\n`apps:write`.\n","parameters":[{"in":"path","name":"projectId","required":true,"schema":{"type":"integer"},"description":"The ID of the project to pause"},{"$ref":"#/components/parameters/OrgName"}],"responses":{"200":{"description":"Project paused","content":{"application/json":{"schema":{"type":"object","required":["id","name","paused_at"],"properties":{"id":{"type":"integer","description":"The project ID"},"name":{"type":"string","description":"The project name"},"paused_at":{"type":"string","format":"date-time","description":"Timestamp when the project was paused"}}}}}},"400":{"description":"Invalid project ID, missing API key, no spicepod configured, or spicepod has been deleted"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient scope"},"404":{"description":"Project not found"},"409":{"description":"Project is already paused","content":{"application/json":{"schema":{"type":"object","required":["error","paused_at"],"properties":{"error":{"type":"string"},"paused_at":{"type":"string","format":"date-time","description":"Timestamp of the existing pause"}}}}}},"500":{"description":"Internal server error"}},"tags":["Projects"]}}}}
```

## Resume a paused project

> Clears the paused state on the project's spicepod and creates a new\
> deployment to bring the runtime back up. Requires \`apps:write\`.<br>

```json
{"openapi":"3.1.0","info":{"title":"Spice Cloud Control-Plane API","version":"v1"},"tags":[{"name":"Projects","description":"Manage projects and their configurations"}],"servers":[{"url":"https://api.spice.ai"}],"security":[{"BearerAuth":[]}],"components":{"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"OAuth 2.0 access token obtained from the Spice.ai authentication service"}},"parameters":{"OrgName":{"in":"header","name":"X-Org-Name","required":false,"description":"The organization to act on, by handle. Omit it to act on the organization the credential is bound to; sending it blank is a 400, not the same as omitting it. A user credential may name any organization its owner belongs to; a machine credential is pinned to its own.\n","schema":{"type":"string","pattern":"^[A-Za-z0-9._-]{1,255}$"}}}},"paths":{"/v1/projects/{projectId}/resume":{"post":{"summary":"Resume a paused project","description":"Clears the paused state on the project's spicepod and creates a new\ndeployment to bring the runtime back up. Requires `apps:write`.\n","parameters":[{"in":"path","name":"projectId","required":true,"schema":{"type":"integer"},"description":"The ID of the project to resume"},{"$ref":"#/components/parameters/OrgName"}],"responses":{"200":{"description":"Project resumed, deployment created","content":{"application/json":{"schema":{"type":"object","required":["id","name","paused_at","deployment_id"],"properties":{"id":{"type":"integer","description":"The project ID"},"name":{"type":"string","description":"The project name"},"paused_at":{"type":"string","format":"date-time","nullable":true,"description":"Always null after a successful resume"},"deployment_id":{"type":"integer","description":"ID of the deployment created to bring the runtime back up"}}}}}},"400":{"description":"Invalid project ID, missing API key, missing project organization, no spicepod configured, spicepod has been deleted, or spicepod configuration is invalid"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient scope"},"404":{"description":"Project not found"},"409":{"description":"Project is not paused"},"422":{"description":"No runtime version in the catalog matches this project’s version range (`code: version_no_match`).\n"},"500":{"description":"Internal server error"},"503":{"description":"The runtime version catalog is unavailable or empty (`code: version_source_unavailable`), so an unpinned stable or preview resume cannot resolve an image tag.\n"}},"tags":["Projects"]}}}}
```

## Get project metrics

> Returns current resource utilization metrics (CPU, memory, disk I/O) and data ingestion metrics for a project.

```json
{"openapi":"3.1.0","info":{"title":"Spice Cloud Control-Plane API","version":"v1"},"tags":[{"name":"Projects","description":"Manage projects and their configurations"}],"servers":[{"url":"https://api.spice.ai"}],"security":[{"BearerAuth":[]}],"components":{"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"OAuth 2.0 access token obtained from the Spice.ai authentication service"}},"parameters":{"OrgName":{"in":"header","name":"X-Org-Name","required":false,"description":"The organization to act on, by handle. Omit it to act on the organization the credential is bound to; sending it blank is a 400, not the same as omitting it. A user credential may name any organization its owner belongs to; a machine credential is pinned to its own.\n","schema":{"type":"string","pattern":"^[A-Za-z0-9._-]{1,255}$"}}}},"paths":{"/v1/projects/{projectId}/metrics":{"get":{"summary":"Get project metrics","description":"Returns current resource utilization metrics (CPU, memory, disk I/O) and data ingestion metrics for a project.","parameters":[{"in":"path","name":"projectId","required":true,"schema":{"type":"integer"},"description":"The ID of the project"},{"in":"query","name":"window","required":false,"schema":{"type":"string"},"description":"Prometheus-style duration (e.g. `5m`, `1h`, `30s`). When provided, counter metrics are returned as rates over the window instead of raw cumulative values. For example, `rows_ingested` returns average rows per second with a window, or total cumulative rows without one."},{"$ref":"#/components/parameters/OrgName"}],"responses":{"200":{"description":"Resource and ingestion metrics. Missing fields indicate no data is currently available. Individual metric queries may fail independently; partial results are returned when possible.","content":{"application/json":{"schema":{"type":"object","properties":{"ingestion":{"type":"object","description":"Aggregated data ingestion metrics","properties":{"rows_ingested":{"type":"number","description":"Total rows ingested (without window) or rows per second (with window)"},"bytes_ingested":{"type":"number","description":"Total bytes ingested (without window) or bytes per second (with window)"}}},"cluster":{"type":"object","description":"Cluster metrics for the project","properties":{"active_executors_count":{"type":"number","description":"Number of active executors registered with the scheduler"}}},"metrics":{"type":"object","description":"Resource metrics keyed by pod name","additionalProperties":{"type":"object","properties":{"cpu_usage_percent":{"type":"number","description":"CPU usage as a percentage (0-100)"},"memory_usage_bytes":{"type":"number","description":"Memory usage in bytes"},"disk_read_bytes":{"type":"number","description":"Disk bytes read per second (with window) or cumulative (without window)"},"disk_read_operations":{"type":"number","description":"Disk read operations per second (with window) or cumulative count (without window)"},"disk_write_bytes":{"type":"number","description":"Disk bytes written per second (with window) or cumulative (without window)"},"disk_write_operations":{"type":"number","description":"Disk write operations per second (with window) or cumulative count (without window)"}}}}}}}}},"400":{"description":"Invalid project ID"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient scope"},"404":{"description":"Project or organization not found"},"422":{"description":"Organization is not fully configured"},"500":{"description":"Internal server error"},"503":{"description":"Metrics service unavailable"}},"tags":["Projects"]}}}}
```

## List projects

> Legacy alias of \`/v1/projects\` — projects were previously called apps. Returns projects belonging to the authenticated organization. Page with \`limit\` (default 1000, max 1000). Prefer \`after\_id\` for a stable keyset (descending \`id\`). \`offset\` is accepted for compatibility. PostgREST also caps a page at 1000 rows.

```json
{"openapi":"3.1.0","info":{"title":"Spice Cloud Control-Plane API","version":"v1"},"tags":[{"name":"Projects","description":"Manage projects and their configurations"}],"servers":[{"url":"https://api.spice.ai"}],"security":[{"BearerAuth":[]}],"components":{"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"OAuth 2.0 access token obtained from the Spice.ai authentication service"}},"parameters":{"OrgName":{"in":"header","name":"X-Org-Name","required":false,"description":"The organization to act on, by handle. Omit it to act on the organization the credential is bound to; sending it blank is a 400, not the same as omitting it. A user credential may name any organization its owner belongs to; a machine credential is pinned to its own.\n","schema":{"type":"string","pattern":"^[A-Za-z0-9._-]{1,255}$"}}},"schemas":{"Project":{"type":"object","properties":{"id":{"type":"integer","description":"Unique identifier for the project"},"name":{"type":"string","description":"Name of the project"},"kind":{"type":"string","enum":["managed","standalone","byoc"],"description":"Resolved project hosting model"},"description":{"type":"string","nullable":true,"description":"Description of the project"},"visibility":{"type":"string","enum":["public","private"],"description":"Visibility setting for the project"},"created_at":{"type":"string","format":"date-time","description":"Timestamp when the project was created"},"cname":{"type":"string","nullable":true,"description":"Region identifier"},"cluster_name":{"type":"string","nullable":true,"description":"Resolved dedicated cluster name; null for projects not assigned to a dedicated cluster."},"endpoint":{"type":"string","nullable":true,"description":"The data-plane endpoint the project connects to, or null before a standalone instance is attached."},"tags":{"type":"object","additionalProperties":{"type":"string"},"nullable":true,"description":"Key-value tags for the project"}}}}},"paths":{"/v1/apps":{"get":{"summary":"List projects","description":"Legacy alias of `/v1/projects` — projects were previously called apps. Returns projects belonging to the authenticated organization. Page with `limit` (default 1000, max 1000). Prefer `after_id` for a stable keyset (descending `id`). `offset` is accepted for compatibility. PostgREST also caps a page at 1000 rows.","parameters":[{"in":"query","name":"limit","schema":{"type":"integer","minimum":1,"maximum":1000,"default":1000},"description":"Maximum number of projects to return"},{"in":"query","name":"offset","schema":{"type":"integer","minimum":0,"default":0},"description":"Number of projects to skip when a cursor is not supplied"},{"in":"query","name":"after_id","schema":{"type":"integer","minimum":1},"description":"Return projects with a strictly smaller id than this value."},{"$ref":"#/components/parameters/OrgName"}],"responses":{"200":{"description":"List of projects","content":{"application/json":{"schema":{"type":"object","properties":{"apps":{"type":"array","items":{"$ref":"#/components/schemas/Project"}}}}}}},"400":{"description":"Invalid limit, offset, or after_id"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient scope"}},"tags":["Projects"],"deprecated":true}}}}
```

## Create a project

> Legacy alias of \`/v1/projects\` — projects were previously called apps. Creates a new project in the authenticated organization.

```json
{"openapi":"3.1.0","info":{"title":"Spice Cloud Control-Plane API","version":"v1"},"tags":[{"name":"Projects","description":"Manage projects and their configurations"}],"servers":[{"url":"https://api.spice.ai"}],"security":[{"BearerAuth":[]}],"components":{"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"OAuth 2.0 access token obtained from the Spice.ai authentication service"}},"schemas":{"ProjectWithConfig":{"type":"object","properties":{"id":{"type":"integer","description":"Unique identifier for the project"},"name":{"type":"string","description":"Name of the project"},"kind":{"type":"string","enum":["managed","standalone","byoc"],"description":"Resolved project hosting model"},"description":{"type":"string","nullable":true,"description":"Description of the project"},"visibility":{"type":"string","enum":["public","private"],"description":"Visibility setting for the project"},"created_at":{"type":"string","format":"date-time","description":"Timestamp when the project was created"},"cname":{"type":"string","nullable":true,"description":"Region identifier"},"cluster_name":{"type":"string","nullable":true,"description":"Resolved dedicated cluster name; null for projects not assigned to a dedicated cluster."},"endpoint":{"type":"string","nullable":true,"description":"The data-plane endpoint the project connects to, or null before a standalone instance is attached."},"production_branch":{"type":"string","nullable":true,"description":"Production branch for the project"},"api_key":{"type":"string","deprecated":true,"description":"Deprecated. Use the API Keys endpoints instead."},"tags":{"type":"object","additionalProperties":{"type":"string"},"nullable":true,"description":"Key-value tags for the project"},"paused_at":{"type":"string","format":"date-time","nullable":true,"description":"Timestamp when the project was paused; null while running"},"warning":{"type":"string","nullable":true,"description":"Present when the project was created but initial configuration could not be applied"},"config":{"type":"object","nullable":true,"description":"Runtime configuration; null for an unattached standalone project.","properties":{"spicepod":{"type":"object","nullable":true,"description":"Spicepod configuration"},"registry":{"type":"string","nullable":true,"description":"Container registry for the runtime image"},"image_tag":{"type":"string","nullable":true,"description":"Runtime image tag"},"update_channel":{"type":"string","enum":["stable","preview","nightly"],"nullable":true,"description":"Update channel for the runtime"},"replicas":{"type":"integer","description":"Number of replicas"},"resources":{"type":"object","nullable":true,"description":"Resource requests and limits for the project container","properties":{"limits":{"type":"object","properties":{"cpu":{"type":"string","description":"Whole-number vCPU limit, or '-' for no CPU limit"},"memory":{"type":"string","description":"Memory limit in Gi (for example, 16Gi)"},"ephemeral-storage":{"type":"string"}}},"requests":{"type":"object","properties":{"cpu":{"type":"string","description":"CPU request. Minimum 100 millicores (for example, 100m or 0.1)."},"memory":{"type":"string","description":"Memory request. Minimum 192Mi."}}}}},"executor":{"type":"object","nullable":true,"description":"Executor container configuration","properties":{"replicas":{"type":"integer","description":"Number of executor replicas"},"resources":{"type":"object","description":"Resource requests and limits for the executor container","properties":{"limits":{"type":"object","properties":{"cpu":{"type":"string","description":"Whole-number vCPU limit, or '-' for no CPU limit"},"memory":{"type":"string","description":"Memory limit in Gi (for example, 16Gi)"},"ephemeral-storage":{"type":"string"}}},"requests":{"type":"object","properties":{"cpu":{"type":"string","description":"CPU request. Minimum 100 millicores (for example, 100m or 0.1)."},"memory":{"type":"string","description":"Memory request. Minimum 192Mi."}}}}}}},"region":{"type":"string","nullable":true,"description":"Cloud region code (e.g., us-east-1)"},"node_group":{"type":"string","nullable":true,"description":"Node group for scheduling the project runtime"},"storage_claim_size_gb":{"type":"number","nullable":true,"description":"Storage claim size in GB"}}}}}},"parameters":{"OrgName":{"in":"header","name":"X-Org-Name","required":false,"description":"The organization to act on, by handle. Omit it to act on the organization the credential is bound to; sending it blank is a 400, not the same as omitting it. A user credential may name any organization its owner belongs to; a machine credential is pinned to its own.\n","schema":{"type":"string","pattern":"^[A-Za-z0-9._-]{1,255}$"}}}},"paths":{"/v1/apps":{"post":{"summary":"Create a project","description":"Legacy alias of `/v1/projects` — projects were previously called apps. Creates a new project in the authenticated organization.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name"],"properties":{"name":{"type":"string","minLength":4,"pattern":"^[a-zA-Z0-9-]+$","description":"Project name (letters, numbers, hyphens only)"},"region":{"type":"string","enum":["us-east-1","us-west-2"],"description":"Cloud region where a managed project will be deployed (e.g. `us-east-1`). Omit this, `cname`, and `cluster_name` to create an unattached standalone project whose placement is resolved when linked.\n"},"cname":{"type":"string","description":"**Deprecated.** Internal region CNAME (e.g. `us-east-1-prod-aws-data`). Use `region` instead. Accepted for backwards compatibility when `region` is omitted. Omit all region sources to create an unattached standalone project.\n"},"cluster_name":{"type":"string","description":"Name of the dedicated cluster to deploy to, as listed by `GET /v1/clusters`. Provide exactly one of `region` or `cluster_name`. When set, the region/routing are derived from the cluster; if `region` is also provided it must match the cluster's region. Omit all region sources to create an unattached standalone project.\n"},"description":{"type":"string","description":"Project description"},"visibility":{"type":"string","enum":["public","private"],"default":"private"},"tags":{"type":"object","additionalProperties":{"type":"string"},"description":"Key-value tags for the project"},"update_channel":{"type":"string","enum":["stable","preview","nightly"],"description":"Update channel for a managed project deployment. A standalone project has no spicepod until linking, so configure its channel after linking."},"replicas":{"type":"integer","minimum":0,"description":"Number of replicas for a managed project. Rejected for standalone projects."},"resources":{"type":"object","description":"Resource requests and limits for a managed project container. Rejected for standalone projects.","properties":{"limits":{"type":"object","properties":{"cpu":{"type":"string","description":"Whole-number vCPU limit, or '-' for no CPU limit"},"memory":{"type":"string","description":"Memory limit in Gi (for example, 16Gi)"},"ephemeral-storage":{"type":"string","description":"Ephemeral storage limit in Gi (for example, 8Gi)"}}},"requests":{"type":"object","properties":{"cpu":{"type":"string","description":"CPU request. Minimum 100 millicores (for example, 100m or 0.1)."},"memory":{"type":"string","description":"Memory request. Minimum 192Mi."}}}}},"executor":{"type":"object","description":"Executor container configuration for a managed project. Rejected for standalone projects.","properties":{"replicas":{"type":"integer","minimum":0,"description":"Number of executor replicas"},"resources":{"type":"object","description":"Resource requests and limits for the executor container","properties":{"limits":{"type":"object","properties":{"cpu":{"type":"string","description":"Whole-number vCPU limit, or '-' for no CPU limit"},"memory":{"type":"string","description":"Memory limit in Gi (for example, 16Gi)"},"ephemeral-storage":{"type":"string","description":"Ephemeral storage limit in Gi (for example, 8Gi)"}}},"requests":{"type":"object","properties":{"cpu":{"type":"string","description":"CPU request. Minimum 100 millicores (for example, 100m or 0.1)."},"memory":{"type":"string","description":"Memory request. Minimum 192Mi."}}}}}}}}}}}},"responses":{"201":{"description":"Project created successfully. The response may include a `warning` field if initial configuration could not be applied.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectWithConfig"}}}},"400":{"description":"Invalid request body or invalid region"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient scope, dedicated-cluster assignment or special-org private-compute ceilings required for resource limits, or requested resources exceed dedicated-cluster capacity"},"409":{"description":"A project with this name already exists"},"429":{"description":"Too many project creation requests (rate limited)"},"500":{"description":"Project creation failed, including when the name-collision check could not be read","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Generic failure reason; the underlying cause stays in the server logs"}}}}}}},"tags":["Projects"],"parameters":[{"$ref":"#/components/parameters/OrgName"}],"deprecated":true}}}}
```

## Get a project

> Legacy alias of \`/v1/projects/{projectId}\` — projects were previously called apps. Returns details for a specific project, including its configuration.

```json
{"openapi":"3.1.0","info":{"title":"Spice Cloud Control-Plane API","version":"v1"},"tags":[{"name":"Projects","description":"Manage projects and their configurations"}],"servers":[{"url":"https://api.spice.ai"}],"security":[{"BearerAuth":[]}],"components":{"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"OAuth 2.0 access token obtained from the Spice.ai authentication service"}},"parameters":{"OrgName":{"in":"header","name":"X-Org-Name","required":false,"description":"The organization to act on, by handle. Omit it to act on the organization the credential is bound to; sending it blank is a 400, not the same as omitting it. A user credential may name any organization its owner belongs to; a machine credential is pinned to its own.\n","schema":{"type":"string","pattern":"^[A-Za-z0-9._-]{1,255}$"}}}},"paths":{"/v1/apps/{appId}":{"get":{"summary":"Get a project","description":"Legacy alias of `/v1/projects/{projectId}` — projects were previously called apps. Returns details for a specific project, including its configuration.","parameters":[{"in":"path","name":"appId","required":true,"schema":{"type":"integer"},"description":"The ID of the project"},{"$ref":"#/components/parameters/OrgName"}],"responses":{"200":{"description":"Project details with configuration","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"integer"},"name":{"type":"string"},"kind":{"type":"string","enum":["managed","standalone","byoc"],"description":"Resolved project hosting model"},"description":{"type":"string"},"visibility":{"type":"string","enum":["public","private"]},"created_at":{"type":"string","format":"date-time"},"cluster_name":{"type":"string","nullable":true,"description":"Resolved dedicated cluster name; null for projects not assigned to a dedicated cluster."},"endpoint":{"type":"string","nullable":true,"description":"The data-plane endpoint the project connects to, or null before a standalone instance is attached."},"production_branch":{"type":"string"},"api_key":{"type":"string","deprecated":true,"description":"Deprecated. Use the API Keys endpoints instead."},"tags":{"type":"object","additionalProperties":{"type":"string"}},"paused_at":{"type":"string","format":"date-time","nullable":true,"description":"Timestamp when the project was paused; null while running"},"config":{"type":"object","properties":{"spicepod":{"type":"object"},"image_tag":{"type":"string","description":"Runtime image tag"},"update_channel":{"type":"string","enum":["stable","preview","nightly"],"nullable":true,"description":"Update channel for the runtime, or null when Spice operates this project's runtime updates."},"version":{"type":"string","description":"Semver range for the runtime version (e.g. 1.x, 2.x)"},"replicas":{"type":"integer"},"resources":{"type":"object","nullable":true,"description":"Resource requests and limits for the project container","properties":{"limits":{"type":"object","properties":{"cpu":{"type":"string","description":"Whole-number vCPU limit, or '-' for no CPU limit"},"memory":{"type":"string","description":"Memory limit in Gi (for example, 16Gi)"},"ephemeral-storage":{"type":"string"}}},"requests":{"type":"object","properties":{"cpu":{"type":"string","description":"CPU request. Minimum 100 millicores (for example, 100m or 0.1)."},"memory":{"type":"string","description":"Memory request. Minimum 192Mi."}}}}},"executor":{"type":"object","nullable":true,"description":"Executor container configuration","properties":{"replicas":{"type":"integer","description":"Number of executor replicas"},"resources":{"type":"object","description":"Resource requests and limits for the executor container","properties":{"limits":{"type":"object","properties":{"cpu":{"type":"string","description":"Whole-number vCPU limit, or '-' for no CPU limit"},"memory":{"type":"string","description":"Memory limit in Gi (for example, 16Gi)"},"ephemeral-storage":{"type":"string"}}},"requests":{"type":"object","properties":{"cpu":{"type":"string","description":"CPU request. Minimum 100 millicores (for example, 100m or 0.1)."},"memory":{"type":"string","description":"Memory request. Minimum 192Mi."}}}}},"storage_size_gb":{"type":"number","nullable":true}}},"region":{"type":"string","nullable":true,"description":"Server-resolved region; null before a standalone instance is attached."},"storage_size_gb":{"type":"number","nullable":true},"storage_claim_size_gb":{"type":"number","deprecated":true,"description":"Deprecated. Use storage_size_gb instead."}}}}}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient scope"},"404":{"description":"Project not found"},"500":{"description":"Internal server error"}},"tags":["Projects"],"deprecated":true}}}}
```

## Update a project

> Legacy alias of \`/v1/projects/{projectId}\` — projects were previously called apps. Updates a project's metadata and configuration, including description, visibility, spicepod configuration, replicas, and resource limits.

```json
{"openapi":"3.1.0","info":{"title":"Spice Cloud Control-Plane API","version":"v1"},"tags":[{"name":"Projects","description":"Manage projects and their configurations"}],"servers":[{"url":"https://api.spice.ai"}],"security":[{"BearerAuth":[]}],"components":{"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"OAuth 2.0 access token obtained from the Spice.ai authentication service"}},"parameters":{"OrgName":{"in":"header","name":"X-Org-Name","required":false,"description":"The organization to act on, by handle. Omit it to act on the organization the credential is bound to; sending it blank is a 400, not the same as omitting it. A user credential may name any organization its owner belongs to; a machine credential is pinned to its own.\n","schema":{"type":"string","pattern":"^[A-Za-z0-9._-]{1,255}$"}}},"schemas":{"ProjectWithConfig":{"type":"object","properties":{"id":{"type":"integer","description":"Unique identifier for the project"},"name":{"type":"string","description":"Name of the project"},"kind":{"type":"string","enum":["managed","standalone","byoc"],"description":"Resolved project hosting model"},"description":{"type":"string","nullable":true,"description":"Description of the project"},"visibility":{"type":"string","enum":["public","private"],"description":"Visibility setting for the project"},"created_at":{"type":"string","format":"date-time","description":"Timestamp when the project was created"},"cname":{"type":"string","nullable":true,"description":"Region identifier"},"cluster_name":{"type":"string","nullable":true,"description":"Resolved dedicated cluster name; null for projects not assigned to a dedicated cluster."},"endpoint":{"type":"string","nullable":true,"description":"The data-plane endpoint the project connects to, or null before a standalone instance is attached."},"production_branch":{"type":"string","nullable":true,"description":"Production branch for the project"},"api_key":{"type":"string","deprecated":true,"description":"Deprecated. Use the API Keys endpoints instead."},"tags":{"type":"object","additionalProperties":{"type":"string"},"nullable":true,"description":"Key-value tags for the project"},"paused_at":{"type":"string","format":"date-time","nullable":true,"description":"Timestamp when the project was paused; null while running"},"warning":{"type":"string","nullable":true,"description":"Present when the project was created but initial configuration could not be applied"},"config":{"type":"object","nullable":true,"description":"Runtime configuration; null for an unattached standalone project.","properties":{"spicepod":{"type":"object","nullable":true,"description":"Spicepod configuration"},"registry":{"type":"string","nullable":true,"description":"Container registry for the runtime image"},"image_tag":{"type":"string","nullable":true,"description":"Runtime image tag"},"update_channel":{"type":"string","enum":["stable","preview","nightly"],"nullable":true,"description":"Update channel for the runtime"},"replicas":{"type":"integer","description":"Number of replicas"},"resources":{"type":"object","nullable":true,"description":"Resource requests and limits for the project container","properties":{"limits":{"type":"object","properties":{"cpu":{"type":"string","description":"Whole-number vCPU limit, or '-' for no CPU limit"},"memory":{"type":"string","description":"Memory limit in Gi (for example, 16Gi)"},"ephemeral-storage":{"type":"string"}}},"requests":{"type":"object","properties":{"cpu":{"type":"string","description":"CPU request. Minimum 100 millicores (for example, 100m or 0.1)."},"memory":{"type":"string","description":"Memory request. Minimum 192Mi."}}}}},"executor":{"type":"object","nullable":true,"description":"Executor container configuration","properties":{"replicas":{"type":"integer","description":"Number of executor replicas"},"resources":{"type":"object","description":"Resource requests and limits for the executor container","properties":{"limits":{"type":"object","properties":{"cpu":{"type":"string","description":"Whole-number vCPU limit, or '-' for no CPU limit"},"memory":{"type":"string","description":"Memory limit in Gi (for example, 16Gi)"},"ephemeral-storage":{"type":"string"}}},"requests":{"type":"object","properties":{"cpu":{"type":"string","description":"CPU request. Minimum 100 millicores (for example, 100m or 0.1)."},"memory":{"type":"string","description":"Memory request. Minimum 192Mi."}}}}}}},"region":{"type":"string","nullable":true,"description":"Cloud region code (e.g., us-east-1)"},"node_group":{"type":"string","nullable":true,"description":"Node group for scheduling the project runtime"},"storage_claim_size_gb":{"type":"number","nullable":true,"description":"Storage claim size in GB"}}}}}}},"paths":{"/v1/apps/{appId}":{"put":{"summary":"Update a project","description":"Legacy alias of `/v1/projects/{projectId}` — projects were previously called apps. Updates a project's metadata and configuration, including description, visibility, spicepod configuration, replicas, and resource limits.","parameters":[{"in":"path","name":"appId","required":true,"schema":{"type":"integer"},"description":"The ID of the project"},{"$ref":"#/components/parameters/OrgName"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"description":{"type":"string"},"visibility":{"type":"string","enum":["public","private"]},"production_branch":{"type":"string"},"tags":{"type":"object","additionalProperties":{"type":"string"},"description":"Key-value tags for the project"},"spicepod":{"oneOf":[{"type":"string","description":"YAML string of the spicepod configuration"},{"type":"object","description":"JSON object of the spicepod configuration"}]},"image_tag":{"type":"string","nullable":true,"description":"Runtime image tag for a managed project; rejected for standalone projects. A non-empty value pins the project. On stable, the pin must be a published stable runtime version. On preview, it must be a published preview or stable runtime version. On stable or preview, send null to clear a pin so deploys resolve from the channel catalog (stable - latest GA for the configured version range; preview - latest RC). null is rejected on nightly and internal channels."},"update_channel":{"type":"string","enum":["stable","preview","nightly"],"description":"Update channel for a managed runtime; rejected for standalone projects."},"version":{"type":"string","description":"Semver range for a managed runtime version (e.g. 1.x, 2.x); rejected for standalone projects."},"replicas":{"type":"integer","minimum":0,"description":"Managed runtime replica count; rejected for standalone projects."},"resources":{"type":"object","description":"Resource requests and limits for a managed project container; rejected for standalone projects.","properties":{"limits":{"type":"object","properties":{"cpu":{"type":"string","description":"Whole-number vCPU limit, or '-' for no CPU limit"},"memory":{"type":"string","description":"Memory limit in Gi (for example, 16Gi)"},"ephemeral-storage":{"type":"string","description":"Ephemeral storage limit in Gi (for example, 8Gi)"}}},"requests":{"type":"object","properties":{"cpu":{"type":"string","description":"CPU request. Minimum 100 millicores (for example, 100m or 0.1)."},"memory":{"type":"string","description":"Memory request. Minimum 192Mi."}}}}},"executor":{"type":"object","description":"Executor container configuration for a managed project; rejected for standalone projects.","properties":{"replicas":{"type":"integer","minimum":0,"description":"Number of executor replicas"},"resources":{"type":"object","description":"Resource requests and limits for the executor container","properties":{"limits":{"type":"object","properties":{"cpu":{"type":"string","description":"Whole-number vCPU limit, or '-' for no CPU limit"},"memory":{"type":"string","description":"Memory limit in Gi (for example, 16Gi)"},"ephemeral-storage":{"type":"string","description":"Ephemeral storage limit in Gi (for example, 8Gi)"}}},"requests":{"type":"object","properties":{"cpu":{"type":"string","description":"CPU request. Minimum 100 millicores (for example, 100m or 0.1)."},"memory":{"type":"string","description":"Memory request. Minimum 192Mi."}}}}},"storage_size_gb":{"type":"number"}}},"region":{"type":"string","description":"Managed project region; standalone placement is resolved during attachment."},"cluster_name":{"type":"string","description":"Reassign the project to a dedicated cluster, as listed by `GET /v1/clusters`. Provide at most one of `region` or `cluster_name`. When set, region/routing are derived from the cluster; if `region` is also provided it must match the cluster's region. Rejected for standalone projects, whose placement is resolved during attachment.\n"},"storage_size_gb":{"type":"number","description":"Managed runtime storage size; rejected for standalone projects."},"storage_claim_size_gb":{"type":"number","deprecated":true,"description":"Deprecated. Use storage_size_gb instead. Rejected for standalone projects."}}}}}},"responses":{"200":{"description":"Project updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectWithConfig"}}}},"400":{"description":"Invalid request body or project ID, including placement or hosted runtime fields that do not apply to standalone projects. When `image_tag` is supplied on stable or preview, a tag that is not a published version for that channel returns `{ error: 'Invalid image_tag for stable channel', code: 'invalid_stable_image_tag' }` (or the preview analog)."},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient scope, viewer role cannot mutate projects, requested replicas or resources exceed plan limits, dedicated-cluster assignment or special-org private-compute ceilings required, requested resources exceed dedicated-cluster capacity, `image_tag` was supplied outside the Enterprise plan (code: `image_tag_requires_enterprise`), or the requested runtime image is not available for the organization plan (code: `image_tag_not_allowed_for_plan`); omitting `image_tag` leaves the configured image unchanged"},"404":{"description":"Project not found"},"409":{"description":"The project's lifecycle state changed while the update was in flight — a pause, resume or restore landing concurrently — so the configuration was not saved (code: `project_state_changed`). Re-read the project before retrying: a configuration update clears `paused_at`, so repeating this request against a project that has since been paused also resumes it."},"500":{"description":"Internal server error"},"502":{"description":"The configuration was stored but could not be published to the spicepod registry (code: `registry_publish_failed`), so the project still deploys its previously published configuration. Retry the request."},"503":{"description":"Runtime version catalog is unavailable"}},"tags":["Projects"],"deprecated":true}}}}
```

## Delete a project

> Legacy alias of \`/v1/projects/{projectId}\` — projects were previously called apps. Deletes a project and tears down its runtime resources.

```json
{"openapi":"3.1.0","info":{"title":"Spice Cloud Control-Plane API","version":"v1"},"tags":[{"name":"Projects","description":"Manage projects and their configurations"}],"servers":[{"url":"https://api.spice.ai"}],"security":[{"BearerAuth":[]}],"components":{"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"OAuth 2.0 access token obtained from the Spice.ai authentication service"}},"parameters":{"OrgName":{"in":"header","name":"X-Org-Name","required":false,"description":"The organization to act on, by handle. Omit it to act on the organization the credential is bound to; sending it blank is a 400, not the same as omitting it. A user credential may name any organization its owner belongs to; a machine credential is pinned to its own.\n","schema":{"type":"string","pattern":"^[A-Za-z0-9._-]{1,255}$"}}}},"paths":{"/v1/apps/{appId}":{"delete":{"summary":"Delete a project","description":"Legacy alias of `/v1/projects/{projectId}` — projects were previously called apps. Deletes a project and tears down its runtime resources.","parameters":[{"in":"path","name":"appId","required":true,"schema":{"type":"integer"},"description":"The ID of the project to delete"},{"$ref":"#/components/parameters/OrgName"}],"responses":{"204":{"description":"Project deleted successfully"},"400":{"description":"Invalid project ID"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient scope or viewer role cannot mutate projects"},"404":{"description":"Project not found"},"500":{"description":"Internal server error"}},"tags":["Projects"],"deprecated":true}}}}
```

## Pause a project

> Legacy alias of \`/v1/projects/{projectId}/pause\` — projects were previously called apps. Pauses the project's running spicepod. The runtime is torn down and the\
> spicepod record is marked as paused. Settings and configuration are\
> preserved. Resume with POST /v1/projects/{projectId}/resume. Requires\
> \`apps:write\`.

```json
{"openapi":"3.1.0","info":{"title":"Spice Cloud Control-Plane API","version":"v1"},"tags":[{"name":"Projects","description":"Manage projects and their configurations"}],"servers":[{"url":"https://api.spice.ai"}],"security":[{"BearerAuth":[]}],"components":{"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"OAuth 2.0 access token obtained from the Spice.ai authentication service"}},"parameters":{"OrgName":{"in":"header","name":"X-Org-Name","required":false,"description":"The organization to act on, by handle. Omit it to act on the organization the credential is bound to; sending it blank is a 400, not the same as omitting it. A user credential may name any organization its owner belongs to; a machine credential is pinned to its own.\n","schema":{"type":"string","pattern":"^[A-Za-z0-9._-]{1,255}$"}}}},"paths":{"/v1/apps/{appId}/pause":{"post":{"summary":"Pause a project","description":"Legacy alias of `/v1/projects/{projectId}/pause` — projects were previously called apps. Pauses the project's running spicepod. The runtime is torn down and the\nspicepod record is marked as paused. Settings and configuration are\npreserved. Resume with POST /v1/projects/{projectId}/resume. Requires\n`apps:write`.","parameters":[{"in":"path","name":"appId","required":true,"schema":{"type":"integer"},"description":"The ID of the project to pause"},{"$ref":"#/components/parameters/OrgName"}],"responses":{"200":{"description":"Project paused","content":{"application/json":{"schema":{"type":"object","required":["id","name","paused_at"],"properties":{"id":{"type":"integer","description":"The project ID"},"name":{"type":"string","description":"The project name"},"paused_at":{"type":"string","format":"date-time","description":"Timestamp when the project was paused"}}}}}},"400":{"description":"Invalid project ID, missing API key, no spicepod configured, or spicepod has been deleted"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient scope"},"404":{"description":"Project not found"},"409":{"description":"Project is already paused","content":{"application/json":{"schema":{"type":"object","required":["error","paused_at"],"properties":{"error":{"type":"string"},"paused_at":{"type":"string","format":"date-time","description":"Timestamp of the existing pause"}}}}}},"500":{"description":"Internal server error"}},"tags":["Projects"],"deprecated":true}}}}
```

## Resume a paused project

> Legacy alias of \`/v1/projects/{projectId}/resume\` — projects were previously called apps. Clears the paused state on the project's spicepod and creates a new\
> deployment to bring the runtime back up. Requires \`apps:write\`.

```json
{"openapi":"3.1.0","info":{"title":"Spice Cloud Control-Plane API","version":"v1"},"tags":[{"name":"Projects","description":"Manage projects and their configurations"}],"servers":[{"url":"https://api.spice.ai"}],"security":[{"BearerAuth":[]}],"components":{"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"OAuth 2.0 access token obtained from the Spice.ai authentication service"}},"parameters":{"OrgName":{"in":"header","name":"X-Org-Name","required":false,"description":"The organization to act on, by handle. Omit it to act on the organization the credential is bound to; sending it blank is a 400, not the same as omitting it. A user credential may name any organization its owner belongs to; a machine credential is pinned to its own.\n","schema":{"type":"string","pattern":"^[A-Za-z0-9._-]{1,255}$"}}}},"paths":{"/v1/apps/{appId}/resume":{"post":{"summary":"Resume a paused project","description":"Legacy alias of `/v1/projects/{projectId}/resume` — projects were previously called apps. Clears the paused state on the project's spicepod and creates a new\ndeployment to bring the runtime back up. Requires `apps:write`.","parameters":[{"in":"path","name":"appId","required":true,"schema":{"type":"integer"},"description":"The ID of the project to resume"},{"$ref":"#/components/parameters/OrgName"}],"responses":{"200":{"description":"Project resumed, deployment created","content":{"application/json":{"schema":{"type":"object","required":["id","name","paused_at","deployment_id"],"properties":{"id":{"type":"integer","description":"The project ID"},"name":{"type":"string","description":"The project name"},"paused_at":{"type":"string","format":"date-time","nullable":true,"description":"Always null after a successful resume"},"deployment_id":{"type":"integer","description":"ID of the deployment created to bring the runtime back up"}}}}}},"400":{"description":"Invalid project ID, missing API key, missing project organization, no spicepod configured, spicepod has been deleted, or spicepod configuration is invalid"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient scope"},"404":{"description":"Project not found"},"409":{"description":"Project is not paused"},"422":{"description":"No runtime version in the catalog matches this project’s version range (`code: version_no_match`).\n"},"500":{"description":"Internal server error"},"503":{"description":"The runtime version catalog is unavailable or empty (`code: version_source_unavailable`), so an unpinned stable or preview resume cannot resolve an image tag.\n"}},"tags":["Projects"],"deprecated":true}}}}
```

## Get project metrics

> Legacy alias of \`/v1/projects/{projectId}/metrics\` — projects were previously called apps. Returns current resource utilization metrics (CPU, memory, disk I/O) and data ingestion metrics for a project.

```json
{"openapi":"3.1.0","info":{"title":"Spice Cloud Control-Plane API","version":"v1"},"tags":[{"name":"Projects","description":"Manage projects and their configurations"}],"servers":[{"url":"https://api.spice.ai"}],"security":[{"BearerAuth":[]}],"components":{"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"OAuth 2.0 access token obtained from the Spice.ai authentication service"}},"parameters":{"OrgName":{"in":"header","name":"X-Org-Name","required":false,"description":"The organization to act on, by handle. Omit it to act on the organization the credential is bound to; sending it blank is a 400, not the same as omitting it. A user credential may name any organization its owner belongs to; a machine credential is pinned to its own.\n","schema":{"type":"string","pattern":"^[A-Za-z0-9._-]{1,255}$"}}}},"paths":{"/v1/apps/{appId}/metrics":{"get":{"summary":"Get project metrics","description":"Legacy alias of `/v1/projects/{projectId}/metrics` — projects were previously called apps. Returns current resource utilization metrics (CPU, memory, disk I/O) and data ingestion metrics for a project.","parameters":[{"in":"path","name":"appId","required":true,"schema":{"type":"integer"},"description":"The ID of the project"},{"in":"query","name":"window","required":false,"schema":{"type":"string"},"description":"Prometheus-style duration (e.g. `5m`, `1h`, `30s`). When provided, counter metrics are returned as rates over the window instead of raw cumulative values. For example, `rows_ingested` returns average rows per second with a window, or total cumulative rows without one."},{"$ref":"#/components/parameters/OrgName"}],"responses":{"200":{"description":"Resource and ingestion metrics. Missing fields indicate no data is currently available. Individual metric queries may fail independently; partial results are returned when possible.","content":{"application/json":{"schema":{"type":"object","properties":{"ingestion":{"type":"object","description":"Aggregated data ingestion metrics","properties":{"rows_ingested":{"type":"number","description":"Total rows ingested (without window) or rows per second (with window)"},"bytes_ingested":{"type":"number","description":"Total bytes ingested (without window) or bytes per second (with window)"}}},"cluster":{"type":"object","description":"Cluster metrics for the project","properties":{"active_executors_count":{"type":"number","description":"Number of active executors registered with the scheduler"}}},"metrics":{"type":"object","description":"Resource metrics keyed by pod name","additionalProperties":{"type":"object","properties":{"cpu_usage_percent":{"type":"number","description":"CPU usage as a percentage (0-100)"},"memory_usage_bytes":{"type":"number","description":"Memory usage in bytes"},"disk_read_bytes":{"type":"number","description":"Disk bytes read per second (with window) or cumulative (without window)"},"disk_read_operations":{"type":"number","description":"Disk read operations per second (with window) or cumulative count (without window)"},"disk_write_bytes":{"type":"number","description":"Disk bytes written per second (with window) or cumulative (without window)"},"disk_write_operations":{"type":"number","description":"Disk write operations per second (with window) or cumulative count (without window)"}}}}}}}}},"400":{"description":"Invalid project ID"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient scope"},"404":{"description":"Project or organization not found"},"422":{"description":"Organization is not fully configured"},"500":{"description":"Internal server error"},"503":{"description":"Metrics service unavailable"}},"tags":["Projects"],"deprecated":true}}}}
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.spice.ai/api/management-api/management/projects.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
