Update a project
Change a project: its name, description, root directory, what it is, where it runs and its links.
/workspaces/{workspace}/projects/{project}Only what you give changes. kind auto and runs auto leave each to detection. Setting runs makes it an app unless it is docs; making it a library, tool or other while Deployments are on is refused, so turn Deployments off first. Give description or homepage as null or “” to follow the repository’s again, and production_url or docs_url as null or “” to clear it. links replaces its other links: at most 10, each a label of up to 40 characters and an http or https address (https:// is added when you leave the scheme out). Needs the Maintain role or higher on its repository.
Only the fields given change. kind and runs take auto to go back to detection. Setting runs makes the project an app unless it is docs. Making it a library, tool or other while Deployments are on is refused with 409 conflict: turn them off first. description and homepage given as null or "" follow the repository’s again; production_url and docs_url given as null or "" are cleared. links replaces the project’s other links: at most 10, each with a label of up to 40 characters and an http or https url (https:// is added when you leave the scheme out); anything else is refused with 422 invalid. Needs the Maintain role or higher on the project’s repository. Recorded in the audit log. See Settings.
- Authentication: Required. Send an access token as
Authorization: Bearer. - MCP tool:
workspacewithactionupdate_project, and the same inputs - Scope: An access token needs
repo:write.
Path parameters
Section titled “Path parameters”| Name | Type | Required | Description |
|---|---|---|---|
workspace |
string | Yes | The workspace’s slug, e.g. “flagon-io”. |
project |
string | Yes | The project’s slug, as in g1t.sh/{workspace}/{project}. |
Body parameters
Section titled “Body parameters”Send a JSON object. Names are snake_case, as in responses; the camelCase spelling is accepted too.
| Name | Type | Required | Description |
|---|---|---|---|
name |
string | No | Its name. |
description |
string or null | No | Its own description. null or “” follows its repository’s again. |
root_dir |
string | No | Where in the repository it lives, such as apps/web; “” for the whole repository. |
kind |
string | No | What it is. auto leaves it to detection. A library, tool or other runs nowhere. One of auto, app, library, tool, docs, other. |
runs |
string | No | Where it runs: g1t when g1t deploys it, elsewhere when it is deployed by other means. auto leaves it to Deployments. One of auto, g1t, elsewhere. |
production_url |
string or null | No | Production’s address when it runs elsewhere. null or “” clears it. |
homepage |
string or null | No | Its homepage. null or “” follows its repository’s website again. |
docs_url |
string or null | No | Where its documentation is read. null or “” clears it. |
links |
array of objects | No | Its other links, replacing the ones it has. [] removes them all. |
links[].label |
string | Yes | |
links[].url |
string | Yes | An http or https address; https:// is added when you leave the scheme out. |
Example request
Section titled “Example request”curl -X PATCH https://api.g1t.sh/workspaces/flagon-io/projects/g1t \ -H "Authorization: Bearer $G1T_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "kind": "app", "runs": "elsewhere", "production_url": "https://g1t.sh", "docs_url": "https://docs.g1t.sh", "links": [ { "label": "Status", "url": "https://status.g1t.sh" } ] }'Example response
Section titled “Example response”A successful request answers 200 with:
{ "id": "prj_01kkp3m8w2f6t9qh4c7d1r5n0x", "workspace": "flagon-io", "slug": "g1t", "name": "g1t", "description": "Git hosting where people and agents work together.", "description_inherited": true, "url": "https://g1t.sh/flagon-io/g1t", "repository": "flagon-io/g1t", "root_dir": "", "default_branch": "main", "private": false, "archived": false, "primary": true, "kind": "app", "kind_reason": { "by": "set", "detail": "Set to an app that runs elsewhere." }, "runs": "elsewhere", "production_url": "https://g1t.sh", "setting": { "kind": "app", "runs": "elsewhere" }, "detected": { "kind": "app", "reason": { "by": "files", "detail": "wrangler.jsonc at its root makes it an app." } }, "ecosystem": null, "links": { "homepage": "https://g1t.sh", "homepage_inherited": true, "docs": "https://docs.g1t.sh", "custom": [ { "label": "Status", "url": "https://status.g1t.sh" } ] }, "created_at": "2026-09-01T10:00:00.000Z", "updated_at": "2026-10-07T11:20:00.000Z", "pushed_at": "2026-10-07T10:00:00.000Z"}Errors
Section titled “Errors”A failed request answers with one of these statuses and a body like {"error": {"code": "not_found", "message": "Repository not found."}}. See errors.
| Status | Code | When |
|---|---|---|
| 401 | unauthenticated |
A token is required, or the one sent is not valid. |
| 403 | forbidden |
The token is valid but not allowed to do this, such as a member-only change or an agent token outside its repository. |
| 404 | not_found |
It does not exist, or you cannot see it. |
| 409 | conflict |
The request conflicts with the current state. |
| 422 | invalid |
The input is not valid. message says which field and why. |