Add sources from a file
const url = 'https://api.sloose.com/orgs/org_9f3c/imports/imp_4d1a/sources';const form = new FormData();form.append('version', '1');form.append('file', 'file');form.append('candidates', 'example');form.append('flowIds', 'example');form.append('sourceIds', 'example');form.append('label', 'example');form.append('origin', 'file');form.append('madeFrom', 'example');form.append('madeByAnswer', 'example');form.append('reshape', 'example');form.append('options', 'example');form.append('sheetName', 'example');
const options = {method: 'POST', headers: {Authorization: 'Bearer <token>'}};
options.body = form;
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/imports/imp_4d1a/sources \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: multipart/form-data' \ --form version=1 \ --form file=@file \ --form candidates=example \ --form flowIds=example \ --form sourceIds=example \ --form label=example \ --form origin=file \ --form madeFrom=example \ --form madeByAnswer=example \ --form reshape=example \ --form options=example \ --form sheetName=exampleUpload a file and make one source from it — or, from a workbook, one per worksheet — in one write under version.
A file is routed by its first bytes, never by its name. A workbook (.xlsx) is read by the workbook reader; anything else is delimited text, its delimiter, quoting and folding worked out from the file. An .xls or .ods is refused naming the one step that fixes it (422 SPREADSHEET_FORMAT).
From a workbook, candidates names the worksheets to add; absent, every worksheet with rows under its header is added. Each becomes its own source, in workbook order, with its own options — { sheet, headerRow }, the header row found per sheet — and every one of them reads the one stored copy of the file. A worksheet that cannot be read fails alone and is named in failed; when none can be, nothing is written (422 NOTHING_READ). Delimited text is one source, stored with { delimiter, quote, collapse } all null: worked out from the file each time it is read, as the wizard stores them.
The bytes are stored once, exactly as uploaded, under a key the server mints — no route takes one from a client — and before the sources are written. An upload that loses the version race takes its file back at once; one whose write failed without saying whether it landed leaves the file, and the nightly sweep deletes it after a day if nothing names it.
madeByAnswer says which kept AI answer made the file — its reshape, sample or re-read, applied — and is what says that answer was used; absent, or with a workbook, no answer made it.
Each source is named where its rows came from: the file’s name, with · <worksheet> for a sheet; “Pasted data” or “Generated sample” for those origins. A name another source of the import already has is numbered.
A source’s id may be the client’s. sourceIds names the id of each source made, paired exactly as flowIds is — the wizard keeps its own (source-1, source-2) because its flows are bound to them, and an id is unique within its import, not across imports. One this import already holds is refused (409 SOURCE_TAKEN); absent, the server mints one. An id removed from an import may be given again: nothing else is keyed by it once its source is gone, and every stored object sits under a revision of its own.
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 import id.
Example
imp_4d1aThe import id.
Request Bodyrequired
Section titled “Request Bodyrequired”object
The version this change was made against — from the last read or write.
The file, at most 50 MB: a workbook (.xlsx) or delimited text, told apart by its first bytes. A plain field is read as text.
A JSON array of worksheet names to add, e.g. ["Accounts","Contacts"]. Absent: every worksheet with rows. Only for a workbook.
A JSON array of recipe flow ids, one per source made — paired with candidates by position when they are given, else with the sources in workbook order. Absent: minted. A flow id this import already uses is refused.
A JSON array of source ids, one per source made, paired as flowIds is. Each is 1 to 64 letters, digits, hyphens or underscores. Absent: minted. A source id this import already holds is refused.
What to call the upload in place of the file’s own name: the name its rows arrive under, and so the one a cleared name returns to.
Where the rows came from; file when absent. A paste is called “Pasted data” and a generated sample “Generated sample” rather than after a file, and both are delimited text.
What a generated sample was asked for — only with origin=generated.
Which kept AI answer made this file, as JSON — { "turnId": "…", "index": 0 }: the turn (GET …/conversations) and the place in its targets of the reshape, sample or re-read applied to make it. What says that answer was used, where the file’s shape cannot. Absent, or not a turn and a place, the file is one no answer made: every file stored, and every new reading of one, says which answer made it or that none did. Delimited text only: no answer makes a workbook.
How this file was reshaped from the file as read at its header row, as JSON — { "steps": [ … ] }: the reshape steps in order, each counted on the grid the ones before it left, and every row a step names by its place marked (marks: the end it was nearer, its place from that end, its cells’ shape and its words) so a template can find it in another file. A template made from the import carries it. Absent, or not one, the file is kept as not reshaped. Delimited text only.
Delimited text only: how to read it, as JSON — { "delimiter": ",", "quote": "\"", "collapse": false }, any setting null or absent to be worked out from the file. For a client that wrote the text itself and knows its format; a guess is right for a file somebody chose, and can only be wrong for this.
Delimited text only: the worksheet the client made it from, which a template names the source by. The server records what it is told; for a workbook it reads the name itself.
Responses
Section titled “Responses”Added.
object
object
The connection Target names; null until one is chosen.
The template this import was started from or saved as.
The template version it copied: “the template has moved on” compares this.
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.
The token held, when one was.
Where it stands. An import being deleted is not returned at all: it reads as gone the moment its delete is accepted.
Whichever step the wizard of the day left it on, as that wizard names it.
The write precondition: every change names the version it was made against, and a stale one is refused 409 IMPORT_CHANGED.
The run that holds the import; every other write is refused while one does.
The sources made, in workbook order, each with its columns and count.
object
Where the rows came from: file, paste, generated, connection.
Which reader read the bytes: delimited or xlsx.
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.
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
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
object
object
One letter a cell: b blank, n a number, t other text.
Its text cells, digits taken out, case and spaces folded, joined by |.
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.
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.
The size of the current cleaning revision; null when the source has none.
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.
The recipe flow this source feeds, paired by id and never by label or position.
The worksheets asked for that could not be read. Always empty for text.
object
The worksheet, as it was asked for.
Why it could not be read, in words a person can act on.
Example
{ "import": { "status": "open" }, "sources": [ { "reshape": { "steps": [ { "marks": [ { "from": "start" } ] } ] } } ]}The request — its body or its query — did not match the schema. issues carries the Zod issue list.
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 bearer’s role is too low, or it was issued for a different org; or somebody else started this import and an operator changes only their own (code: NOT_YOURS).
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 import, or it is not visible to this session (code: IMPORT_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"}As every write (IMPORT_CHANGED, IMPORT_RUNNING, NOT_CONFIGURED); a flow id in flowIds is already another source’s (code: FLOW_TAKEN); or a source id in sourceIds is already one of this import’s sources (code: SOURCE_TAKEN).
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 file is larger than 50 MB (code: FILE_TOO_LARGE, with the limit in bytes); or it is a workbook whose XML unpacks to more than 16 MB, more than the server reads whole — saved as CSV, the same sheet is read at any size up to the upload’s (code: WORKBOOK_TOO_LARGE, with unpacked and limit in bytes).
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 body is not multipart/form-data (code: UNSUPPORTED_MEDIA_TYPE).
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 file cannot be made into a source: an .xls or .ods (SPREADSHEET_FORMAT, with the problem), a workbook the reader cannot open (UNREADABLE_FILE), worksheets named for a text file (NOT_A_WORKBOOK), a workbook sent as a paste or a sample (NOT_TEXT), or nothing in it could be read (NOTHING_READ, with failed for a workbook) — as of a text with a row of more than 1,048,576 characters in its cells, or more than 16,384 cells, more than the server reads in one.
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"}