Management APIs / Projects

Connect a project to a GitHub repository

PUThttps://api.spice.ai/v1/projects/{projectId}/repository

Connects the project to a repository in the organization's GitHub account, through the organization's Spice Cloud GitHub App installation. The next deployment reads spicepod.yaml (or spicepod.yml) from root_directory on production_branch. Connecting sets the project description to the repository description. Connecting again replaces the repository, root directory and production branch. Requires apps:write.

Authorizations

  • AuthorizationstringRequired

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

Path parameters

  • projectIdintegerRequired

    The ID of the project to connect

Header parameters

  • X-Org-Namestring

    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}$

Body

application/jsonRequired

  • repositorystringRequired

    Repository in the organization's GitHub account, as name or owner/name. The owner must be the organization's GitHub account.

    • Example: cookbook
  • root_directorystring | null

    Directory inside the repository that contains spicepod.yaml. Omit it, or send null or an empty string, for the repository root.

    • Maximum length: 512
    • Example: cayenne
  • production_branchstring

    Branch that deployments read. Defaults to the repository's default branch. A branch that GitHub renamed is stored under its new name.

    • Maximum length: 255
    • Example: trunk

Responses

200Project connectedapplication/json
  • project_idintegerRequired

    The project ID

  • repositorystringRequired

    The repository as owner/name

  • repository_idintegerRequired

    The GitHub repository ID

  • root_directorystring | nullRequired

    The stored root directory. Null is the repository root.

  • production_branchstringRequired

    The branch that deployments read

  • connected_atstring (date-time)Required

    When the project was connected

  • has_spicepodbooleanRequired

    True when spicepod.yaml or spicepod.yml exists in the root directory on the production branch. A deployment fails until it does.

400Bad Request

Invalid project ID or request body, a repository outside the organization's GitHub account (code: invalid_repository), or a root directory outside the repository (code: invalid_root_directory)

401Unauthorized

403Insufficient scope, or viewer role cannot mutate projects

404Not Found

Project not found, or the organization's GitHub App installation cannot read the repository (code: repository_not_found)

409Conflict

The organization has no usable GitHub App installation (code: github_not_connected), or another project already deploys this repository and root directory (code: root_directory_conflict)

413Request body too large

422Unprocessable Content

The repository has no branch named production_branch (code: branch_not_found), the project has no spicepod configuration (code: spicepod_missing), or the organization is not fully configured

500Internal server error

503GitHub did not answer (code: github_unavailable)

curl -X PUT "https://api.spice.ai/v1/projects/<projectId>/repository" \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "repository": "cookbook"
  }'
{
  "project_id": 0,
  "repository": "string",
  "repository_id": 0,
  "root_directory": "string",
  "production_branch": "string",
  "connected_at": "2026-01-01T00:00:00Z",
  "has_spicepod": true
}

application/json

PUThttps://api.spice.ai/v1/orgs/{orgId}/projects/{projectId}/repository

The org is orgId in the path. Connects the project to a repository in the organization's GitHub account, through the organization's Spice Cloud GitHub App installation. The next deployment reads spicepod.yaml (or spicepod.yml) from root_directory on production_branch. Connecting sets the project description to the repository description. Connecting again replaces the repository, root directory and production branch. Requires apps:write.

Authorizations

  • AuthorizationstringRequired

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

Path parameters

  • orgIdintegerRequired

    The org id from GET /v1/orgs

    • Minimum: 1
  • projectIdintegerRequired

    The ID of the project to connect

Header parameters

  • X-Org-Namestring

    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}$

Body

application/jsonRequired

  • repositorystringRequired

    Repository in the organization's GitHub account, as name or owner/name. The owner must be the organization's GitHub account.

    • Example: cookbook
  • root_directorystring | null

    Directory inside the repository that contains spicepod.yaml. Omit it, or send null or an empty string, for the repository root.

    • Maximum length: 512
    • Example: cayenne
  • production_branchstring

    Branch that deployments read. Defaults to the repository's default branch. A branch that GitHub renamed is stored under its new name.

    • Maximum length: 255
    • Example: trunk

Responses

200Project connectedapplication/json
  • project_idintegerRequired

    The project ID

  • repositorystringRequired

    The repository as owner/name

  • repository_idintegerRequired

    The GitHub repository ID

  • root_directorystring | nullRequired

    The stored root directory. Null is the repository root.

  • production_branchstringRequired

    The branch that deployments read

  • connected_atstring (date-time)Required

    When the project was connected

  • has_spicepodbooleanRequired

    True when spicepod.yaml or spicepod.yml exists in the root directory on the production branch. A deployment fails until it does.

