Reserve an upload
const url = 'https://api.sloose.com/orgs/org_9f3c/imports/imp_4d1a/files';const options = { method: 'POST', headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'}, body: '{"size":1,"sha256":"example","id":"2489E9AD-2EE2-8E00-8EC9-32D5F69181C0"}'};
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/files \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data '{ "size": 1, "sha256": "example", "id": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0" }'Reserves one file for this import and returns how to upload it straight to storage: a single signed PUT for a file up to 64 MiB, whose SHA-256 is signed in so storage verifies the bytes, or a multipart plan whose parts are each requested with POST …/files/{fid}/parts once their Content-MD5 is known. Refused where the plan’s space for files would be passed (403 LIMIT_FILES_BYTES) or the file is larger than one may be here (403 LIMIT_FILE_SIZE, the lower of five gigabytes and the organisation’s own ceiling). The row exists before any byte does; a reserved upload never committed is deleted after a day. No file name is sent or stored.
Authorizations
Section titled “Authorizations”Parameters
Section titled “Parameters”Path Parameters
Section titled “Path Parameters”The organisation id the session was issued for. A token for one organisation can never read another.
Example
org_9f3cThe organisation id the session was issued for. A token for one organisation can never read another.
The import id.
Example
imp_4d1aThe import id.
Request Bodyrequired
Section titled “Request Bodyrequired”object
The file’s size in bytes (at least one: an empty file is nothing to store).
The content’s SHA-256, base64, computed by the browser. Signed into a single upload, so storage verifies it; for a multipart file it is a claim.
The file’s id, made by the caller (a UUIDv7), so that a reservation asked again after its answer was lost is the same reservation: the same id, size and checksum answer how to upload it again, and nothing is reserved twice. An id that is another file’s, or this one’s with other facts, is refused (FILE_ID_TAKEN). Absent, the server makes one.
Examplegenerated
{ "size": 1, "sha256": "example", "id": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0"}Responses
Section titled “Responses”The file is reserved.
object
object
The stored size in bytes, read from storage at commit; null until then.
Read from the file’s first bytes by the server, never from its name or the browser’s claim.
The content’s SHA-256 (base64), as the browser said it. See sha256Verified.
True where storage checked it (a single signed PUT); false where it is the browser’s claim (a multipart file, whose parts are each verified by their MD5).
When the sweep may take the file. For an upload in progress it moves on with every link signed: one that has passed is an upload nobody is sending.
When the file was reserved (ISO 8601, UTC): a reservation never finished is told by how old it is.
object
Headers to send on the PUT exactly as given: they are part of the signature, and storage refuses a request without them.
object
object
Example
{ "file": { "state": "reserved" }, "upload": { "mode": "single" }}No bearer, or one that no longer resolves: a session that is unknown or expired (code: AUTH_REQUIRED), or an API token that was revoked or expired (TOKEN_REVOKED, TOKEN_EXPIRED), whose organisation is gone (ORG_NOT_FOUND) or whose member or user row is (MEMBERSHIP_GONE).
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"}A limit: LIMIT_FILES_BYTES or LIMIT_FILE_SIZE, or the role or session. Like every route behind a session: a session signed in but in no organisation is refused code: NO_ORG, a banned person code: BANNED, and a closed organisation code: ORG_CLOSED.
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.
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"}This deployment cannot take direct uploads yet (NOT_CONFIGURED), or the id asked for is another file’s (FILE_ID_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 id asked for is not a UUIDv7 made within a day of the server’s clock (INVALID_FILE_ID).
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 restore switch is on (code: MAINTENANCE): every route but /health and /robots.txt is refused before anything is read, except the operator’s own POST /staff/people/{id}/delete with the ADMIN_TOKEN. Sloose is down for maintenance. Please try again in a few minutes.
object
Example
{ "code": "MAINTENANCE"}Headers
Section titled “Headers”Seconds until asking again is worth it (300 while the switch is on).