Upload V3

circle-exclamation

Quick Start

Base URL

  • Release Candidate (RC): https://upload-api-rc.truvideo.com/

  • Production: https://upload-api.truvideo.com/

Authentication

All API requests require a Bearer Token.

Authorization: Bearer YOUR-ACCESS-TOKEN

Access tokens are generated using the endpoint described in: [SDK Mobile] – Generate an API Token

⚠️ Token Expiry

  • Tokens expire after a fixed duration.

  • If a request returns 401 Unauthorized, generate a new token and retry the request.

  • Do not retry non-idempotent requests blindly after token refresh.

Key Identifiers

Field
Description

uploadId

Unique identifier for the upload session

mediaId

Identifier for the media asset in the TruVideo system

partNumber

Sequential chunk number (starting from 1)

eTag

MD5 hash returned by S3 after chunk upload

presignedUrl

Temporary authenticated URL for direct S3 upload

Multipart Upload Process (High-Level)

The B2B upload follows a four-phase asynchronous flow:

⚠️ Important: The upload is finalized asynchronously. Polling the status endpoint is a required step to confirm success or failure.

End-to-End Upload Workflow

Step 1: Start Upload (Create Session)

Endpoint

POST /upload/start

Summary: Starts a new multipart upload session.

Description Creates a new multipart upload session and returns:

  • uploadId

  • mediaId

  • Initial set of pre-signed URLs

Request Body Parameters

amountOfParts

integerRequired

The number of file parts for multipart upload. Must be between 1 and 120.

S3 Constraints:

  • Minimum size per part Each part must be at least 5 MB, except for the last part, which can be smaller.

  • Maximum size per part The maximum size of each part is 600 MB.

  • Maximum amount of parts You can divide a file into a maximum of 120 parts.

Example: 5

We will evaluate limiting the maximum number of parts to preserve adequate performance in our systems (Future updates)

chevron-rightMedia (object)hashtag

object • Required

Describes the media asset that will be uploaded. Contains technical details about the media file being uploaded.


fileType

stringRequired

File extension provided by the client.

These are all file types supported:

Extension | Type

MP4 | VIDEO MOV | VIDEO AVI | VIDEO MKV | VIDEO FLV | VIDEO WMV | VIDEO 3GPP | VIDEO WEBM | VIDEO JPG | IMAGE JPEG | IMAGE PNG | IMAGE SVG | IMAGE MP3 | AUDIO WAV | AUDIO AAC | AUDIO FLAC | AUDIO PDF | DOCUMENT

Example: "WAV"


creator

string [0, 255] characters • Optional

The name of the person or entity who created or uploaded the media. UUIDs are also valid.

Examples: "FirstName LastName" | 111111-222-aaa-bbb-33cc


title

stringOptional

Human-friendly title for the uploaded content. Used for display purposes in the media library. All special characters are now accepted. We have a sanitizedTitle in the response. The API will preserve the original title and additionally provide a sanitized version safe for filesystem operations.

  • Original title is preserved as submitted

  • A sanitized version (`sanitizedTitle`) is automatically generated for filesystem operations

  • No default value applied

Example of title: "BMW Engine diagnostic Walkaround 2025"

Example of sanitizedTitle in the response: Input: "Hello: World!" → Output: "Hello__World_" Input: "Product Lunch Video" → Output: "Product_Lunch_Video" Input: "Product %%#@^&" → Output: "Product_______"


duration

integerOptionalMilliseconds

Length of the media in milliseconds.

Example: 76661


resolution

stringOptional

Capture resolution label reported by the client

Constraints:

  • Exclusive values: “LOW, “NORMAL”, “HIGH”

  • If the client doesn’t explicitly specify a resolution, we default to Resolution.NORMAL, which corresponds to 720p. "LOW" and "HIGH" correspond to 480p and 1080p respectively.

  • No support to change resolution post-upload.

Example: “NORMAL"


tags

objectOptional

Free-form key/value labels that downstream systems can use for filtering.

Tags are used to classify and group media by intrinsic attributes — for example, category, type, or any characteristic that naturally describes the media itself. They are designed to enhance searchability and organization and are therefore part of the media object.

Constraints:

  • The tags are key value entries There are no specific length limits defined in our model

  • only MongoDB’s default document limit of 16 MB applies.

  • Custom key names are allowed since the key field is just indexed, with no restrictions or validation rules.

Example:

"brand": "Jeep",

"fuelType": "diesel"


insights:

objectOptional

Flags that control how the uploaded media is surfaced in downstream products.


isLibrary

booleanOptional

Indicates whether this upload should be added to the permanent media library (visible for reuse across work orders once processing finishes)

Default: false

Example: true


includeInReport

booleanOptional

Determines if this media should be injected into the automated PDF/email reports we send to customers; false keeps the media in the portal but omits it from the reports.

