Management APIs

Deployments

Create and monitor project deployments

OpenAPIapi.spice.ai/openapi.json

List deployments

GET/v1/projects/{projectId}/deployments

Returns a list of deployments for the specified project, ordered by most recent first.

Path parameters

NameTypeRequiredDescription
projectIdintegerYes

The ID of the project

Query parameters

NameTypeRequiredDescription
limitintegerNo

Maximum number of deployments to return

  • Default: 20
statusstringNo

Filter by deployment status

  • Allowed values: queued, in_progress, succeeded, failed, created

Header parameters

NameTypeRequiredDescription
AuthorizationstringYes

Bearer <token>. Authentication lists the tokens it accepts.

X-Org-NamestringNo

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. A portal session token is bound to none, so it must send this header on every route but GET /v1/orgs (400 org_assertion_required otherwise).

  • Pattern: ^[A-Za-z0-9._-]{1,255}$

Example request

curl "https://api.spice.ai/v1/projects/<projectId>/deployments" \
  -H "Authorization: Bearer <token>"

Responses

  • 200OK

    List of deployments

    application/json

    • deploymentsarray of object

      13 properties
      • idinteger

        Unique identifier for the deployment

      • statusstring

        Current status of the deployment

        • Allowed values: queued, in_progress, succeeded, failed, created
      • created_atstring (date-time)

        Timestamp when the deployment was created

      • updated_atstring (date-time) | null

        Timestamp when the deployment was last updated

      • image_tagstring | null

        Runtime image tag used for this deployment

      • replicasinteger

        Number of replicas

      • branchstring | null

        Git branch name

      • commit_shastring | null

        Git commit SHA

      • commit_messagestring | null

        Git commit message

      • error_codestring | null

        Set with error_message on failed and on in_progress while Cloud is retrying a scheduling block. Null on succeeded, on ordinary waiting in_progress, and on writers that predated this column. Older failed rows may still have a message with a null code.

      • error_messagestring | null

        Catalog copy for the current error_code. Older failed rows may still have a message with a null error_code.

      • creation_sourcestring | null

        Source that triggered the deployment

      • created_byinteger | null

        User ID who created the deployment

  • 401Unauthorized

    Unauthorized

  • 403Forbidden

    Insufficient scope

  • 404Not Found

    Project not found

Create a deployment

POST/v1/projects/{projectId}/deployments

Creates a new deployment for the specified project using its current spicepod configuration. A project connected to a GitHub repository deploys spicepod.yaml from its root directory, read when the deployment is created. It reads the head of the production branch, or the branch or commit_sha the request names. The runtime image is selected based on the project's update channel.

Path parameters

NameTypeRequiredDescription
projectIdintegerYes

The ID of the project

Header parameters

NameTypeRequiredDescription
AuthorizationstringYes

Bearer <token>. Authentication lists the tokens it accepts.

X-Org-NamestringNo

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. A portal session token is bound to none, so it must send this header on every route but GET /v1/orgs (400 org_assertion_required otherwise).

  • Pattern: ^[A-Za-z0-9._-]{1,255}$

Request body

Optional

application/json

  • image_tagstring

    Override the runtime image tag for this deployment. Requires the Enterprise plan; omit it to deploy the image the project is configured with. When the effective update channel is stable or preview, a supplied tag must be a published version for that channel. When the effective update channel is nightly, a supplied tag must be a published spicehq/spiceai nightly-* tag (YYYYMMDDHHmm plus - plus 7 to 40 lowercase hex characters, for example 202609081124-cadf292).

  • channelstring

    Update channel that determines the runtime image

    • Allowed values: stable, preview, nightly
  • expected_update_channelstring

    If set, the stored project update channel must match this value or the request is refused with 409 update_channel_mismatch. This is a precondition, not an override (channel still changes the image train).

    • Allowed values: stable, preview, nightly
  • replicasinteger

    Override the number of replicas for this deployment

    • Minimum: 1
    • Maximum: 10
  • branchstring

    For a project connected to a GitHub repository, deploy spicepod.yaml from the head of this branch or tag of that repository instead of the production branch. The branch or tag must exist. With commit_sha, it must contain the commit. The production branch and the stored spicepod do not change, so the next deployment without a revision, and any automatic redeploy, deploy the production branch head again. A project with no connected repository refuses this field with 400 repository_not_connected. A project whose org has no GitHub App installation refuses it with 422 github_installation_missing. A request from the deploy GitHub Action (User-Agent spice-cloud-deploy-action) does not check or use this field for any project, because the Action sends the branch of its workflow run as metadata.

    • Minimum length: 1
    • Maximum length: 255
  • commit_shastring

    For a project connected to a GitHub repository, deploy spicepod.yaml from this commit instead of the head of the production branch. The commit must be on branch, or on the production branch (never a tag of the same name) when branch is omitted, so a commit that only a fork holds is refused. The deployment records the full SHA. The production branch and the stored spicepod do not change. A project with no connected repository refuses this field with 400 repository_not_connected. A project whose org has no GitHub App installation refuses it with 422 github_installation_missing. A request from the deploy GitHub Action (User-Agent spice-cloud-deploy-action) does not check or use this field for any project, because the Action sends the commit of its workflow run as metadata.

    • Pattern: ^[0-9a-fA-F]{7,40}$
  • commit_messagestring

    Not used. A deployment from a connected repository records the message of the commit it reads.

  • debugboolean

    Enable debug mode for this deployment

  • targetobject

    Optional per-deployment override. Omit (or { kind: cloud }) to place the deployment where the project itself runs — Spice-managed compute, its own BYOC cluster, or its attached standalone Cloud Connect instance — which is a property of the project, not of this request. Pass { kind: cluster, instance_id } to override that for this deployment and route it to a BYOC cluster connection; the cluster must be owned by the token's org, not in a terminal lifecycle state (decommissioning/archived), not paused, and the operator must hold a live connection (verified by the connectivity ping, not the Supabase lifecycle status). A standalone project cannot be overridden this way and is refused with 409.

    2 properties
    • kindstring

      • Allowed values: cloud, cluster
    • instance_idstring

      Required when kind is cluster.

