Skip to content

Save, update, detach, take the latest, choose another, or drop the template

POST
/orgs/{org}/imports/{id}/template
curl --request POST \
--url https://api.sloose.com/orgs/org_9f3c/imports/imp_4d1a/template \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{ "action": "new", "templateId": "example", "version": 1, "name": "example", "visibility": "private", "registryVersion": 1 }'

The six commands between an import and its template (design §2.2; choose and drop are §6 of the draft-and-refine design). Each is one write under version: the import and whatever it writes to the template land together or not at all, and are refused while a run holds the import.

  • new — any role, on an import they may change: a template from the import’s recipe, its first version, and the import pointed at it. Each flow’s source is described by what it is now — its reader and its place among the import’s sources — because a template is run again on next month’s file.
  • update — the builder role or above, and for a private template its creator or an administrator: the recipe becomes the template’s next version, only while the template is still at the version this import copied (409 TEMPLATE_MOVED otherwise, naming the version it is at, who made it and when), and never for a template a configuration repo manages (409 TEMPLATE_MANAGED). The import moves to the version it made. An unchanged recipe writes nothing: a version that moved for nothing would tell every other import from the template that it had moved on.
  • detach — the pointer is cleared; the recipe stays, as the import’s own. Detaching an import that has no template changes nothing and moves no version.
  • take-latest — the template’s current recipe replaces the import’s, and each of the template’s flows is paired with a source the import holds: the source already feeding a flow of that id, then a worksheet of the same name, then — only when exactly one of each is left — the one left. A source paired with nothing keeps a flow of its own: the one it fed, with this import’s recipe for it. A flow of the template paired with nothing stays in the recipe, for a file still to come.
  • choose — for a file that does not fit the template the import was started from (design §6, Choose another template): the chosen template’s current recipe replaces the import’s and the import points at it, at that version. Each file the import holds takes one of its recipes as a file arriving does — the recipe made for a worksheet of its name, where one alone was, else the first still waiting, in the template’s order, the files taken in the order the import holds them — and a file left with none starts a recipe of its own, empty. Nothing of the recipe it replaces is kept: it was the other template’s. A template the caller cannot see is not found.
  • drop — Start without a template (design §6): the pointer and the recipe both go, with the modules it chose and the draft’s account of it, and each file keeps its rows and its cleaning under a recipe of its own, empty, as an import started without a template would hold them. An import with no template changes nothing and moves no version.
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 import id.

string
Example
imp_4d1a

The import id.

Media typeapplication/json
object
action
required

new: save this import’s recipe as a new template and point the import at it. update: write it as the next version of the template the import came from. detach: forget the template; the recipe is the import’s own. take-latest: replace the recipe with the template’s current version. choose: take another template (templateId) — its current version replaces the recipe, and the import points at it. drop: start without a template — the template and its recipe are both forgotten; the files and their cleaning stay.

string
Allowed values: new update detach take-latest choose drop
templateId

choose only, and required there: the template to take, one the caller can see — shared with the org, or their own.

string
>= 1 characters
version
required

The import’s version this was decided against — from the last read or write.

integer
>= 1
name

new only: what the template is called. The import’s name when absent.

string
>= 1 characters <= 200 characters
visibility

new only: private (the default) is yours alone; org shares it with everyone here, which needs the builder role and a plan with shared templates.

string
Allowed values: private org
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

update, detach, take-latest, choose and drop: the import as it now stands, and — after update, take-latest and choose — the template it now has. template is absent after detach and drop, which leave the import without one.

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

The connection Target names; null until one is chosen.

string | null
templateId
required

The template this import was started from or saved as.

string | null
templateVersion
required

The template version it copied: “the template has moved on” compares this.

integer | null
name
required
string
createdByUserId
required

Who started it — the person, or the person a token acts as. Null only for an import a schedule started, which is nobody’s own.

string | null
tokenId
required

The token held, when one was.

string | null
createdByScheduleId
required
string | null
status
required

Where it stands. An import being deleted is not returned at all: it reads as gone the moment its delete is accepted.

string
Allowed values: open running attention done
currentStep
required

Whichever step the wizard of the day left it on, as that wizard names it.

string | null
currentStage
required
string | null
completedSteps
required
Array<string>
enabledModules
required
Array<string>
version
required

The write precondition: every change names the version it was made against, and a stale one is refused 409 IMPORT_CHANGED.

integer
updatedByUserId
required
string | null
updatedByTokenId
required
string | null
updatedByScheduleId
required
string | null
runningRunId
required

The run that holds the import; every other write is refused while one does.

string | null
lastRunAt
required
string | null
createdAt
required
string
updatedAt
required
string
recipe
required

The import’s own flows, value maps and run policy, migrated to the current schema version on read. Null until the wizard writes one, or when it could not be migrated.

