Update a template
const url = 'https://api.sloose.com/orgs/org_9f3c/templates/b3f1c8a2';const options = { method: 'PUT', headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'}, body: '{"name":"example","description":"example","visibility":"private","config":{"additionalProperty":"example"},"libraryVersions":"example","connectorId":"example","expectedUpdatedAt":"example","registryVersion":1}'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}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.
Authorizations
Section titled “Authorizations”Parameters
Section titled “Parameters”Path Parameters
Section titled “Path Parameters”The org id the session was issued for. A token for one org can never read another.
Example
org_9f3cThe org id the session was issued for. A token for one org can never read another.
The template id.
Example
b3f1c8a2The template id.
Request Bodyrequired
Section titled “Request Bodyrequired”object
private is the creator’s alone; org is visible to everyone in the org.
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
Helper library versions this template was built against: namespace → semver.
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.
The updatedAt this client last read. Present: the write is refused with 409 if somebody else saved first. Absent: last writer wins.
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.
Responses
Section titled “Responses”Saved.
object
object
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.
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.
bundle:<file> when pushed from a config repo; null when built by a person.
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.
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.
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.
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.
Migrated to the current schema version on read. Null when it could not be migrated.
Migration steps applied on read. Non-empty means the stored row is from an older build.
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).
The error envelope every non-2xx answer uses.
object
Human-readable explanation.
Machine-readable reason. Absent on a few legacy 400s.
Examplegenerated
{ "error": "example", "code": "example"}No bearer, or one that is expired, revoked or no longer resolves to a member.
The error envelope every non-2xx answer uses.
object
Human-readable explanation.
Machine-readable reason. Absent on a few legacy 400s.
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).
The error envelope every non-2xx answer uses.
object
Human-readable explanation.
Machine-readable reason. Absent on a few legacy 400s.
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).
The error envelope every non-2xx answer uses.
object
Human-readable explanation.
Machine-readable reason. Absent on a few legacy 400s.
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).
object
The version that is on the server now.
object
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.
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.
bundle:<file> when pushed from a config repo; null when built by a person.
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.
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.
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.
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.
Migrated to the current schema version on read. Null when it could not be migrated.
Migration steps applied on read. Non-empty means the stored row is from an older build.
object
The repository file that owns the template: bundle:<file>.
Example
{ "code": "TEMPLATE_CONFLICT", "template": { "visibility": "private", "managedBy": "sdk" }}The configuration is not valid for the current schema version.
object
Example
{ "code": "INVALID_TEMPLATE"}