Skip to content

Update a template

PUT
/orgs/{org}/templates/{id}
curl --request PUT \
--url https://api.sloose.com/orgs/org_9f3c/templates/b3f1c8a2 \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{ "name": "example", "description": "example", "visibility": "private", "config": { "additionalProperty": "example" }, "libraryVersions": "example", "connectorId": "example", "expectedUpdatedAt": "example", "registryVersion": 1 }'

A template shared with the org may be saved by any builder or above; a private one only by its creator or an admin. Send expectedUpdatedAt to make the write conditional: if somebody else saved in the meantime you get a 409 with their version of the template, so a client can show the difference rather than quietly overwriting a colleague’s work.

A changed config is the template’s next version, recorded in its history (GET /{id}/versions) in the same write; a save that changes only the name, or sends the configuration unchanged, makes none. A template a configuration repo manages (managedBy: sdk) takes no change here but its visibility: 409 TEMPLATE_MANAGED, naming the repo file, because the next push would overwrite it.

org
required

The org id the session was issued for. A token for one org can never read another.

string
Example
org_9f3c

The org id the session was issued for. A token for one org can never read another.

id
required

The template id.

string
Example
b3f1c8a2

The template id.

Media typeapplication/json
object
name
string
>= 1 characters <= 200 characters
description
string | null
<= 2000 characters
visibility

private is the creator’s alone; org is visible to everyone in the org.

string
Allowed values: private org
config

The template configuration. Any schema version is accepted: it is migrated to the current one before it is stored, so an older client can still save.

object
key
additional properties
libraryVersions

Helper library versions this template was built against: namespace → semver.

object | null
connectorId

The connection the template is built for, which it records and an import started from it pre-selects — one this bearer may use, or 404 CONNECTION_NOT_FOUND. Optional: a template may name no connection, and then whoever starts an import from it picks one (design §14.8). On update, naming one records it; leaving it out keeps the template’s.

string | null
expectedUpdatedAt

The updatedAt this client last read. Present: the write is refused with 409 if somebody else saved first. Absent: last writer wins.

string | null
registryVersion

The registryVersion the recipe was built against: the configuration’s registry.version as you loaded it (GET …/config/resolved). Read only when this request writes a recipe to the template — a create; an update carrying config; an import’s new, and its update when the recipe changed — and then stored as the template’s registryVersion, so that a change to the configuration made since can be told. Omitted or null there, the template is stamped with none (null): nothing on the server knows which version your recipe saw, and the version current when the save arrives would claim it had seen changes it had not. A version the org has not reached is refused there (400, code: BAD_REGISTRY_VERSION, with the current registryVersion). A request that writes no recipe to a template — a rename, detach, take-latest, choose, drop, an update of an unchanged recipe — ignores it and keeps the stamp the template has.

integer | null

Saved.

Media typeapplication/json
object
template
required
object
id
required
string
orgId
required
string
connectorId
required

The connection it was built for, when it names one: a template saved from an import records that import’s, and an import started from it pre-selects that one. Null on a template that names none — pushed from a configuration repository, or written by an agent without one — which is picked for on Target, among the connections of its kind.

string | null
name
required
string
description
required
string | null
createdByUserId
required
string
visibility
required
string
Allowed values: private org
schemaVersion
required
number
enabledModules
required
Array<string>
libraryVersions
required
object | null
registryVersion
required

