Skip to content

Reserve an upload

POST
/orgs/{org}/imports/{id}/files
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.

org
required

The organisation id the session was issued for. A token for one organisation can never read another.

string
Example
org_9f3c

The organisation id the session was issued for. A token for one organisation can never read another.

id
required

The import id.

string
Example
imp_4d1a

The import id.

Media typeapplication/json
object
size
required

The file’s size in bytes (at least one: an empty file is nothing to store).

integer
>= 1
sha256
required

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.

string
id

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.

string format: uuid
Examplegenerated
{
"size": 1,
"sha256": "example",
"id": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0"
}

The file is reserved.

Media typeapplication/json
object
file
required
object
id
required
string
state
required
string
Allowed values: reserved committed attached removed deleting
size
required

The stored size in bytes, read from storage at commit; null until then.

integer | null
declaredSize
required
integer
contentType
required

Read from the file’s first bytes by the server, never from its name or the browser’s claim.

string | null
sha256
required

The content’s SHA-256 (base64), as the browser said it. See sha256Verified.

string | null
sha256Verified
required

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).

boolean
dueAt
required

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.

string | null
createdAt
required

When the file was reserved (ISO 8601, UTC): a reservation never finished is told by how old it is.

string
upload
required
One of:
object
url
required
string
headers
required

Headers to send on the PUT exactly as given: they are part of the signature, and storage refuses a request without them.

object
key
additional properties
string
expiresInSeconds
required
integer
mode
required
string
Allowed values: single
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).

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

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.

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.

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

This deployment cannot take direct uploads yet (NOT_CONFIGURED), or the id asked for is another file’s (FILE_ID_TAKEN).

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 id asked for is not a UUIDv7 made within a day of the server’s clock (INVALID_FILE_ID).

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 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.

Media typeapplication/json
object
error
required
string
code
required
string
Allowed value: MAINTENANCE
Example
{
"code": "MAINTENANCE"
}
Retry-After
integer

Seconds until asking again is worth it (300 while the switch is on).

Report a problem with this page

sloose.com