object | null
migrated
required

Migration steps applied to the recipe on read.

Array<string>
unreadable
required
string | null
sources
required
Array<object>
object
id
required
string
position
required
integer
label
required
string
defaultLabel
required
string | null
origin
required

Where the rows came from: file, paste, generated, connection.

string
reader
required

Which reader read the bytes: delimited or xlsx.

string | null
connectorId
required
string | null
madeFrom
required
string | null
byteSize
required
integer | null
digest
required

The SHA-256 of the file stored for the source, hex: the identity of its bytes, which changes with every new file and never with a new reading of the same one. With how they are read (reader, options, sheetName), what says an AI answer that proposed a change to the file (a reshape, a sample, a re-read) was not taken: the same bytes, read the same way, are still the file it was proposed for. Null for a file stored before it was kept; the sheets of one workbook share their workbook’s.

string | null
madeByAnswer
required

Which kept answer made this file — { turnId, index }, the turn and the reshape, sample or re-read in its targets — or null: what says such an answer was used, on the server and in the app alike, where the file’s shape cannot. Written with every file stored for the source and every new reading of it, from the upload’s madeByAnswer, and null for any other.

object
turnId
required
string
>= 1 characters <= 100 characters
index
required
integer
<= 499
reshape
required

How this file was reshaped from the file as read at its header row (#1363): the steps in order, each counted on the grid the ones before it left, every row a step named by its place marked so another file’s can be found by it. Written with every file stored for the source and every new reading of it, from the upload’s reshape, and null for any other.

object
steps
required
Array<object>
>= 1 items
object
op
required
string
>= 1 characters
marks
Array<object>
object
from
required
string
Allowed values: start end
at
required
integer
>= 1
shape
required

One letter a cell: b blank, n a number, t other text.

string
/^[bnt]*$/
text
required

Its text cells, digits taken out, case and spaces folded, joined by |.

string
key
additional properties
options
required

What the reader needs to read the file again: delimiter, sheet, header row — in the shape this build reads, whatever shape they were stored in. They are stored with the version of that shape and walked forward when read; that version is not shown.

object | null
sheetName
required

The worksheet’s name, for a source read from one; null for text. The reader finds the sheet by its place (options.sheet); a template names it by this, because a name survives next month’s workbook having its tabs reordered.

string | null
columns
required
Array<string>
rowCount
required
integer
cleaningBytes
required

The size of the current cleaning revision; null when the source has none.

integer | null
workBytes
required

The size of the current revision of its work — the guesses waiting on it, the ones turned down, how each used one was found; null when the source has none.

integer | null
flowId
required

The recipe flow this source feeds, paired by id and never by label or position.

string | null
createdAt
required
string
draft
required

The draft’s account of itself — which parts it drafted, which it could not and why — as the wizard wrote it, with its schemaVersion; null when no draft has been made.

object | null
libraryPins
required

The versions this import keeps instead of the current ones (#559): namespace → { version, library }. Empty when it keeps none. A pin whose library is no longer the one current under its name keeps nothing — the library was removed since — and the page says so.

object
key
additional properties
object
version
required
number
library
required
string
template

The template the action wrote or read: the new one, the updated one, the one whose latest was taken, the one chosen. Absent after detach and drop.

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
{
"import": {
"status": "open",
"sources": [
{
"reshape": {
"steps": [
{
"marks": [
{
"from": "start"
}
]
}
]
}
}
]
},
"template": {
"visibility": "private",
"managedBy": "sdk"
}
}

new: the import pointed at its new template, and the template.

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

The connection Target names; null until one is chosen.

string | null
templateId
required

The template this import was started from or saved as.

string | null
templateVersion
required

The template version it copied: “the template has moved on” compares this.

integer | null
name
required
string
createdByUserId
required

Who started it — the person, or the person a token acts as. Null only for an import a schedule started, which is nobody’s own.

string | null
tokenId
required

The token held, when one was.

string | null
createdByScheduleId
required
string | null
status
required

Where it stands. An import being deleted is not returned at all: it reads as gone the moment its delete is accepted.

string
Allowed values: open running attention done
currentStep
required

Whichever step the wizard of the day left it on, as that wizard names it.

string | null
currentStage
required
string | null
completedSteps
required
Array<string>
enabledModules
required
Array<string>
version
required

The write precondition: every change names the version it was made against, and a stale one is refused 409 IMPORT_CHANGED.

integer
updatedByUserId
required
string | null
updatedByTokenId
required
string | null
updatedByScheduleId
required
string | null
runningRunId
required

The run that holds the import; every other write is refused while one does.

string | null
lastRunAt
required
string | null
createdAt
required
string
updatedAt
required
string
recipe
required

The import’s own flows, value maps and run policy, migrated to the current schema version on read. Null until the wizard writes one, or when it could not be migrated.

object | null
migrated
required

Migration steps applied to the recipe on read.

Array<string>
unreadable
required
string | null
sources
required
Array<object>
object
id
required
string
position
required
integer
label
required
string
defaultLabel
required
string | null
origin
required

Where the rows came from: file, paste, generated, connection.

string
reader
required

Which reader read the bytes: delimited or xlsx.

string | null
connectorId
required
string | null
madeFrom
required
string | null
byteSize
required
integer | null
digest
required

The SHA-256 of the file stored for the source, hex: the identity of its bytes, which changes with every new file and never with a new reading of the same one. With how they are read (reader, options, sheetName), what says an AI answer that proposed a change to the file (a reshape, a sample, a re-read) was not taken: the same bytes, read the same way, are still the file it was proposed for. Null for a file stored before it was kept; the sheets of one workbook share their workbook’s.

string | null
madeByAnswer
required

Which kept answer made this file — { turnId, index }, the turn and the reshape, sample or re-read in its targets — or null: what says such an answer was used, on the server and in the app alike, where the file’s shape cannot. Written with every file stored for the source and every new reading of it, from the upload’s madeByAnswer, and null for any other.

object
turnId
required
string
>= 1 characters <= 100 characters
index
required
integer
<= 499
reshape
required

How this file was reshaped from the file as read at its header row (#1363): the steps in order, each counted on the grid the ones before it left, every row a step named by its place marked so another file’s can be found by it. Written with every file stored for the source and every new reading of it, from the upload’s reshape, and null for any other.

object
steps
required
Array<object>
>= 1 items
object
op
required
string
>= 1 characters
marks
Array<object>
object
from
required
string
Allowed values: start end
at
required
integer
>= 1
shape
required

One letter a cell: b blank, n a number, t other text.

string
/^[bnt]*$/
text
required

Its text cells, digits taken out, case and spaces folded, joined by |.

string
key
additional properties
options
required

What the reader needs to read the file again: delimiter, sheet, header row — in the shape this build reads, whatever shape they were stored in. They are stored with the version of that shape and walked forward when read; that version is not shown.

object | null
sheetName
required

The worksheet’s name, for a source read from one; null for text. The reader finds the sheet by its place (options.sheet); a template names it by this, because a name survives next month’s workbook having its tabs reordered.

string | null
columns
required
Array<string>
rowCount
required
integer
cleaningBytes
required

The size of the current cleaning revision; null when the source has none.

integer | null
workBytes
required

The size of the current revision of its work — the guesses waiting on it, the ones turned down, how each used one was found; null when the source has none.

integer | null
flowId
required

The recipe flow this source feeds, paired by id and never by label or position.

string | null
createdAt
required
string
draft
required

The draft’s account of itself — which parts it drafted, which it could not and why — as the wizard wrote it, with its schemaVersion; null when no draft has been made.

object | null
libraryPins
required

The versions this import keeps instead of the current ones (#559): namespace → { version, library }. Empty when it keeps none. A pin whose library is no longer the one current under its name keeps nothing — the library was removed since — and the page says so.

object
key
additional properties
object
version
required
number
library
required
string
template

The template the action wrote or read: the new one, the updated one, the one whose latest was taken, the one chosen. Absent after detach and drop.

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
{
"import": {
"status": "open",
"sources": [
{
"reshape": {
"steps": [
{
"marks": [
{
"from": "start"
}
]
}
]
}
}
]
},
"template": {
"visibility": "private",
"managedBy": "sdk"
}
}

The request did not match the schema (issues carries the Zod issue list); choose named no templateId (code: INVALID_BODY); or new or update sent a registryVersion 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"
}

An operator acting on somebody else’s import (code: NOT_YOURS); an operator updating or sharing a template (code: ROLE_REQUIRED); updating somebody else’s private template without being an administrator (code: NOT_TEMPLATE_OWNER); or a plan that 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 import, template — for choose, one the caller cannot see is not found — or the connection the import names, or it is not visible to this session.

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 changed the import since this version (code: IMPORT_CHANGED, with its version and updatedBy); a run holds it (code: IMPORT_RUNNING); the template has moved on since the import copied it (code: TEMPLATE_MOVED, with its version, updatedBy and updatedAt); a configuration repo manages the template (code: TEMPLATE_MANAGED, with its sourceRef); the import has no template to update or take from (code: NO_TEMPLATE), or no recipe to save (code: NO_RECIPE); or a stored recipe, or a source’s reader options, came from a newer build (code: FROM_FUTURE, which is refused before anything is written).

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 import’s stored recipe (code: INVALID_RECIPE) or the template’s (code: INVALID_TEMPLATE) is not usable under the current schema, with its issues; or it could not be read at all (code: UNREADABLE).

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

Report a problem with this page