Example request

curl -X POST "https://api.spice.ai/v1/projects/<projectId>/deployments" \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "image_tag": "string",
    "channel": "stable",
    "expected_update_channel": "stable",
    "replicas": 1,
    "branch": "string",
    "commit_sha": "string",
    "commit_message": "string",
    "debug": true,
    "target": {}
  }'

Responses

  • 202Accepted

    Deployment created and queued for processing

    application/json

    • idinteger

      Unique identifier for the deployment

    • statusstring

      Current status of the deployment

      • Allowed values: queued, in_progress, succeeded, failed, created
    • created_atstring (date-time)

      Timestamp when the deployment was created

    • updated_atstring (date-time) | null

      Timestamp when the deployment was last updated

    • image_tagstring | null

      Runtime image tag used for this deployment

    • replicasinteger

      Number of replicas

    • branchstring | null

      Git branch name

    • commit_shastring | null

      Git commit SHA

    • commit_messagestring | null

      Git commit message

    • error_codestring | null

      Set with error_message on failed and on in_progress while Cloud is retrying a scheduling block. Null on succeeded, on ordinary waiting in_progress, and on writers that predated this column. Older failed rows may still have a message with a null code.

    • error_messagestring | null

      Catalog copy for the current error_code. Older failed rows may still have a message with a null error_code.

    • creation_sourcestring | null

      Source that triggered the deployment

    • created_byinteger | null

      User ID who created the deployment

  • 400Bad Request

    Invalid request body, project has no spicepod configuration, the spicepod has been deleted, or the spicepod is paused (code: spicepod_paused; resume it with POST /v1/projects/{projectId}/resume before deploying). Also returned when the spicepod name, kind or version is missing or not valid: the body is { error: 'Invalid spicepod configuration' } with an issues array of {path, message}. The runtime checks all other spicepod fields when it loads the spicepod. For a standalone Cloud Connect project, also returned when the Spicepod references a ${secrets:...} name the project does not define: the body carries code: unknown_secret_references, a missing_secrets array of {name, path, suggestion?}, and secrets_url. When the effective update channel is stable or preview and image_tag is supplied, the tag must be a published version for that channel or the body is { error: 'Invalid image_tag for stable channel', code: 'invalid_stable_image_tag' } (or the preview analog). When the effective update channel is nightly and image_tag is supplied, the tag must be a published spicehq/spiceai nightly-* tag of the form YYYYMMDDHHmm plus - plus 7 to 40 lowercase hex characters (for example 202609081124-cadf292) or the body is { error: 'Invalid image_tag for nightly channel', code: 'invalid_nightly_image_tag' }. For a project connected to a GitHub repository, also returned when the root directory has no spicepod.yaml or it is invalid or too large (code: spicepod_not_found, spicepod_invalid or spicepod_too_large), when commit_sha is not on branch (or on the production branch when branch is omitted) (code: commit_not_on_branch), or when commit_sha comes without branch and the project has no production branch (code: branch_required). Nothing is dispatched and no deployment is recorded. Also returned when branch or commit_sha is sent for a project with no connected repository (code: repository_not_connected), except from the deploy GitHub Action. Nothing is dispatched.

  • 401Unauthorized

    Unauthorized

  • 403Forbidden

    Insufficient scope, viewer role cannot create deployments, image_tag was supplied outside the Enterprise plan (code: image_tag_requires_enterprise), the requested runtime image is not available for the organization plan (code: image_tag_not_allowed_for_plan), or the organization's GitHub App installation cannot read the connected repository (code: github_unauthorized or github_forbidden); omitting image_tag deploys the image the project is configured with

  • 404Not Found

    Project not found. For a cluster target, also returned when the BYOC cluster connection does not exist or is not owned by the token's org. Also returned when the connected GitHub repository, its production branch, or the requested branch or commit_sha was not found (code: github_not_found). With commit_sha and no branch, this includes a production branch that no longer exists.

  • 409Conflict

    A deployment is already in progress for this project (code: deployment_in_progress, with optional activeDeploymentId) — or, for a cluster target, the BYOC cluster is paused, offline, or otherwise not in a deployable state. Also returned when the project's deploy target is unusable: its kind conflicts with its cluster/instance references, a cluster target was requested for a standalone project, a standalone project has no attached instance, or that instance has not yet enrolled the encryption key its secrets are sealed to (retrying once it is online succeeds). Also returned when expected_update_channel does not match the stored spicepod update channel, or when that channel changes before dispatch (code: update_channel_mismatch).

  • 413Content Too Large

    Request body exceeds the maximum size (1 MiB), or — for a standalone Cloud Connect project — the project's resolved secrets exceed the maximum sealed-payload size. Nothing is dispatched and no deployment is recorded.

  • 422Unprocessable Content

    Organization is not fully configured, no runtime version in the catalog matches this project’s version range (code: version_no_match), or the spicepod uses version v1beta1, which the Spice 2 runtime cannot load (code: spicepod_version_unsupported). Also returned when the Spicepod uses a connection credential that holds a secret reference deploy cannot resolve: the body carries code: connection_credentials_unresolved and an unresolved_credentials array of {connection, field}. Nothing is deployed. Also returned when branch or commit_sha is sent for a project with a connected repository whose org has no GitHub App installation to read it (code: github_installation_missing), except from the deploy GitHub Action. Nothing is dispatched.

  • 429Too Many Requests

    GitHub rate-limited the read of the connected repository (code: github_rate_limited).

  • 500Internal Server Error

    Internal server error. For a standalone Cloud Connect project, also returned with code: deployment_not_settled when the deployment record could not be moved out of queued; the project's next deployment is refused until it is cleared.

  • 502Bad Gateway

    Upstream service failure while provisioning the deployment, or — for a standalone Cloud Connect project — the spicepod could not be handed to the instance's gateway, or the instance rejected it. Also returned when GitHub did not answer while the connected repository was read (code: github_unavailable).

  • 503Service Unavailable

    The runtime version catalog is unavailable or empty (code: version_source_unavailable), so an unpinned stable or preview deploy cannot resolve an image tag — or catalog membership for an explicit image_tag override cannot be validated. Also returned when the published nightly tag list cannot be loaded to validate a nightly image_tag override.

