Upgrade template deployment
POSThttps://api.instacloud.com/projects/{projectId}/template-deployments/{deploymentId}/upgrade
Token scope: account · org · project — read-only tokens refused (not a GET).
Move a deployed template instance to the version the registry serves now (async — poll GET /template-deployments/:id). The SAME services are reused: image, port, start command, always-on, public access, the volume mount path and the variables are all rewritten from the new manifest, a service the new version adds is created, and a service it drops is left running. A volume the new version adds to an existing service is attached at this plan's size and mounted by the run's own deploy; an existing volume is never resized, because a manifest cannot declare a size. Public access on a STORAGE service is lineage-wide — it sets that bucket public on every branch that has a copy, not only this one, and the preview's row for the field says so. Send expectedVersion/expectedDigest from the preview so a republish between review and apply is refused rather than run.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
projectId | path | string | yes | |
deploymentId | path | string | yes |
Request body
application/json
| Field | Type | Required | Description |
|---|---|---|---|
variables | object | no | values for required variables the new version adds; existing values are recovered and need not be resent |
expectedVersion | string | no | the version the caller reviewed; a different one in the registry answers 409 template_version_changed |
expectedDigest | string | no | the to_digest from the preview; a different one answers 409 template_version_changed |
Responses
202
Default Response
| Field | Type | Required | Description |
|---|---|---|---|
deploymentId | string | no | |
deployment | object | no | One server-side template deployment run and its progress. |
deployment.id | string | no | |
deployment.status | "running" | "succeeded" | "failed" | "partial" | no | partial = some services came up healthy, others failed — created resources are kept either way |
deployment.step | "create_services" | "write_variables" | "deploy" | "health_check" | no | the pipeline step the run is currently on (or stopped at) |
deployment.templateCode | string | no | |
deployment.templateVersion | string | no | |
deployment.projectId | string | no | |
deployment.branchId | string | no | |
deployment.region | string | no | InstaCloud region slug every service of this deployment was created in. Deployments recorded before regions were recorded read as the platform default. |
deployment.services | object[] | no | |
deployment.services.name | string | no | the service's actual name on the branch, which is the manifest's name only for the first copy — a second deployment of the same template into the same branch names its services <name>-2 and leaves the first copy alone |
deployment.services.serviceId | string | no | |
deployment.services.url | string | no | |
deployment.services.state | "pending" | "created" | "deployed" | "healthy" | "failed" | no | |
deployment.services.skipped | boolean | no | an upgrade stepped over this service because the user had deleted it — the run never touched it, serviceId points at the deleted row, and state stays pending however the deployment ends. Not "still in progress" |
deployment.error | string | no | |
deployment.logsTail | string | no | container log tail captured when a service never became healthy |
deployment.rollbackTo | object | no | the version one step back, present only when this deployment was produced by an upgrade: what POST .../rollback would return the instance to. Absent on a first deploy, once the predecessor is gone, and on a deployment a ROLLBACK produced — that row's step back is the newer version it just left, which is offered as the update, not as a way back. Present is not a promise it will succeed — a version whose manifest is no longer recorded, or was republished with different content, still refuses at click time |
deployment.rollbackTo.version | string | yes | |
deployment.createdAt | string | no | |
status | "approval_required" | no | |
approvalId | string | no | |
action | string | no | |
actions | string[] | no | |
message | string | no | |
url | string | no | |
nextActions | object[] | no | |
nextActions.op | string | yes | Neutral logical action id, e.g. "service.add" — NOT an operationId or a CLI/MCP tool name; each client maps it to its own surface. |
nextActions.reason | string | yes | Natural-language, human/LLM-facing "why do this now". |
nextActions.args | object | no | Suggested, flat named arguments; "<placeholder>"s where a value is unknown. |
nextActions.gated | boolean | no | True if the action passes a governance gate. |
400
Default Response
| Field | Type | Required | Description |
|---|---|---|---|
error | string | yes | |
missing | object[] | no | |
missing.name | string | yes | |
missing.key | string | yes | |
missing.description | string | no |
403
Default Response
| Field | Type | Required | Description |
|---|---|---|---|
error | string | yes |
404
Default Response
| Field | Type | Required | Description |
|---|---|---|---|
error | string | yes |
409
code template_version_changed: republished since the review. code template_up_to_date: already running this content. code template_not_served: off the catalog. code template_no_services: the deployment owns nothing to upgrade. code template_superseded: this instance already moved off this deployment — the message names the one to act on instead
| Field | Type | Required | Description |
|---|---|---|---|
error | string | yes | |
code | string | no | stable machine-readable reason, e.g. private_lane_disabled, private_lane_unavailable_in_region, public_access_closed, credential_change_in_progress |