# Edit a community template draft

`PATCH https://api.instacloud.com/orgs/{orgId}/templates/{code}`

**Token scope:** `account` · `org` — read-only tokens refused (not a GET).

## Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgId` | path | `string` | yes |  |
| `code` | path | `string` | yes |  |

## Request body (application/json)

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `code` | `string` | no | Rename. Only before the first publish. |
| `name` | `string` | no |  |
| `tagline` | `string \| null` | no |  |
| `category` | `string \| null` | no |  |
| `readme` | `string \| null` | no |  |
| `logoUrl` | `string \| null` | no | An https:// image link. The link and its percent-encoded form are each at most 2048 characters. null clears it. |
| `variables` | `object[]` | no | Only the variables that changed, at most 600, the cap a project apply has. A name deleted in this PATCH can be added again only in a later PATCH. One invalid entry answers 400 and nothing is saved. |
| `variables.service` | `string` | yes |  |
| `variables.name` | `string` | yes | The generator's name for the variable: the view's originalName when it is renamed, else its name. On an add, the new variable's name. |
| `variables.choice` | `object \| null \| null` | no | null clears the choice, back to what the generator chose. Omitted leaves the choice as it is. |
| `variables.newName` | `string \| null` | no | Renames the variable: ^[A-Z][A-Z0-9_]{0,63}$, and no other variable of the service may have that name. null clears the rename. Omitted leaves the name as it is. |
| `variables.add` | `true` | no | Adds a required variable called name to a web service or worker: ^[A-Z][A-Z0-9_]{0,63}$, a name no variable of the service has or shows, at most 200 variables per service and 1000 per template. The entry carries nothing else. A choice for it rides in its own entry, and adds run before every other entry. |
| `variables.delete` | `true` | no | Deletes a variable the author added, with its choice and rename. One from the project answers 400: remove it with choice removed. The entry carries nothing else, and deletes run after every other entry. |
| `services` | `object[]` | no | Only the services that changed, at most 100. An add or a delete entry carries nothing else. Service adds run first and deletes run after every other entry. A template holds at most 50 services. A name deleted in this PATCH can be added again only in a later PATCH. One invalid entry answers 400 and nothing is saved. |
| `services.name` | `string` | yes | The service. On an add, the new service name: lower-kebab, at most 39 characters, a name no service of the template has. |
| `services.removed` | `boolean` | no | true leaves the service out of the published template, false restores it. Omitted leaves it as it is. A service the author added is deleted instead, and true on one answers 400. |
| `services.settings` | `object \| null \| null` | no | Only the fields that changed: each replaces that field. null clears every setting of the service. Postgres takes only pgVersion and storage only public. Redis, MySQL and MongoDB answer 400, and so does a field the service type does not take. |
| `services.add` | `object` | no | A service the author adds to a template: a compute service from an image, web with a port and a worker without one, or a managed database or bucket by type. |
| `services.delete` | `true` | no | Deletes a service the author added, with every setting, choice, rename and added variable kept under its name. One from the project answers 400: remove it with removed true. The entry carries nothing else, and deletes run after every other entry. |
| `expectedUpdatedAt` | `string` | yes | The draft's updatedAt as the client rendered it. A different current value answers 409 template_draft_changed. |

## Response 200

