Skip to content

Create a direct-to-storage upload session.

POST
/v1/uploads
curl --request POST \
--url https://api.share2.us/v1/uploads \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{ "source": "cli", "filename": "example", "size_bytes": 1, "sha256": "example", "content_class": "text", "expires_in_hours": 1, "password_protected": false, "one_time_download": false, "encrypted_client_side": false, "visibility": "public", "recipient_email": "hello@example.com", "targets": [ { "target_device_session_id": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0", "sealed_key": "example" } ], "target_device": "example", "sealed_key": "example" }'

Firebase browser callers must include a valid X-Session-Id; otherwise the API returns 401 session_required.

Media typeapplication/json
object
source
required
string
Allowed values: cli portal mcp api
filename
required
string
>= 1 characters <= 255 characters
size_bytes
required
integer format: int64
>= 1
sha256
required
string
/^[a-f0-9]{64}$/
content_class
required
string
Allowed values: text image document archive binary
expires_in_hours
required
integer
>= 1
password_protected
boolean
one_time_download
boolean
encrypted_client_side
boolean
visibility

private makes the share recipient-restricted from creation, EVEN WITH NO RECIPIENTS — which the gateway resolves to “only an active user of the owning account” (ADR-022). That is the “upload a file privately” case; without it the only route is upload-public-then-flip via POST /v1/shares/{id}/visibility, which leaves a live public link in between. Not plan-gated (neither is that flip). Cannot be combined with target_device or recipient_email, where a link visibility describes nothing.

string
default: public
Allowed values: public private
recipient_email

Recipient email for cross-account E2E teammate delivery.

string format: email
targets

Per-recipient-device sealed content keys for teammate delivery.

Array<object>
object
target_device_session_id
required
string format: uuid
sealed_key
required

Base64-encoded 80-byte sealed content-key envelope.

string
target_device

Back-compatible own-device target alias or session id.

string
sealed_key

Back-compatible own-device base64 sealed content-key envelope.

string

Upload session created.

Media typeapplication/json
object
upload
required
object
id
required
string
share_id
required
string
status
required
string
Allowed values: created uploading completed canceled failed
expected_size_bytes
required
integer format: int64
expected_sha256
string
/^[a-f0-9]{64}$/
created_at
required
string format: date-time
share
required
object
id
required
string
public_id
required
string
>= 12 characters
url
required
string format: uri
filename
required
string
size_bytes
required
integer format: int64
content_class
string
Allowed values: text image document archive binary
state
required
string
Allowed values: created uploading uploaded scanning ready expired revoked blocked deleted
download_count
integer
max_downloads
integer
>= 1
password_protected
boolean
recipient_restricted

What the share ACTUALLY is. On the create response this is what lets a client that asked for visibility: private tell it got one: an older server ignores the field and returns a 201 with a PUBLIC link, so an ABSENT value must be read as “unknown”, never as false.

boolean
encrypted
boolean
scan_status

Malware scan outcome. skipped means the file was not scanned (scanning off, encrypted, or scanner unavailable) and is served with a visible warning; only a real dirty verdict blocks a share (ADR-013).

string
Allowed values: pending clean blocked skipped
expires_at
required
string format: date-time
created_at
required
string format: date-time
upload_plan
required
object
method
required
string
Allowed values: put multipart
url
required
string format: uri
headers
object
key
additional properties
string
parts
Array<object>
object
part_number
required
integer
>= 1
url
required
string format: uri
expires_at
required
string format: date-time
Example
{
"upload": {
"status": "created"
},
"share": {
"content_class": "text",
"state": "created",
"scan_status": "pending"
},
"upload_plan": {
"method": "put"
}
}

Standard error envelope.

Media typeapplication/json
object
error
required
object
code
required
string
message
required
string
request_id
required
string
Example
{
"error": {
"code": "quota_exceeded"
}
}