Deployments
Publish your project to production and track the rollout.
Deployments build your project and publish it to its production URL. Deploying is asynchronous — start the deploy, then poll for status. All endpoints require the api-key header.
#Deploy to Production
/api/v1/vcaas/projects/:projectId/deployments/deployUses creditsBuild and deploy your project to a production URL. This endpoint is asynchronous — it returns immediately with status "deploying" and the deployment continues in the background for 2 to 5 minutes.
Poll GET /projects/:projectId/deployments/status every 10–15 seconds until status is "success", then read the public URL from GET /projects/:projectId → productionProjectUrl. If the server is not active, it auto-starts (charging extra START_SERVER credits) and returns SERVER_NOT_READY; poll GET /projects/:projectId until agentServerStatus is "Active", then retry.
Path parameters
| Parameter | Type | Description |
|---|---|---|
projectId | string | The project ID |
Response fields
| Field | Type | Description |
|---|---|---|
data.projectId | string | The project ID |
data.status | string | Always "deploying" on success |
data.message | string | Instructions on how to poll for status |
Example request
curl -X POST -H "api-key: tlm_sk_your_key" \
https://api-accounts.totalum.app/api/v1/vcaas/projects/my-app/deployments/deploy{
"errors": null,
"data": {
"projectId": "my-app",
"status": "deploying",
"message": "Deployment started. It will take from 2 to 5 minutes. Fetch GET .../deployments/status every 10-15 seconds to track progress."
}
}{
"errors": {
"errorCode": "DEPLOYMENT_RUNNING",
"errorMessage": "A deployment is already in progress"
},
"data": null
}Error codes
| Code | HTTP | Meaning |
|---|---|---|
MISSING_PROJECT_ID | 400 | projectId is required |
PROJECT_NOT_FOUND | 404 | Project does not exist or you don't own it |
AGENT_RUNNING | 409 | Cannot deploy while agent is running |
DEPLOYMENT_RUNNING | 409 | A deployment is already in progress |
RECOVERY_RUNNING | 409 | A version recovery is in progress |
REBUILD_RUNNING | 409 | A rebuild is in progress — poll GET /projects/:projectId/rebuild/status until it is no longer "rebuilding", then retry |
GITHUB_PULL_RUNNING | 409 | A GitHub pull is rebuilding the project — poll GET /projects/:projectId/github/pull-status until it is no longer "pulling", then retry |
IMPORT_IN_PROGRESS | 409 | A project import is in progress — poll GET /projects/:projectId until importInProgress is null, then retry |
SERVER_NOT_READY | 409 | Server auto-starting, poll until Active then retry |
INSUFFICIENT_CREDITS | 402 | Not enough credits for deployment |
#Unpublish
/api/v1/vcaas/projects/:projectId/deployments/unpublishFreeTake the project fully offline. This removes, in one call:
- the published site at the production URL,
- the preview snapshot served while the project's server is asleep,
- every custom domain attached to the project.
The call is synchronous: when it answers "unpublished", the project is offline. If the site or the preview snapshot cannot be removed, the call fails. A custom domain that cannot be removed is only a warning: the call still succeeds, the domain is listed in data.customDomainsFailed and explained in data.warnings, and it serves nothing because the site behind it is gone. Calling unpublish again is safe and retries anything left over, because anything already removed counts as done. Unpublishing a project that was never published also succeeds.
To publish again, call POST /projects/:projectId/deployments/deploy. Custom domains are removed, not paused, so you have to add them again with PUT /projects/:projectId/domain. Your DNS records at your registrar are not touched.
This endpoint is free and works even when your credit balance is zero. It is refused while a deployment is running, because that deployment would publish the site again when it finished.
Path parameters
| Parameter | Type | Description |
|---|---|---|
projectId | string | The project ID |
Response fields
| Field | Type | Description |
|---|---|---|
data.projectId | string | The project ID |
data.status | string | Always "unpublished" on success |
data.customDomainsRemoved | string[] | The custom domains that were removed (empty when the project had none) |
data.customDomainsFailed | string[] | Custom domains that could not be removed — they serve nothing; unpublish again to retry them |
data.warnings | string[] | Non-fatal problems, such as a custom domain that could not be removed. Empty when everything went through |
data.message | string | What was removed and how to publish again |
Example request
curl -X POST -H "api-key: tlm_sk_your_key" \
https://api-accounts.totalum.app/api/v1/vcaas/projects/my-app/deployments/unpublish{
"errors": null,
"data": {
"projectId": "my-app",
"status": "unpublished",
"customDomainsRemoved": ["app.example.com"],
"customDomainsFailed": [],
"warnings": [],
"message": "The project is offline: its published site, preview snapshot and custom domains were removed. Deploy again to publish it; custom domains have to be added again."
}
}{
"errors": {
"errorCode": "DEPLOYMENT_RUNNING",
"errorMessage": "A deployment is in progress and would publish the site again when it finishes. Wait for GET /api/v1/vcaas/projects/my-app/deployments/status to leave \"deploying\", then retry."
},
"data": null
}Error codes
| Code | HTTP | Meaning |
|---|---|---|
MISSING_PROJECT_ID | 400 | projectId is required |
PROJECT_NOT_FOUND | 404 | Project does not exist or you don't own it |
DEPLOYMENT_RUNNING | 409 | A deployment is in progress — wait until GET /projects/:projectId/deployments/status is no longer "deploying", then retry |
UNPUBLISH_ERROR | 400 | The published site could not be removed — retry |
UNPUBLISH_PREVIEW_ERROR | 400 | The site was removed but the preview snapshot was not — retry to finish |
#Get Deployment Status
/api/v1/vcaas/projects/:projectId/deployments/statusFreeCheck the current deployment status. Poll until status is "success".
Path parameters
| Parameter | Type | Description |
|---|---|---|
projectId | string | The project ID |
Response fields
| Field | Type | Description |
|---|---|---|
data.status | string | null | "deploying" | "success" | "error" | null (if never deployed) |
data.createdAt | string | null | ISO 8601 deployment date |
data.versionId | string | undefined | Version that was deployed |
Example request
curl -H "api-key: tlm_sk_your_key" \
https://api-accounts.totalum.app/api/v1/vcaas/projects/my-app/deployments/status{
"errors": null,
"data": {
"status": "success",
"createdAt": "2026-03-11T11:00:00.000Z",
"versionId": "v_abc123"
}
}{
"errors": {
"errorCode": "PROJECT_NOT_FOUND",
"errorMessage": "Project does not exist or you don't own it"
},
"data": null
}Error codes
| Code | HTTP | Meaning |
|---|---|---|
MISSING_PROJECT_ID | 400 | projectId is required |
PROJECT_NOT_FOUND | 404 | Project does not exist or you don't own it |