The configuration version the recipe was built against, as its save REPORTED it (#616): an agent’s save over MCP stamps the version it checked the recipe against, and a repository’s push the version it wrote (none when another write landed while it wrote the configuration, which it checks before its templates; one landing while the templates are saved is outside that check, and the stamp stays, #650); any other save, the registryVersion it sent — a label the server stores for any version the org has reached, not one it checked. null when the save said none.

number | null
sourceRef
required

bundle:<file> when pushed from a config repo; null when built by a person.

string | null
kind
required

The kind of connection this template imports into — zoho_crm. Null on a template saved before kinds were recorded, which is read as Zoho CRM, the only kind there was.

string | null
version
required

Which version of the template this is. “Update the template” writes the next one; an import that copied an earlier one is told the template has moved on.

integer
managedBy
required

sdk when a config repo owns the template: changes arrive by the next push, and updates from an import are refused. Null when people own it.

string | null
Allowed values: sdk
lastUsedAt
required

When a run last started from it — a run authorised for an import made from it, or naming it with no import, a dry run included. Null for one no run has started from. Runs are purged, so this is kept, not worked out; it moves no version.

string | null
createdAt
required
string
updatedAt
required
string
config
required

Migrated to the current schema version on read. Null when it could not be migrated.

object | null
migrated
required

Migration steps applied on read. Non-empty means the stored row is from an older build.

Array<string>
unreadable
required
string | null
Example
{
"template": {
"visibility": "private",
"managedBy": "sdk"
}
}

The request — its body or its query — did not match the schema (issues carries the Zod issue list), or it writes a recipe and its registryVersion names a version this org’s configuration has not reached (code: BAD_REGISTRY_VERSION, with the current registryVersion).

Media typeapplication/json

The error envelope every non-2xx answer uses.

object
error
required

Human-readable explanation.

string
code

Machine-readable reason. Absent on a few legacy 400s.

string
key
additional properties
Examplegenerated
{
"error": "example",
"code": "example"
}

No bearer, or one that is expired, revoked or no longer resolves to a member.

Media typeapplication/json

The error envelope every non-2xx answer uses.

object
error
required

Human-readable explanation.

string
code

Machine-readable reason. Absent on a few legacy 400s.

string
key
additional properties
Examplegenerated
{
"error": "example",
"code": "example"
}

The role is too low — a template shared with the org is changed by any builder or above, a private one only by its creator or an admin (code: NOT_TEMPLATE_OWNER) — or the plan cannot share templates (code: FEATURE_SHARED_TEMPLATES).

Media typeapplication/json

The error envelope every non-2xx answer uses.

object
error
required

Human-readable explanation.

string
code

Machine-readable reason. Absent on a few legacy 400s.

string
key
additional properties
Examplegenerated
{
"error": "example",
"code": "example"
}

No such template, or it is not visible to this session; or the connectorId names no connection this person — or token — may use (code: CONNECTION_NOT_FOUND).

Media typeapplication/json

The error envelope every non-2xx answer uses.

object
error
required

Human-readable explanation.

string
code

Machine-readable reason. Absent on a few legacy 400s.

string
key
additional properties
Examplegenerated
{
"error": "example",
"code": "example"
}

Somebody else saved first (code: TEMPLATE_CONFLICT) — the current server-side template is included so you can merge — or a configuration repo manages the template (code: TEMPLATE_MANAGED).

Media typeapplication/json
Any of:
object
error
required
string
code
required
string
Allowed values: TEMPLATE_CONFLICT
template
required

The version that is on the server now.

object
id
required
string
orgId
required
string
connectorId
required

The connection it was built for, when it names one: a template saved from an import records that import’s, and an import started from it pre-selects that one. Null on a template that names none — pushed from a configuration repository, or written by an agent without one — which is picked for on Target, among the connections of its kind.

string | null
name
required
string
description
required
string | null
createdByUserId
required
string
visibility
required
string
Allowed values: private org
schemaVersion
required
number
enabledModules
required
Array<string>
libraryVersions
required
object | null
registryVersion
required

The configuration version the recipe was built against, as its save REPORTED it (#616): an agent’s save over MCP stamps the version it checked the recipe against, and a repository’s push the version it wrote (none when another write landed while it wrote the configuration, which it checks before its templates; one landing while the templates are saved is outside that check, and the stamp stays, #650); any other save, the registryVersion it sent — a label the server stores for any version the org has reached, not one it checked. null when the save said none.

number | null
sourceRef
required

bundle:<file> when pushed from a config repo; null when built by a person.

string | null
kind
required

The kind of connection this template imports into — zoho_crm. Null on a template saved before kinds were recorded, which is read as Zoho CRM, the only kind there was.

string | null
version
required

Which version of the template this is. “Update the template” writes the next one; an import that copied an earlier one is told the template has moved on.

integer
managedBy
required

sdk when a config repo owns the template: changes arrive by the next push, and updates from an import are refused. Null when people own it.

string | null
Allowed values: sdk
lastUsedAt
required

When a run last started from it — a run authorised for an import made from it, or naming it with no import, a dry run included. Null for one no run has started from. Runs are purged, so this is kept, not worked out; it moves no version.

string | null
createdAt
required
string
updatedAt
required
string
config
required

Migrated to the current schema version on read. Null when it could not be migrated.

object | null
migrated
required

Migration steps applied on read. Non-empty means the stored row is from an older build.

Array<string>
unreadable
required
string | null
Example
{
"code": "TEMPLATE_CONFLICT",
"template": {
"visibility": "private",
"managedBy": "sdk"
}
}

The configuration is not valid for the current schema version.

Media typeapplication/json
object
error
required
string
code
required
string
Allowed values: INVALID_TEMPLATE
issues
required
Array
key
additional properties
Example
{
"code": "INVALID_TEMPLATE"
}

Report a problem with this page