400Bad Request

Invalid project ID or request body, a repository outside the organization's GitHub account (code: invalid_repository), or a root directory outside the repository (code: invalid_root_directory). orgId is not a valid org id (invalid_org_id), or X-Org-Name does not name that org (org_path_mismatch).

401Unauthorized

403Forbidden

Insufficient scope, or viewer role cannot mutate projects. 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, or the organization's GitHub App installation cannot read the repository (code: repository_not_found)

409Conflict

The organization has no usable GitHub App installation (code: github_not_connected), or another project already deploys this repository and root directory (code: root_directory_conflict)

413Request body too large

422Unprocessable Content

The repository has no branch named production_branch (code: branch_not_found), the project has no spicepod configuration (code: spicepod_missing), or the organization is not fully configured

500Internal server error

503GitHub did not answer (code: github_unavailable)

curl -X PUT "https://api.spice.ai/v1/orgs/<orgId>/projects/<projectId>/repository" \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "repository": "cookbook"
  }'
{
  "project_id": 0,
  "repository": "string",
  "repository_id": 0,
  "root_directory": "string",
  "production_branch": "string",
  "connected_at": "2026-01-01T00:00:00Z",
  "has_spicepod": true
}

application/json

PUThttps://api.spice.ai/v1/apps/{appId}/repositoryDeprecated

Legacy alias of /v1/projects/{projectId}/repository — projects were previously called apps. Connects the project to a repository in the organization's GitHub account, through the organization's Spice Cloud GitHub App installation. The next deployment reads spicepod.yaml (or spicepod.yml) from root_directory on production_branch. Connecting sets the project description to the repository description. Connecting again replaces the repository, root directory and production branch. Requires apps:write.

Authorizations

  • AuthorizationstringRequired

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

Path parameters

  • appIdintegerRequired

    The ID of the project to connect

Header parameters

  • X-Org-Namestring

    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}$

Body

application/jsonRequired

  • repositorystringRequired

    Repository in the organization's GitHub account, as name or owner/name. The owner must be the organization's GitHub account.

    • Example: cookbook
  • root_directorystring | null

    Directory inside the repository that contains spicepod.yaml. Omit it, or send null or an empty string, for the repository root.

    • Maximum length: 512
    • Example: cayenne
  • production_branchstring

    Branch that deployments read. Defaults to the repository's default branch. A branch that GitHub renamed is stored under its new name.

    • Maximum length: 255
    • Example: trunk

Responses

200Project connectedapplication/json
  • project_idintegerRequired

    The project ID

  • repositorystringRequired

    The repository as owner/name

  • repository_idintegerRequired

    The GitHub repository ID

  • root_directorystring | nullRequired

    The stored root directory. Null is the repository root.

  • production_branchstringRequired

    The branch that deployments read

  • connected_atstring (date-time)Required

    When the project was connected

  • has_spicepodbooleanRequired

    True when spicepod.yaml or spicepod.yml exists in the root directory on the production branch. A deployment fails until it does.

400Bad Request

Invalid project ID or request body, a repository outside the organization's GitHub account (code: invalid_repository), or a root directory outside the repository (code: invalid_root_directory)

401Unauthorized

403Insufficient scope, or viewer role cannot mutate projects

404Not Found

Project not found, or the organization's GitHub App installation cannot read the repository (code: repository_not_found)

409Conflict

The organization has no usable GitHub App installation (code: github_not_connected), or another project already deploys this repository and root directory (code: root_directory_conflict)

413Request body too large

422Unprocessable Content

The repository has no branch named production_branch (code: branch_not_found), the project has no spicepod configuration (code: spicepod_missing), or the organization is not fully configured

500Internal server error

503GitHub did not answer (code: github_unavailable)

OpenAPIapi.spice.ai/openapi.json

curl -X PUT "https://api.spice.ai/v1/apps/<appId>/repository" \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "repository": "cookbook"
  }'
{
  "project_id": 0,
  "repository": "string",
  "repository_id": 0,
  "root_directory": "string",
  "production_branch": "string",
  "connected_at": "2026-01-01T00:00:00Z",
  "has_spicepod": true
}

application/json