Skip to content

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

  1. POST /api/upload-sessions
  2. inspect upload_strategy
  3. if multipart, call POST /api/upload-sessions/{id}/parts for part instructions
  4. upload parts directly to storage
  5. POST /api/upload-sessions/{id}/complete
  6. poll GET /api/upload-sessions/{id}
  7. when status is ready, call POST /api/products with upload_session_id

Remote import flow

  1. POST /api/upload-sessions with session_type=remote_import
  2. POST /api/upload-sessions/{id}/remote with incoming file payload
  3. poll or finalize according to session state
  4. attach ready session to product

Session fields

Current session resources expose fields such as:

FieldTypeNotes
idstringUpload session id.
session_typestringdevice_multipart or remote_import.
statusstringcreated, uploading, uploaded, finalizing, ready, failed, aborted, expired.
upload_strategystringsingle_part or multipart.
asset_kindstring or nullUsually image or video.
file_namestring or nullOriginal filename.
file_size_bytesinteger or nullFile size in bytes.
mime_typestring or nullUploaded mime type.
staging_diskstringCurrent staging disk.
uploaded_partsarrayMultipart parts already accepted.
uploaded_assetobject or nullFinalized asset reference when ready.
initial_uploadobject or nullSingle-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

FieldTypeRequiredNotes
session_typestringYesdevice_multipart or remote_import.
product_idintegerNoExisting product the upload will later attach to.
asset_kindstringNoCurrent config supports image/video kinds.
file_namestringYes for device_multipartOriginal filename.
file_size_bytesintegerYes for device_multipartMax upload size is environment-configured, currently 5 GB.
mime_typestringYes for device_multipartMust be an allowed mime type.
remote_providerstringYes for remote_importMust be enabled in upload config.
remote_provider_file_idstringNoProvider-specific identifier.
remote_provider_metadataobjectNoProvider-specific metadata blob.

Allowed remote providers in current config

  • url
  • onedrive
  • unsplash
  • google_drive_picker
  • google_photos_picker
  • dropbox
  • box
  • google_drive

Success response example

json
{
  "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_id is 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

json
{
  "part_number": 1
}

Success response example

json
{
  "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

json
{
  "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 ready
  • 202 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/jpeg
  • image/png
  • image/webp
  • image/gif
  • image/heic
  • image/heif

Video

  • video/mp4
  • video/quicktime
  • video/x-msvideo
  • video/x-matroska
  • video/webm

Example flow: upload then create product

  1. POST /api/upload-sessions
  2. POST /api/upload-sessions/{id}/parts until all parts are uploaded
  3. POST /api/upload-sessions/{id}/complete
  4. GET /api/upload-sessions/{id} until status=ready
  5. POST /api/products with upload_session_id

Fangate backend developer documentation