Default: true

Example: true

chevron-rightMetadata (object)hashtag

object Optional

Nested object containing various processing flags and technical specifications. Metadata is a flexible key–value object (Map<String, Object>) that can store business-specific or contextual information. It’s intended for custom integrations or domain-related data that may vary depending on each client’s use case.

Keys must be strings and values are stored as generic JSON objects (arrays and nested objects are supported). The only practical size limit is MongoDB’s 16 MB document cap, so keep metadata comfortably below a few megabytes. We reserve failureReason and failureTimestamp for internal lifecycle tracking, so avoid using those names in client payloads.

Example

{ "processingPriority": "NORMAL", "retentionDays": 365, "compressionEnabled": true, "encryptionType": "AES256" }

Common uses:

  • Business information

  • Tech specifications

Example Request

cURL

Method: POST

Request body

Success Response

201 Upload Session created

Error Response

400 Invalid Request Payload

401 Unauthorized

STEP 2. Get Upload Details

GET /upload/{uploadId}

Summary: Get upload details

Description: Retrieves the status and details of an existing upload session.

Success Response

Response 200 OK :

Response Fields:

Field
Type
Description

uploadId

string

Upload session identifier

mediaId

string

Media asset identifier

s3UploadId

string

AWS S3 multipart upload ID

status

string

Current upload status (INITIALIZED, PARTIAL, PENDING_COMPLETE, COMPLETED, FAILED)

bucketName

string

S3 bucket name

keyName

string

S3 object key

fileUrl

string

Direct S3 file URL

creator

string

Display name or identifier of the user/app that initiated the upload

parts

array

Registered parts with ETags

failureReason

string

Error message if status is FAILED (null otherwise)

sanitizedTitle

string

string`Auto-generated

A filesystem-safe version of the title where special characters and whitespace are replaced with underscores. This field is automatically generated by the system and returned in responses.

All non-alphanumeric characters (except `.`, `-`, and `_`) are converted to underscores

Whitespace is converted to underscores

Original title is preserved in the `title` field

Examples: Input: `"Product %%#@^&"` → Output: `"Product_______"`

Upload Status Values:

Status
Description

INITIALIZED

Upload session created but no data uploaded yet

PARTIAL

Some parts uploaded but upload not completed

PENDING_COMPLETE

Completion request received, processing in progress

COMPLETED

Upload successfully processed and available

FAILED

Processing encountered unrecoverable error

Error Response

401 Unauthorized:

400 Invalid uploadId

STEP 3: Complete Upload V3

POST /upload/{uploadId}/complete

Summary: Complete upload (B2B)

Description: Finalizes the upload asynchronously (202 Accepted) after validating contiguous parts. Accepts the B2B payload structure with the parts collection.

Request Body:

Success Response

202 Accepted:

Upload completion request accepted for asynchronous processing. The backend will assemble and validate the file. Use the GET endpoint to check the upload status.

Error Response

400 Invalid completion payload

401 Unauthorised


Upload Workflow

Complete V3 Upload Flow

Step 1: Start Upload

Call POST /upload/start to initialize the upload session:

Save the uploadId and presignedUrl from the response.


Step 2: Upload Chunks to S3

Use the pre-signed URLs returned in Step 1 to PUT each file chunk directly into S3. Follow the detailed instructions in “Step 2.1” below: split the file, send each chunk with the proper Content-Type header, and capture the ETag from every 200 OK response. Those ETags are required when you finalize the upload.

Step 2.1: Upload Chunks to S3

Important: Upload directly to S3 using the pre-signed URLs, NOT to the TruVideo API.

Split your file into chunks and upload each chunk to S3 using the pre-signed URLs:

S3 Response:

Critical: Capture and store the ETag from each S3 response. You must provide these ETags when completing the upload.

Chunk Size Recommendations:

Minimum size per part:

  • 5 MB (S3 requirement — except for the last part)

Recommended size per part:

  • Small files (<100MB): 10–20 MB

  • Medium files (100MB–1GB): 20–50 MB

  • Large files (>1GB): 50–600 MB

Maximum size per part:

  • 600 MB

Maximum number of parts:

  • 120 parts

Note: Future updates may further refine the maximum number of parts to preserve optimal system performance.


Step 2.2: Request Additional Pre-signed URLs (if needed)

If you need more pre-signed URLs than initially provided:

Response:


Step 3: Get Upload Status (Optional)

Check the current upload status:


Step 4: Complete Upload

After all chunks are uploaded to S3, call the complete endpoint with all part information:

Response:

circle-exclamation

Step 5: Poll for Completion

After receiving 202 Accepted, poll the GET endpoint to check the status:

The status field will move from PENDING_COMPLETE to either COMPLETED (success) or FAILED (error). Keep polling until the status reaches one of those terminal values.

Last updated