Get a deployment

GET/v1/projects/{projectId}/deployments/{deploymentId}

Returns a single deployment for the specified project. The body matches one item from GET /v1/projects/{projectId}/deployments. Not cacheable. Poll this path for stored status after POST create.

Path parameters

NameTypeRequiredDescription
projectIdintegerYes

The ID of the project

deploymentIdintegerYes

The ID of the deployment

Header parameters

NameTypeRequiredDescription
AuthorizationstringYes

Bearer <token>. Authentication lists the tokens it accepts.

X-Org-NamestringNo

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. A portal session token is bound to none, so it must send this header on every route but GET /v1/orgs (400 org_assertion_required otherwise).

  • Pattern: ^[A-Za-z0-9._-]{1,255}$

Example request

curl "https://api.spice.ai/v1/projects/<projectId>/deployments/<deploymentId>" \
  -H "Authorization: Bearer <token>"

Responses

  • 200OK

    Deployment

    application/json

    • idinteger

      Unique identifier for the deployment

    • statusstring

      Current status of the deployment

      • Allowed values: queued, in_progress, succeeded, failed, created
    • created_atstring (date-time)

      Timestamp when the deployment was created

    • updated_atstring (date-time) | null

      Timestamp when the deployment was last updated

    • image_tagstring | null

      Runtime image tag used for this deployment

    • replicasinteger

      Number of replicas

    • branchstring | null

      Git branch name

    • commit_shastring | null

      Git commit SHA

    • commit_messagestring | null

      Git commit message

    • error_codestring | null

      Set with error_message on failed and on in_progress while Cloud is retrying a scheduling block. Null on succeeded, on ordinary waiting in_progress, and on writers that predated this column. Older failed rows may still have a message with a null code.

    • error_messagestring | null

      Catalog copy for the current error_code. Older failed rows may still have a message with a null error_code.

    • creation_sourcestring | null

      Source that triggered the deployment

    • created_byinteger | null

      User ID who created the deployment

  • 400Bad Request

    Invalid project ID or deployment ID

  • 401Unauthorized

    Unauthorized

  • 403Forbidden

    Insufficient scope

  • 404Not Found

    Project or deployment not found

  • 500Internal Server Error

    Internal server error

List deployments

GET/v1/orgs/{orgId}/projects/{projectId}/deployments

The org is orgId in the path. Returns a list of deployments for the specified project, ordered by most recent first.

Path parameters

NameTypeRequiredDescription
orgIdintegerYes

The org id from GET /v1/orgs

  • Minimum: 1
projectIdintegerYes

The ID of the project

Query parameters

NameTypeRequiredDescription
limitintegerNo

Maximum number of deployments to return

  • Default: 20
statusstringNo

Filter by deployment status

  • Allowed values: queued, in_progress, succeeded, failed, created

Header parameters

NameTypeRequiredDescription
AuthorizationstringYes

Bearer <token>. Authentication lists the tokens it accepts.

X-Org-NamestringNo

When present, X-Org-Name must name the same org as orgId. Otherwise the request returns org_path_mismatch (400).

  • Pattern: ^[A-Za-z0-9._-]{1,255}$

Example request

curl "https://api.spice.ai/v1/orgs/<orgId>/projects/<projectId>/deployments" \
  -H "Authorization: Bearer <token>"

Responses

  • 200OK

    List of deployments

    application/json

    • deploymentsarray of object

      13 properties
      • idinteger

        Unique identifier for the deployment

      • statusstring

        Current status of the deployment

        • Allowed values: queued, in_progress, succeeded, failed, created
      • created_atstring (date-time)

        Timestamp when the deployment was created

      • updated_atstring (date-time) | null

        Timestamp when the deployment was last updated

      • image_tagstring | null

        Runtime image tag used for this deployment

      • replicasinteger

        Number of replicas

      • branchstring | null

        Git branch name

      • commit_shastring | null

        Git commit SHA

      • commit_messagestring | null

        Git commit message

      • error_codestring | null

        Set with error_message on failed and on in_progress while Cloud is retrying a scheduling block. Null on succeeded, on ordinary waiting in_progress, and on writers that predated this column. Older failed rows may still have a message with a null code.

      • error_messagestring | null

        Catalog copy for the current error_code. Older failed rows may still have a message with a null error_code.

      • creation_sourcestring | null

        Source that triggered the deployment

      • created_byinteger | null

        User ID who created the deployment

  • 400Bad Request

    orgId is not a valid org id (invalid_org_id), or X-Org-Name does not name that org (org_path_mismatch).

  • 401Unauthorized

    Unauthorized

  • 403Forbidden

    Insufficient scope. The caller is not a member of the org (org_forbidden). A machine credential named a different org (org_assertion_mismatch). The org is deleted (org_deleted).

  • 404Not Found

    Project not found

