Deploy projects
Takes a built site live at `https://<slug>.hanzo.app` in one call.
POST /v1/projects/{slug}/deploy
| Address | https://api.hanzo.ai/v1/projects/{slug}/deploy |
| Method | POST |
| Operation | post_projects_by_slug_deploy |
| Auth | Authorization: Bearer $HANZO_API_KEY |
Takes a built site live at https://<slug>.hanzo.app in one call. The body is the site itself — a zip or tar.gz holding index.html at its root (or a single wrapper directory that does), sent raw or as a multipart file part. It is unpacked to the site's own storage prefix and served immediately, answering the finished deployment.
It is bounded by the edge body limit (16 MiB by default), and that bound is the whole reason the other path exists: an oversized POST is refused by the server BEFORE any handler runs and surfaces as an opaque 400 Error when parsing request that reads like a malformed payload rather than a size cap. A site too large for one archive opens a deployment with POST /v1/project/{slug}/deployments instead and writes its files straight to storage against the scoped grant that answers with — no body limit, and no bytes through this API at all.
Billing is fail-closed and fails FIRST: the hosting gate runs before anything is parsed or uploaded, so an unfunded org is 402 and an unreachable commerce is 503 with nothing written. The debit lands only on success — a failed upload is never billed and never flips the live site — and a redeploy answers the SAME URL, because slug and apex are stable.
Scope: a validated principal is required (401 without one) and the site is resolved within that principal's org, so another tenant's slug is a 404. Object storage must be configured (503); an archive that does not walk is a 400 and one over the size cap is a 413.
Request
2 fields, body application/octet-stream.
| Field | In | Type | Required | Description |
|---|---|---|---|---|
slug | path | string | yes | |
(body) | body | string (binary) | yes |
Response
| Status | Body | Meaning |
|---|---|---|
2XX | projectsDeployment | Success |
2XX body — 21 fields.
| Field | In | Type | Always | Description |
|---|---|---|---|---|
bucket | body | string | — | |
bytes | body | integer | — | |
commit | body | string | — | |
createdAt | body | integer | — | |
files | body | integer | — | |
id | body | string | — | |
liveUrl | body | string | — | |
message | body | string | — | |
prefix | body | string | — | |
projectId | body | string | — | |
source | body | string | — | |
status | body | string | — | |
updatedAt | body | integer | — | |
upload | body | projectsUploadGrant | — | |
upload.expiresAt | body | integer | — | |
upload.fields | body | object | — | |
upload.fields.* | body | string | — | |
upload.maxBytes | body | integer | — | |
upload.prefix | body | string | — | |
upload.url | body | string | — | |
version | body | integer | — |
Failure carries the platform error shape — see Errors.
Examples
hanzo projects deploy <slug>import { Configuration, ProjectApi } from 'hanzoai';
const api = new ProjectApi(new Configuration({ accessToken: process.env.HANZO_API_KEY }));
const { data } = await api.postProjectsBySlugDeploy({ slug: 'slug' });from hanzoai.cloud import ApiClient, Configuration
from hanzoai.cloud.api import ProjectApi
client = ApiClient(Configuration(access_token=os.environ["HANZO_API_KEY"]))
result = ProjectApi(client).post_projects_by_slug_deploy(slug='slug')cfg := hanzoai.NewConfiguration()
cfg.AddDefaultHeader("Authorization", "Bearer "+os.Getenv("HANZO_API_KEY"))
client := hanzoai.NewAPIClient(cfg)
resp, _, err := client.ProjectAPI.PostProjectsBySlugDeploy(context.Background()).Execute()
if err != nil {
return err
}use hanzo_client::apis::{configuration::Configuration, project_api};
let mut cfg = Configuration::new();
cfg.bearer_access_token = std::env::var("HANZO_API_KEY").ok();
let result = project_api::post_projects_by_slug_deploy(&cfg, Default::default()).await?;import ai.hanzo.cloud.ApiClient;
import ai.hanzo.cloud.api.ProjectApi;
ApiClient client = new ApiClient();
client.setBearerToken(System.getenv("HANZO_API_KEY"));
var result = new ProjectApi(client).postProjectsBySlugDeploy();curl -X POST https://api.hanzo.ai/v1/projects/<slug>/deploy \
-H "Authorization: Bearer $HANZO_API_KEY"MCP reaches project through the projects tool, which names its 48 operations with its own verbs — this one among them, under a name only MCP 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?