Create a template
const url = 'https://api.sloose.com/orgs/org_9f3c/templates';const options = { method: 'POST', 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 POST \ --url https://api.sloose.com/orgs/org_9f3c/templates \ --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 }'The configuration is migrated to the current schema version and validated before it is stored. Source rows are never stored — a template is the recipe, not the data.
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.
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”Created.
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 (code: NOT_TEMPLATE_OWNER), the plan cannot share templates (code: FEATURE_SHARED_TEMPLATES), or the org has been closed (code: ORG_CLOSED) — asked in the insert itself, so a request already let in when the org closed makes nothing.
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 connectorId names no connection this person — or token — may use (code: CONNECTION_NOT_FOUND): another org’s, somebody’s own, or none at all, which are one answer.
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 configuration came from a newer build than this server (code: FROM_FUTURE).
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 configuration is not valid for the current schema version.
object
Example
{ "code": "INVALID_TEMPLATE"}