Create a deployment

POST/v1/orgs/{orgId}/projects/{projectId}/deployments

The org is orgId in the path. Creates a new deployment for the specified project using its current spicepod configuration. A project connected to a GitHub repository deploys spicepod.yaml from its root directory, read when the deployment is created. It reads the head of the production branch, or the branch or commit_sha the request names. The runtime image is selected based on the project's update channel.

Path parameters

NameTypeRequiredDescription
orgIdintegerYes

The org id from GET /v1/orgs

  • Minimum: 1
projectIdintegerYes

The ID of the project

Header parameters

NameTypeRequiredDescription
AuthorizationstringYes

Bearer <token>. Authentication lists the tokens it accepts.

X-Org-NamestringNo

When present, X-Org-Name must name the same org as orgId. Otherwise the request returns org_path_mismatch (400).

  • Pattern: ^[A-Za-z0-9._-]{1,255}$

Request body

Optional

application/json

  • image_tagstring

    Override the runtime image tag for this deployment. Requires the Enterprise plan; omit it to deploy the image the project is configured with. When the effective update channel is stable or preview, a supplied tag must be a published version for that channel. When the effective update channel is nightly, a supplied tag must be a published spicehq/spiceai nightly-* tag (YYYYMMDDHHmm plus - plus 7 to 40 lowercase hex characters, for example 202609081124-cadf292).

  • channelstring

    Update channel that determines the runtime image

    • Allowed values: stable, preview, nightly
  • expected_update_channelstring

    If set, the stored project update channel must match this value or the request is refused with 409 update_channel_mismatch. This is a precondition, not an override (channel still changes the image train).

    • Allowed values: stable, preview, nightly
  • replicasinteger

    Override the number of replicas for this deployment

    • Minimum: 1
    • Maximum: 10
  • branchstring

    For a project connected to a GitHub repository, deploy spicepod.yaml from the head of this branch or tag of that repository instead of the production branch. The branch or tag must exist. With commit_sha, it must contain the commit. The production branch and the stored spicepod do not change, so the next deployment without a revision, and any automatic redeploy, deploy the production branch head again. A project with no connected repository refuses this field with 400 repository_not_connected. A project whose org has no GitHub App installation refuses it with 422 github_installation_missing. A request from the deploy GitHub Action (User-Agent spice-cloud-deploy-action) does not check or use this field for any project, because the Action sends the branch of its workflow run as metadata.

    • Minimum length: 1
    • Maximum length: 255
  • commit_shastring

    For a project connected to a GitHub repository, deploy spicepod.yaml from this commit instead of the head of the production branch. The commit must be on branch, or on the production branch (never a tag of the same name) when branch is omitted, so a commit that only a fork holds is refused. The deployment records the full SHA. The production branch and the stored spicepod do not change. A project with no connected repository refuses this field with 400 repository_not_connected. A project whose org has no GitHub App installation refuses it with 422 github_installation_missing. A request from the deploy GitHub Action (User-Agent spice-cloud-deploy-action) does not check or use this field for any project, because the Action sends the commit of its workflow run as metadata.

    • Pattern: ^[0-9a-fA-F]{7,40}$
  • commit_messagestring

    Not used. A deployment from a connected repository records the message of the commit it reads.

  • debugboolean

    Enable debug mode for this deployment

  • targetobject

    Optional per-deployment override. Omit (or { kind: cloud }) to place the deployment where the project itself runs — Spice-managed compute, its own BYOC cluster, or its attached standalone Cloud Connect instance — which is a property of the project, not of this request. Pass { kind: cluster, instance_id } to override that for this deployment and route it to a BYOC cluster connection; the cluster must be owned by the token's org, not in a terminal lifecycle state (decommissioning/archived), not paused, and the operator must hold a live connection (verified by the connectivity ping, not the Supabase lifecycle status). A standalone project cannot be overridden this way and is refused with 409.

    2 properties
    • kindstring

      • Allowed values: cloud, cluster
    • instance_idstring

      Required when kind is cluster.

Example request

curl -X POST "https://api.spice.ai/v1/orgs/<orgId>/projects/<projectId>/deployments" \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "image_tag": "string",
    "channel": "stable",
    "expected_update_channel": "stable",
    "replicas": 1,
    "branch": "string",
    "commit_sha": "string",
    "commit_message": "string",
    "debug": true,
    "target": {}
  }'