Default Response

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `template` | `object` | yes |  |
| `template.id` | `string` | yes | The draft's stable id. A rename of its code keeps it, and a new draft gets a new one, even under a code a deleted draft had. Routes and editor links address a draft by its code. |
| `template.code` | `string` | yes |  |
| `template.orgId` | `string` | yes |  |
| `template.sourceProjectId` | `string \| null` | yes |  |
| `template.blank` | `boolean` | yes | Created with POST /orgs/{orgId}/templates, with no project behind it: every service is one the author added, and Regenerate From Project answers 400. A generated draft whose project was deleted is not blank. |
| `template.status` | `"draft" \| "published" \| "unpublished"` | yes |  |
| `template.publishedVersion` | `string \| null` | yes |  |
| `template.hasUnpublishedChanges` | `boolean` | yes |  |
| `template.name` | `string` | yes |  |
| `template.tagline` | `string \| null` | yes |  |
| `template.category` | `string \| null` | yes |  |
| `template.readme` | `string \| null` | yes |  |
| `template.defaultReadme` | `string` | yes | A README skeleton built from the draft as it is now: service names and required variable names only, never a value. The console offers it behind a button; it is not stored. |
| `template.logoUrl` | `string \| null` | yes |  |
| `template.services` | `object[]` | yes |  |
| `template.services.name` | `string` | yes |  |
| `template.services.type` | `string` | yes | web with a port, worker without one, or the managed type (postgres, redis, mysql, mongodb or storage). It and the fields below are the values after the author's settings. |
| `template.services.image` | `string \| null` | yes |  |
| `template.services.port` | `integer \| null` | yes |  |
| `template.services.healthcheck` | `string \| null` | yes |  |
| `template.services.volume` | `boolean` | yes |  |
| `template.services.mountPath` | `string \| null` | yes | null with volume true: the volume mounts at the default /data. null with volume false: no volume. |
| `template.services.command` | `string \| null` | yes |  |
| `template.services.alwaysOn` | `boolean \| null` | yes |  |
| `template.services.public` | `boolean` | no | Storage only, always present on a bucket: anonymous public-read, after the author's setting. |
| `template.services.pgVersion` | `integer` | no | Postgres only: the major a deploy creates the database on, after the author's setting. Absent when the project's database recorded none. |
| `template.services.added` | `boolean` | no | Present, and true, only on a service the author added: a PATCH deletes it for good. One from the project is removed instead. |
| `template.services.removed` | `boolean` | yes | The author left this service out of the template. It stays listed so it can be restored. |
| `template.services.variables` | `object[]` | yes | Sorted by the generator's name (originalName when renamed). Empty for a managed database. A removed service lists what restoring it brings back. |
| `template.services.variables.name` | `string` | yes |  |
| `template.services.variables.kind` | `"required" \| "optional" \| "default" \| "reference" \| "generated" \| "fixed" \| "removed"` | yes |  |
| `template.services.variables.value` | `string` | no | default: the default text. reference: the token. fixed: the literal or the address reference. |
| `template.services.variables.description` | `string` | no | What whoever deploys reads. Omitted while it is the default sentence, which the console shows as an empty box. |
| `template.services.variables.brokenReference` | `string` | no | The token this variable referenced before its service was removed from the template or left the project. The variable is then required. |
| `template.services.variables.originalName` | `string` | no | Present only when the author renamed the variable: the generator's name, which a PATCH variables entry sends as name. name is then the new one. |
| `template.services.variables.added` | `boolean` | no | Present, and true, only on a variable the author added: a PATCH deletes it for good. One from the project is removed with choice removed instead. |
| `template.referenceOptions` | `object[]` | yes | What a variable may reference in the template as it is now. A removed service offers nothing. |
| `template.referenceOptions.token` | `string` | yes | Exactly what a reference choice sends and the manifest stores. |
| `template.referenceOptions.service` | `string` | yes |  |
| `template.referenceOptions.key` | `string` | yes | A credential key of a managed database or a storage bucket, or url or host of a web service. |
| `template.editableFields` | `object` | yes | Per service type, the TemplateServiceSettings keys a template service of that type takes. A PATCH answers 400 for any other. |
| `template.editableFields.web` | `"image" \| "port" \| "healthcheck" \| "command" \| "mountPath" \| "alwaysOn"[]` | yes |  |
| `template.editableFields.worker` | `"image" \| "port" \| "healthcheck" \| "command" \| "mountPath" \| "alwaysOn"[]` | yes |  |
| `template.editableFields.postgres` | `"pgVersion"[]` | yes |  |
| `template.editableFields.redis` | `string[]` | yes |  |
| `template.editableFields.mysql` | `string[]` | yes |  |
| `template.editableFields.mongodb` | `string[]` | yes |  |
| `template.editableFields.storage` | `"public"[]` | yes |  |
| `template.referenceKeys` | `object` | yes | Per managed service type, the credential keys a variable may reference on a service of that type, one the author has not applied yet included (secretNames.ts CANONICAL_KEYS). A web service's url and host are not listed. |
| `template.referenceKeys.postgres` | `string[]` | yes |  |
| `template.referenceKeys.redis` | `string[]` | yes |  |
| `template.referenceKeys.mysql` | `string[]` | yes |  |
| `template.referenceKeys.mongodb` | `string[]` | yes |  |
| `template.referenceKeys.storage` | `string[]` | yes |  |
| `template.publishRequirements` | `object[]` | yes | Always seven, in this order: has_service, no_blocked, no_conflicts, has_tagline, has_category, has_readme, required_descriptions. |
| `template.publishRequirements.code` | `"has_service" \| "no_blocked" \| "no_conflicts" \| "has_tagline" \| "has_category" \| "has_readme" \| "required_descriptions"` | yes |  |
| `template.publishRequirements.ok` | `boolean` | yes |  |
| `template.publishRequirements.items` | `string[]` | yes | no_blocked: each blocked reason. no_conflicts: one sentence with its fix for each name the author added that the project now has too, services first. required_descriptions: each <service>.<VAR> still without a description. Otherwise empty. |
| `template.report` | `object` | yes | What generation skipped, what blocks publishing (each with a fix), and notices. |
| `template.report.skipped` | `object[]` | yes |  |
| `template.report.skipped.service` | `string` | no |  |
| `template.report.skipped.variable` | `string` | no |  |
| `template.report.skipped.reason` | `string` | yes |  |
| `template.report.skipped.fix` | `string` | no |  |
| `template.report.blocked` | `object[]` | yes |  |
| `template.report.blocked.service` | `string` | no |  |
| `template.report.blocked.variable` | `string` | no |  |
| `template.report.blocked.reason` | `string` | yes |  |
| `template.report.blocked.fix` | `string` | no |  |
| `template.report.notices` | `object[]` | yes |  |
| `template.report.notices.service` | `string` | no |  |
| `template.report.notices.variable` | `string` | no |  |
| `template.report.notices.reason` | `string` | yes |  |
| `template.report.notices.fix` | `string` | no |  |
| `template.updatedAt` | `string` | yes |  |
| `template.takenDown` | `boolean` | yes | Staff took this template down. It cannot be republished. |
| `template.deployCount` | `integer` | yes | Succeeded deployments of this template. |
| `template.totalProjects` | `integer` | yes | Distinct projects that deployed this template since its first publish, any outcome: the number the gallery card shows (the catalog's totalProjects). |

## Response 400

Default Response

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `error` | `string` | yes |  |

## Response 404

Default Response

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `error` | `string` | yes |  |

## Response 409

code template_draft_changed: the draft changed since the client read it (expectedUpdatedAt), review it and save again. Without a code: the new code is taken, or the template was already published and keeps its code.

| 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 |

## Response 429

This user saved too many times in the last minute. Retry later.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `error` | `string` | yes |  |
