POST/sites/:siteSlug/deployments
Upload a new deployment by sending a ZIP archive as multipart/form-data. All files in the ZIP are extracted and stored on Cloudflare R2. The deployment starts in draft status until published. Requires the deployments:write scope.
Request body
Send multipart/form-data with a single field file containing the ZIP archive (.zip, application/zip). The ZIP is unpacked server-side — all valid static files are uploaded to edge storage. Skipped file types (e.g. system files) are silently ignored.
Limits
Max 1 000 files per deployment. Max 500 MB unzipped total. Exceeding these returns a 422 error.
Response
Returns 201 Created with data.deploymentId, data.previewUrl (https://{deploymentId}-{siteSlug}.zxapi.net), and data.liveUrl. The deployment is in draft — call /publish to go live.
Example response
{
"data": {
"deploymentId": "v-2vka1lafuv0ebvru9m3",
"previewUrl": "https://v-2vka1lafuv0ebvru9m3-my-site.zxapi.net",
"liveUrl": "https://my-site.zxapi.net"
}
}Code examples
curl "https://www.zyberspace.com/api/v1/{teamSlug}/sites/my-site/deployments" \
-H "Authorization: Bearer zxk_live_YOUR_API_KEY" \
-X POST \
-F "file=@dist.zip"const form = new FormData();
form.append("file", zipBlob, "deploy.zip");
const res = await fetch(`https://www.zyberspace.com/api/v1/{teamSlug}/sites/my-site/deployments`, {
method: "POST",
headers: { Authorization: "Bearer zxk_live_YOUR_API_KEY" },
body: form,
});
const { data } = await res.json(); // 201
console.log(data.previewUrl); // preview before publishing
console.log(data.deploymentId); // use this for /publishBase URL: https://www.zyberspace.com