Responses

  • 202Accepted

    Deployment created and queued for processing

    application/json

    • idinteger

      Unique identifier for the deployment

    • statusstring

      Current status of the deployment

      • Allowed values: queued, in_progress, succeeded, failed, created
    • created_atstring (date-time)

      Timestamp when the deployment was created

    • updated_atstring (date-time) | null

      Timestamp when the deployment was last updated

    • image_tagstring | null

      Runtime image tag used for this deployment

    • replicasinteger

      Number of replicas

    • branchstring | null

      Git branch name

    • commit_shastring | null

      Git commit SHA

    • commit_messagestring | null

      Git commit message

    • error_codestring | null

      Set with error_message on failed and on in_progress while Cloud is retrying a scheduling block. Null on succeeded, on ordinary waiting in_progress, and on writers that predated this column. Older failed rows may still have a message with a null code.

    • error_messagestring | null

      Catalog copy for the current error_code. Older failed rows may still have a message with a null error_code.

    • creation_sourcestring | null

      Source that triggered the deployment

    • created_byinteger | null

      User ID who created the deployment

  • 400Bad Request

    Invalid request body, project has no spicepod configuration, the spicepod has been deleted, or the spicepod is paused (code: spicepod_paused; resume it with POST /v1/projects/{projectId}/resume before deploying). Also returned when the spicepod name, kind or version is missing or not valid: the body is { error: 'Invalid spicepod configuration' } with an issues array of {path, message}. The runtime checks all other spicepod fields when it loads the spicepod. For a standalone Cloud Connect project, also returned when the Spicepod references a ${secrets:...} name the project does not define: the body carries code: unknown_secret_references, a missing_secrets array of {name, path, suggestion?}, and secrets_url. When the effective update channel is stable or preview and image_tag is supplied, the tag must be a published version for that channel or the body is { error: 'Invalid image_tag for stable channel', code: 'invalid_stable_image_tag' } (or the preview analog). When the effective update channel is nightly and image_tag is supplied, the tag must be a published spicehq/spiceai nightly-* tag of the form YYYYMMDDHHmm plus - plus 7 to 40 lowercase hex characters (for example 202609081124-cadf292) or the body is { error: 'Invalid image_tag for nightly channel', code: 'invalid_nightly_image_tag' }. For a project connected to a GitHub repository, also returned when the root directory has no spicepod.yaml or it is invalid or too large (code: spicepod_not_found, spicepod_invalid or spicepod_too_large), when commit_sha is not on branch (or on the production branch when branch is omitted) (code: commit_not_on_branch), or when commit_sha comes without branch and the project has no production branch (code: branch_required). Nothing is dispatched and no deployment is recorded. Also returned when branch or commit_sha is sent for a project with no connected repository (code: repository_not_connected), except from the deploy GitHub Action. Nothing is dispatched. orgId is not a valid org id (invalid_org_id), or X-Org-Name does not name that org (org_path_mismatch).

  • 401Unauthorized

    Unauthorized

  • 403Forbidden

    Insufficient scope, viewer role cannot create deployments, image_tag was supplied outside the Enterprise plan (code: image_tag_requires_enterprise), the requested runtime image is not available for the organization plan (code: image_tag_not_allowed_for_plan), or the organization's GitHub App installation cannot read the connected repository (code: github_unauthorized or github_forbidden); omitting image_tag deploys the image the project is configured with. The caller is not a member of the org (org_forbidden). A machine credential named a different org (org_assertion_mismatch). The org is deleted (org_deleted).

  • 404Not Found

    Project not found. For a cluster target, also returned when the BYOC cluster connection does not exist or is not owned by the token's org. Also returned when the connected GitHub repository, its production branch, or the requested branch or commit_sha was not found (code: github_not_found). With commit_sha and no branch, this includes a production branch that no longer exists.

  • 409Conflict

    A deployment is already in progress for this project (code: deployment_in_progress, with optional activeDeploymentId) — or, for a cluster target, the BYOC cluster is paused, offline, or otherwise not in a deployable state. Also returned when the project's deploy target is unusable: its kind conflicts with its cluster/instance references, a cluster target was requested for a standalone project, a standalone project has no attached instance, or that instance has not yet enrolled the encryption key its secrets are sealed to (retrying once it is online succeeds). Also returned when expected_update_channel does not match the stored spicepod update channel, or when that channel changes before dispatch (code: update_channel_mismatch).

  • 413Content Too Large

    Request body exceeds the maximum size (1 MiB), or — for a standalone Cloud Connect project — the project's resolved secrets exceed the maximum sealed-payload size. Nothing is dispatched and no deployment is recorded.

  • 422Unprocessable Content

    Organization is not fully configured, no runtime version in the catalog matches this project’s version range (code: version_no_match), or the spicepod uses version v1beta1, which the Spice 2 runtime cannot load (code: spicepod_version_unsupported). Also returned when the Spicepod uses a connection credential that holds a secret reference deploy cannot resolve: the body carries code: connection_credentials_unresolved and an unresolved_credentials array of {connection, field}. Nothing is deployed. Also returned when branch or commit_sha is sent for a project with a connected repository whose org has no GitHub App installation to read it (code: github_installation_missing), except from the deploy GitHub Action. Nothing is dispatched.

  • 429Too Many Requests

    GitHub rate-limited the read of the connected repository (code: github_rate_limited).

  • 500Internal Server Error

    Internal server error. For a standalone Cloud Connect project, also returned with code: deployment_not_settled when the deployment record could not be moved out of queued; the project's next deployment is refused until it is cleared.

  • 502Bad Gateway

    Upstream service failure while provisioning the deployment, or — for a standalone Cloud Connect project — the spicepod could not be handed to the instance's gateway, or the instance rejected it. Also returned when GitHub did not answer while the connected repository was read (code: github_unavailable).

  • 503Service Unavailable

    The runtime version catalog is unavailable or empty (code: version_source_unavailable), so an unpinned stable or preview deploy cannot resolve an image tag — or catalog membership for an explicit image_tag override cannot be validated. Also returned when the published nightly tag list cannot be loaded to validate a nightly image_tag override.

Get a deployment

GET/v1/orgs/{orgId}/projects/{projectId}/deployments/{deploymentId}

The org is orgId in the path. Returns a single deployment for the specified project. The body matches one item from GET /v1/projects/{projectId}/deployments. Not cacheable. Poll this path for stored status after POST create.

Path parameters

NameTypeRequiredDescription
orgIdintegerYes

The org id from GET /v1/orgs

  • Minimum: 1
projectIdintegerYes

The ID of the project

deploymentIdintegerYes

