Upload Sessions
Preferred resumable upload API for modern Fangate clients.
Use upload sessions when you need:
- direct-to-storage uploads
- resumable multipart uploads
- large video uploads
- remote-import staging
- an explicit backend-ready state before creating a product
After an upload session reaches ready, attach it to a product with POST /api/products using upload_session_id.
Session lifecycle
Device multipart flow
POST /api/upload-sessions- inspect
upload_strategy - if
multipart, callPOST /api/upload-sessions/{id}/partsfor part instructions - upload parts directly to storage
POST /api/upload-sessions/{id}/complete- poll
GET /api/upload-sessions/{id} - when status is
ready, callPOST /api/productswithupload_session_id
Remote import flow
POST /api/upload-sessionswithsession_type=remote_importPOST /api/upload-sessions/{id}/remotewith incoming file payload- poll or finalize according to session state
- attach ready session to product
Session fields
Current session resources expose fields such as:
| Field | Type | Notes |
|---|---|---|
id | string | Upload session id. |
session_type | string | device_multipart or remote_import. |
status | string | created, uploading, uploaded, finalizing, ready, failed, aborted, expired. |
upload_strategy | string | single_part or multipart. |
asset_kind | string or null | Usually image or video. |
file_name | string or null | Original filename. |
file_size_bytes | integer or null | File size in bytes. |
mime_type | string or null | Uploaded mime type. |
staging_disk | string | Current staging disk. |
uploaded_parts | array | Multipart parts already accepted. |
uploaded_asset | object or null | Finalized asset reference when ready. |
initial_upload | object or null | Single-part upload instruction when applicable. |
POST /api/upload-sessions
Create a new upload session.
- Auth required: Yes
- Roles: Authenticated creator
- Content type:
application/json
Request body
| Field | Type | Required | Notes |
|---|---|---|---|
session_type | string | Yes | device_multipart or remote_import. |
product_id | integer | No | Existing product the upload will later attach to. |
asset_kind | string | No | Current config supports image/video kinds. |
file_name | string | Yes for device_multipart | Original filename. |
file_size_bytes | integer | Yes for device_multipart | Max upload size is environment-configured, currently 5 GB. |
mime_type | string | Yes for device_multipart | Must be an allowed mime type. |
remote_provider | string | Yes for remote_import | Must be enabled in upload config. |
remote_provider_file_id | string | No | Provider-specific identifier. |
remote_provider_metadata | object | No | Provider-specific metadata blob. |
Allowed remote providers in current config
urlonedriveunsplashgoogle_drive_pickergoogle_photos_pickerdropboxboxgoogle_drive
Success response example
{
"success": true,
"errors_message": null,
"data": {
"id": "01knyn6vkpnvh2rzgg9c0n6xz5",
"session_type": "device_multipart",
"status": "created",
"upload_strategy": "multipart",
"asset_kind": "video",
"file_name": "sample.mp4",
"file_size_bytes": 52428800,
"mime_type": "video/mp4",
"staging_disk": "uppy_staging_s3",
"uploaded_parts": [],
"uploaded_asset": null,
"initial_upload": null
}
}Validation and side effects
- if
product_idis sent, ownership is verified - upload strategy is derived from configured multipart policy and file size
- current default presign TTL is 15 minutes
- current multipart threshold is 100 MB with an 8 MB minimum part size
GET /api/upload-sessions/
Return the current state of one upload session.
- Auth required: Yes
- Roles: Session owner
Use this endpoint for polling after complete.
POST /api/upload-sessions/{uploadSession}/remote
Upload a remote-import payload into an existing remote session.
- Auth required: Yes
- Roles: Session owner
- Content type:
multipart/form-data
Request format
Send the file in either:
files[]file
If the client sends X-Fangate-Upload-Session, it must match the route session id.
POST /api/upload-sessions/{uploadSession}/parts
Request a presigned instruction for one multipart part.
- Auth required: Yes
- Roles: Session owner
- Content type:
application/json
Request body
{
"part_number": 1
}Success response example
{
"success": true,
"errors_message": null,
"data": {
"session": {
"id": "01knyn6vkpnvh2rzgg9c0n6xz5",
"status": "uploading"
},
"part": {
"part_number": 1,
"method": "PUT",
"url": "https://example-presigned-url",
"headers": {
"Content-Type": "video/mp4"
},
"expires_at": "2026-04-20T10:15:00Z"
}
}
}POST /api/upload-sessions/{uploadSession}/complete
Finalize a direct upload.
- Auth required: Yes
- Roles: Session owner
- Content type:
application/json
Multipart request body
{
"parts": [
{
"part_number": 1,
"etag": "etag-value",
"size_bytes": 8388608
}
]
}For single_part or remote_import flows, the body can be omitted.
Responses
200 OK: session is already ready202 Accepted: finalization continues asynchronously
Side effects
- may dispatch
FinalizeUploadSessionJob - finalizer processes on
filesystems.media_process_disk - if processing disk and final disk differ, backend mirrors the finalized asset to
uploads.final_disk
DELETE /api/upload-sessions/
Abort an unfinished upload session.
- Auth required: Yes
- Roles: Session owner
Returns the final session representation with status=aborted.
Accepted file types
Current upload config allows:
Images
image/jpegimage/pngimage/webpimage/gifimage/heicimage/heif
Video
video/mp4video/quicktimevideo/x-msvideovideo/x-matroskavideo/webm
Example flow: upload then create product
POST /api/upload-sessionsPOST /api/upload-sessions/{id}/partsuntil all parts are uploadedPOST /api/upload-sessions/{id}/completeGET /api/upload-sessions/{id}untilstatus=readyPOST /api/productswithupload_session_id