Creates a project seeded from a PUBLISHED EXAMPLE — either a starter-kit…
Creates a project seeded from a PUBLISHED EXAMPLE — either a starter-kit template from the ONE embedded gallery catalog, or any live project on the…
POST /v1/projects/fork
| Address | https://api.hanzo.ai/v1/projects/fork |
| Method | POST |
| Operation | post_projects_fork |
| Auth | Authorization: Bearer $HANZO_API_KEY |
Creates a project seeded from a PUBLISHED EXAMPLE — either a starter-kit template from the ONE embedded gallery catalog, or any live project on the platform (an example a seeded creator published, or another org's app serving at <slug>.hanzo.app). Answers 201 with the new project.
slug names the PARENT to fork and is required. Templates resolve first, and
the caller org's own private templates ahead of the public gallery, so a
curated template slug keeps meaning the same thing even if someone later
publishes a live project under it; variant picks that template's
format/page/theme. If no template matches, the slug resolves to the UNIQUE
live project that owns it across all orgs — the same resolution the site edge
uses to serve <slug>.hanzo.app, so what you can browse is what you can fork.
name and target override the derived project name and slug; everything
else is inherited from the parent. A live parent contributes its REPO, so the
child builds from the same source — the parent's deployed bytes are never
copied, because releases are per-tenant by design and the fork publishes its
own. The parent it actually resolved is stamped on the child as forkedFrom,
so attribution is a fact recorded at fork time rather than a claim
reconstructed later.
It funnels through the SAME create path POST /v1/projects uses, so slug validation, org scoping, ID minting and the 409 on a slug the caller's own org already uses are identical.
Scope: a validated principal is required (403 without one) and the child is created in THAT principal's org.
Request
4 fields, body application/json (required).
| Field | In | Type | Required | Description |
|---|---|---|---|---|
name | body | string | — | target project name (optional; defaults to the parent's title) |
slug | body | string | — | parent slug to fork — catalog template or published project (required) |
target | body | string | — | Target overrides the derived project slug (optional; defaults to the parent slug). |
variant | body | string | — | Variant picks a template's format/page/theme (optional; defaults to the template's first shape). |
Response
| Status | Body | Meaning |
|---|---|---|
201 | projectsProject | created |
201 body — 30 fields.
| Field | In | Type | Always | Description |
|---|---|---|---|---|
analytics | body | boolean | — | Analytics is whether the web-analytics beacon is injected into this site's pages. |
bucket | body | string | — | Bucket is the object-store bucket the site's files are served out of. |
cacheControl | body | string | — | CacheControl is the Cache-Control policy the edge serves this site's HTML under — how long a reader may hold a stale page before asking again. |
createdAt | body | integer | — | CreatedAt is when the project was created, as Unix seconds. |
currentDeploymentId | body | string | — | CurrentDeploymentID names the deployment currently serving, so a caller can ask what is live without scanning the history. |
description | body | string | — | Description is the one-line summary, which is copied onto forks of this project and shown on a gallery card. |
forkedFrom | body | string | — | ForkedFrom is the parent this project was forked from ("<org>/<slug>" of a published project, or a catalog template slug) — the attribution edge a gallery… |
framework | body | string | — | Framework is a BUILD HINT from a closed set, defaulting to static. |
hidden | body | boolean | — | Hidden is PLATFORM MODERATION, and it is a different axis from visibility: it pulls a public project out of the catalogue without editing the publisher's own… |
hiddenReason | body | string | — | HiddenReason is why moderation hid it. |
id | body | string | — | ID is the project's internal identifier. |
key | body | string | — | Key is the project's publishable ingest key, minted at create. |
lastPurgeAt | body | integer | — | LastPurgeAt is when the edge cache was last cleared, as Unix seconds, so a console can say how fresh what readers see actually is. |
license | body | string | — | License is the terms that upstream work carries. |
liveUrl | body | string | — | LiveURL is where the site answers today. |
name | body | string | — | Name is the project's display name, free text a person chose. |
org | body | string | — | Org is the organisation that owns the project, and therefore who pays for it and who may change it. |
repo | body | projectsRepo | — | |
repo.branch | body | string | — | Branch is the ref a push has to touch for this project to rebuild. |
repo.provider | body | string | — | Provider is the forge the URL was recognised as — it decides which webhook and which credential reach the repository, and is DERIVED from the URL rather than… |
repo.url | body | string | — | URL is the clone address of the repository this project builds from. |
slug | body | string | — | Slug is the identifier that MATTERS: the handle every later call addresses, the S3 key segment the site's objects live under, and the label of the public host… |
space | body | string | — | Space is the project's Base data space, which is where a deployed site's form, forum and data submissions land. |
starred | body | boolean | — | Starred is THIS CALLER's star, not a property of the project — two people in the same org see different values for the same row, which is the whole point of… |
status | body | string | — | Status is where the project stands — whether a build has ever succeeded and whether anything is serving right now. |
tags | body | object | — | Tags is the site's browser tag config: platform slug → non-secret pixel id (GA measurement, Meta pixel, …) — what track.js injects and the server CAPI reads,… |
tags.* | body | string | — | |
updatedAt | body | integer | — | UpdatedAt is when the project's own record last changed, as Unix seconds. |
upstream | body | string | — | Upstream credits the third-party work this project was published from — a free-text line, because the honest answer is a name and a title that no enum could… |
visibility | body | string | — | Visibility is "public" or "private", and Hidden reports platform moderation. |
Failure carries the platform error shape — see Errors.
Examples
hanzo projects forkimport { Configuration, ProjectsApi } from 'hanzoai';
const api = new ProjectsApi(new Configuration({ accessToken: process.env.HANZO_API_KEY }));
const { data } = await api.postProjectsFork({ name: "<name>", slug: "<slug>" });from hanzoai.cloud import ApiClient, Configuration
from hanzoai.cloud.api import ProjectsApi
client = ApiClient(Configuration(access_token=os.environ["HANZO_API_KEY"]))
result = ProjectsApi(client).post_projects_fork(name="<name>", slug="<slug>")cfg := cloud.NewConfiguration()
cfg.AddDefaultHeader("Authorization", "Bearer "+os.Getenv("HANZO_API_KEY"))
client := cloud.NewAPIClient(cfg)
resp, _, err := client.ProjectsAPI.PostProjectsFork(context.Background()).Execute()
if err != nil {
return err
}use hanzo_cloud::apis::{configuration::Configuration, projects_api};
let mut cfg = Configuration::new();
cfg.bearer_access_token = std::env::var("HANZO_API_KEY").ok();
let result = projects_api::post_projects_fork(&cfg, Default::default()).await?;import ai.hanzo.cloud.ApiClient;
import ai.hanzo.cloud.api.ProjectsApi;
ApiClient client = new ApiClient();
client.setRequestInterceptor(b -> b.header("Authorization", "Bearer " + System.getenv("HANZO_API_KEY")));
var result = new ProjectsApi(client).postProjectsFork();curl -X POST https://api.hanzo.ai/v1/projects/fork \
-H "Authorization: Bearer $HANZO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "<name>",
"slug": "<slug>"
}'The door reaches projects through the projects tool, which names its 48 operations with its own verbs — this one among them, under a name only the door declares. describe explains any of them:
curl -X POST https://api.hanzo.ai/v1/mcp \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "describe",
"arguments": {
"op": "list_projects"
}
}
}'How is this guide?