The ID of the deployment

Header parameters

NameTypeRequiredDescription
AuthorizationstringYes

Bearer <token>. Authentication lists the tokens it accepts.

X-Org-NamestringNo

When present, X-Org-Name must name the same org as orgId. Otherwise the request returns org_path_mismatch (400).

  • Pattern: ^[A-Za-z0-9._-]{1,255}$

Example request

curl "https://api.spice.ai/v1/orgs/<orgId>/projects/<projectId>/deployments/<deploymentId>" \
  -H "Authorization: Bearer <token>"

Responses

  • 200OK

    Deployment

    application/json

    • idinteger

      Unique identifier for the deployment

    • statusstring

      Current status of the deployment

      • Allowed values: queued, in_progress, succeeded, failed, created
    • created_atstring (date-time)

      Timestamp when the deployment was created

    • updated_atstring (date-time) | null

      Timestamp when the deployment was last updated

    • image_tagstring | null

      Runtime image tag used for this deployment

    • replicasinteger

      Number of replicas

    • branchstring | null

      Git branch name

    • commit_shastring | null

      Git commit SHA

    • commit_messagestring | null

      Git commit message

    • error_codestring | null

      Set with error_message on failed and on in_progress while Cloud is retrying a scheduling block. Null on succeeded, on ordinary waiting in_progress, and on writers that predated this column. Older failed rows may still have a message with a null code.

    • error_messagestring | null

      Catalog copy for the current error_code. Older failed rows may still have a message with a null error_code.

    • creation_sourcestring | null

      Source that triggered the deployment

    • created_byinteger | null

      User ID who created the deployment

  • 400Bad Request

    Invalid project ID or deployment ID. orgId is not a valid org id (invalid_org_id), or X-Org-Name does not name that org (org_path_mismatch).

  • 401Unauthorized

    Unauthorized

  • 403Forbidden

    Insufficient scope. The caller is not a member of the org (org_forbidden). A machine credential named a different org (org_assertion_mismatch). The org is deleted (org_deleted).

  • 404Not Found

    Project or deployment not found

  • 500Internal Server Error

    Internal server error

List deployments

GET/v1/apps/{appId}/deploymentsDeprecated

Legacy alias of /v1/projects/{projectId}/deployments — projects were previously called apps. Returns a list of deployments for the specified project, ordered by most recent first.

Path parameters

NameTypeRequiredDescription
appIdintegerYes

The ID of the project

Query parameters

NameTypeRequiredDescription
limitintegerNo

Maximum number of deployments to return

  • Default: 20
statusstringNo

Filter by deployment status

  • Allowed values: queued, in_progress, succeeded, failed, created

Header parameters

NameTypeRequiredDescription
AuthorizationstringYes

Bearer <token>. Authentication lists the tokens it accepts.

X-Org-NamestringNo

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. A portal session token is bound to none, so it must send this header on every route but GET /v1/orgs (400 org_assertion_required otherwise).

  • Pattern: ^[A-Za-z0-9._-]{1,255}$

Example request

curl "https://api.spice.ai/v1/apps/<appId>/deployments" \
  -H "Authorization: Bearer <token>"

Responses

  • 200OK

    List of deployments

    application/json

    • deploymentsarray of object

      13 properties
      • idinteger

        Unique identifier for the deployment

      • statusstring

        Current status of the deployment

        • Allowed values: queued, in_progress, succeeded, failed, created
      • created_atstring (date-time)

        Timestamp when the deployment was created

      • updated_atstring (date-time) | null

        Timestamp when the deployment was last updated

      • image_tagstring | null

        Runtime image tag used for this deployment

      • replicasinteger

        Number of replicas

      • branchstring | null

        Git branch name

      • commit_shastring | null

        Git commit SHA

      • commit_messagestring | null

        Git commit message

      • error_codestring | null

        Set with error_message on failed and on in_progress while Cloud is retrying a scheduling block. Null on succeeded, on ordinary waiting in_progress, and on writers that predated this column. Older failed rows may still have a message with a null code.

      • error_messagestring | null

        Catalog copy for the current error_code. Older failed rows may still have a message with a null error_code.

      • creation_sourcestring | null

        Source that triggered the deployment

      • created_byinteger | null

        User ID who created the deployment

  • 401Unauthorized

    Unauthorized

  • 403Forbidden

    Insufficient scope

  • 404Not Found

    Project not found

Create a deployment

POST/v1/apps/{appId}/deploymentsDeprecated

Legacy alias of /v1/projects/{projectId}/deployments — projects were previously called apps. Creates a new deployment for the specified project using its current spicepod configuration. A project connected to a GitHub repository deploys spicepod.yaml from its root directory, read when the deployment is created. It reads the head of the production branch, or the branch or commit_sha the request names. The runtime image is selected based on the project's update channel.

Path parameters

NameTypeRequiredDescription
appIdintegerYes

The ID of the project

Header parameters

NameTypeRequiredDescription
AuthorizationstringYes

Bearer <token>. Authentication lists the tokens it accepts.

X-Org-NamestringNo

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. A portal session token is bound to none, so it must send this header on every route but GET /v1/orgs (400 org_assertion_required otherwise).

  • Pattern: ^[A-Za-z0-9._-]{1,255}$

Request body

Optional

application/json

  • image_tagstring

    Override the runtime image tag for this deployment. Requires the Enterprise plan; omit it to deploy the image the project is configured with. When the effective update channel is stable or preview, a supplied tag must be a published version for that channel. When the effective update channel is nightly, a supplied tag must be a published spicehq/spiceai nightly-* tag (YYYYMMDDHHmm plus - plus 7 to 40 lowercase hex characters, for example 202609081124-cadf292).

  • channelstring

    Update channel that determines the runtime image

    • Allowed values: stable, preview, nightly
  • expected_update_channelstring

    If set, the stored project update channel must match this value or the request is refused with 409 update_channel_mismatch. This is a precondition, not an override (channel still changes the image train).

    • Allowed values: stable, preview, nightly
  • replicasinteger

    Override the number of replicas for this deployment

    • Minimum: 1
    • Maximum: 10
  • branchstring

    For a project connected to a GitHub repository, deploy spicepod.yaml from the head of this branch or tag of that repository instead of the production branch. The branch or tag must exist. With commit_sha, it must contain the commit. The production branch and the stored spicepod do not change, so the next deployment without a revision, and any automatic redeploy, deploy the production branch head again. A project with no connected repository refuses this field with 400 repository_not_connected. A project whose org has no GitHub App installation refuses it with 422 github_installation_missing. A request from the deploy GitHub Action (User-Agent spice-cloud-deploy-action) does not check or use this field for any project, because the Action sends the branch of its workflow run as metadata.

    • Minimum length: 1
    • Maximum length: 255
  • commit_shastring

    For a project connected to a GitHub repository, deploy spicepod.yaml from this commit instead of the head of the production branch. The commit must be on branch, or on the production branch (never a tag of the same name) when branch is omitted, so a commit that only a fork holds is refused. The deployment records the full SHA. The production branch and the stored spicepod do not change. A project with no connected repository refuses this field with 400 repository_not_connected. A project whose org has no GitHub App installation refuses it with 422 github_installation_missing. A request from the deploy GitHub Action (User-Agent spice-cloud-deploy-action) does not check or use this field for any project, because the Action sends the commit of its workflow run as metadata.

    • Pattern: ^[0-9a-fA-F]{7,40}$
  • commit_messagestring

    Not used. A deployment from a connected repository records the message of the commit it reads.

  • debugboolean

    Enable debug mode for this deployment

  • targetobject

    Optional per-deployment override. Omit (or { kind: cloud }) to place the deployment where the project itself runs — Spice-managed compute, its own BYOC cluster, or its attached standalone Cloud Connect instance — which is a property of the project, not of this request. Pass { kind: cluster, instance_id } to override that for this deployment and route it to a BYOC cluster connection; the cluster must be owned by the token's org, not in a terminal lifecycle state (decommissioning/archived), not paused, and the operator must hold a live connection (verified by the connectivity ping, not the Supabase lifecycle status). A standalone project cannot be overridden this way and is refused with 409.

    2 properties
    • kindstring

      • Allowed values: cloud, cluster
    • instance_idstring

      Required when kind is cluster.

Example request

curl -X POST "https://api.spice.ai/v1/apps/<appId>/deployments" \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "image_tag": "string",
    "channel": "stable",
    "expected_update_channel": "stable",
    "replicas": 1,
    "branch": "string",
    "commit_sha": "string",
    "commit_message": "string",
    "debug": true,
    "target": {}
  }'

Responses

  • 202Accepted

    Deployment created and queued for processing

    application/json

    • idinteger

      Unique identifier for the deployment

    • statusstring

      Current status of the deployment

      • Allowed values: queued, in_progress, succeeded, failed, created
    • created_atstring (date-time)

      Timestamp when the deployment was created

    • updated_atstring (date-time) | null

      Timestamp when the deployment was last updated

    • image_tagstring | null

      Runtime image tag used for this deployment

    • replicasinteger

      Number of replicas

    • branchstring | null

      Git branch name

    • commit_shastring | null

      Git commit SHA

    • commit_messagestring | null

      Git commit message

    • error_codestring | null

      Set with error_message on failed and on in_progress while Cloud is retrying a scheduling block. Null on succeeded, on ordinary waiting in_progress, and on writers that predated this column. Older failed rows may still have a message with a null code.

    • error_messagestring | null

      Catalog copy for the current error_code. Older failed rows may still have a message with a null error_code.

    • creation_sourcestring | null

      Source that triggered the deployment

    • created_byinteger | null

      User ID who created the deployment

  • 400Bad Request

    Invalid request body, project has no spicepod configuration, the spicepod has been deleted, or the spicepod is paused (code: spicepod_paused; resume it with POST /v1/projects/{projectId}/resume before deploying). Also returned when the spicepod name, kind or version is missing or not valid: the body is { error: 'Invalid spicepod configuration' } with an issues array of {path, message}. The runtime checks all other spicepod fields when it loads the spicepod. For a standalone Cloud Connect project, also returned when the Spicepod references a ${secrets:...} name the project does not define: the body carries code: unknown_secret_references, a missing_secrets array of {name, path, suggestion?}, and secrets_url. When the effective update channel is stable or preview and image_tag is supplied, the tag must be a published version for that channel or the body is { error: 'Invalid image_tag for stable channel', code: 'invalid_stable_image_tag' } (or the preview analog). When the effective update channel is nightly and image_tag is supplied, the tag must be a published spicehq/spiceai nightly-* tag of the form YYYYMMDDHHmm plus - plus 7 to 40 lowercase hex characters (for example 202609081124-cadf292) or the body is { error: 'Invalid image_tag for nightly channel', code: 'invalid_nightly_image_tag' }. For a project connected to a GitHub repository, also returned when the root directory has no spicepod.yaml or it is invalid or too large (code: spicepod_not_found, spicepod_invalid or spicepod_too_large), when commit_sha is not on branch (or on the production branch when branch is omitted) (code: commit_not_on_branch), or when commit_sha comes without branch and the project has no production branch (code: branch_required). Nothing is dispatched and no deployment is recorded. Also returned when branch or commit_sha is sent for a project with no connected repository (code: repository_not_connected), except from the deploy GitHub Action. Nothing is dispatched.

  • 401Unauthorized

    Unauthorized

  • 403Forbidden

    Insufficient scope, viewer role cannot create deployments, image_tag was supplied outside the Enterprise plan (code: image_tag_requires_enterprise), the requested runtime image is not available for the organization plan (code: image_tag_not_allowed_for_plan), or the organization's GitHub App installation cannot read the connected repository (code: github_unauthorized or github_forbidden); omitting image_tag deploys the image the project is configured with

  • 404Not Found

    Project not found. For a cluster target, also returned when the BYOC cluster connection does not exist or is not owned by the token's org. Also returned when the connected GitHub repository, its production branch, or the requested branch or commit_sha was not found (code: github_not_found). With commit_sha and no branch, this includes a production branch that no longer exists.

  • 409Conflict

    A deployment is already in progress for this project (code: deployment_in_progress, with optional activeDeploymentId) — or, for a cluster target, the BYOC cluster is paused, offline, or otherwise not in a deployable state. Also returned when the project's deploy target is unusable: its kind conflicts with its cluster/instance references, a cluster target was requested for a standalone project, a standalone project has no attached instance, or that instance has not yet enrolled the encryption key its secrets are sealed to (retrying once it is online succeeds). Also returned when expected_update_channel does not match the stored spicepod update channel, or when that channel changes before dispatch (code: update_channel_mismatch).

  • 413Content Too Large

    Request body exceeds the maximum size (1 MiB), or — for a standalone Cloud Connect project — the project's resolved secrets exceed the maximum sealed-payload size. Nothing is dispatched and no deployment is recorded.

  • 422Unprocessable Content

    Organization is not fully configured, no runtime version in the catalog matches this project’s version range (code: version_no_match), or the spicepod uses version v1beta1, which the Spice 2 runtime cannot load (code: spicepod_version_unsupported). Also returned when the Spicepod uses a connection credential that holds a secret reference deploy cannot resolve: the body carries code: connection_credentials_unresolved and an unresolved_credentials array of {connection, field}. Nothing is deployed. Also returned when branch or commit_sha is sent for a project with a connected repository whose org has no GitHub App installation to read it (code: github_installation_missing), except from the deploy GitHub Action. Nothing is dispatched.

  • 429Too Many Requests

    GitHub rate-limited the read of the connected repository (code: github_rate_limited).

  • 500Internal Server Error

    Internal server error. For a standalone Cloud Connect project, also returned with code: deployment_not_settled when the deployment record could not be moved out of queued; the project's next deployment is refused until it is cleared.

  • 502Bad Gateway

    Upstream service failure while provisioning the deployment, or — for a standalone Cloud Connect project — the spicepod could not be handed to the instance's gateway, or the instance rejected it. Also returned when GitHub did not answer while the connected repository was read (code: github_unavailable).

  • 503Service Unavailable

    The runtime version catalog is unavailable or empty (code: version_source_unavailable), so an unpinned stable or preview deploy cannot resolve an image tag — or catalog membership for an explicit image_tag override cannot be validated. Also returned when the published nightly tag list cannot be loaded to validate a nightly image_tag override.

Get a deployment

GET/v1/apps/{appId}/deployments/{deploymentId}Deprecated

Legacy alias of /v1/projects/{projectId}/deployments/{deploymentId} — projects were previously called apps. Returns a single deployment for the specified project. The body matches one item from GET /v1/projects/{projectId}/deployments. Not cacheable. Poll this path for stored status after POST create.

Path parameters

NameTypeRequiredDescription
appIdintegerYes

The ID of the project

deploymentIdintegerYes

The ID of the deployment

Header parameters

NameTypeRequiredDescription
AuthorizationstringYes

Bearer <token>. Authentication lists the tokens it accepts.

X-Org-NamestringNo

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. A portal session token is bound to none, so it must send this header on every route but GET /v1/orgs (400 org_assertion_required otherwise).

  • Pattern: ^[A-Za-z0-9._-]{1,255}$

Example request

curl "https://api.spice.ai/v1/apps/<appId>/deployments/<deploymentId>" \
  -H "Authorization: Bearer <token>"

Responses

  • 200OK

    Deployment

    application/json

    • idinteger

      Unique identifier for the deployment

    • statusstring

      Current status of the deployment

      • Allowed values: queued, in_progress, succeeded, failed, created
    • created_atstring (date-time)

      Timestamp when the deployment was created

    • updated_atstring (date-time) | null

      Timestamp when the deployment was last updated

    • image_tagstring | null

      Runtime image tag used for this deployment

    • replicasinteger

      Number of replicas

    • branchstring | null

      Git branch name

    • commit_shastring | null

      Git commit SHA

    • commit_messagestring | null

      Git commit message

    • error_codestring | null

      Set with error_message on failed and on in_progress while Cloud is retrying a scheduling block. Null on succeeded, on ordinary waiting in_progress, and on writers that predated this column. Older failed rows may still have a message with a null code.

    • error_messagestring | null

      Catalog copy for the current error_code. Older failed rows may still have a message with a null error_code.

    • creation_sourcestring | null

      Source that triggered the deployment

    • created_byinteger | null

      User ID who created the deployment

  • 400Bad Request

    Invalid project ID or deployment ID

  • 401Unauthorized

    Unauthorized

  • 403Forbidden

    Insufficient scope

  • 404Not Found

    Project or deployment not found

  • 500Internal Server Error

    Internal server error