Resumable Upload

Some uploads such as videos or large tailored audiences might be greater than 64MB and should use resumable upload. Resumable upload is a 2-step process. First, make a request with the total content length and content type which returns a location. Second, upload chunks of size less than 64MB using the location from the initial request. Note that chunks should be in integer multiples of x-ton-min-chunk-size (except the last).

Please choose an upload chunk size such that you can reliable upload the chunk in a 30-second window. For example: If you have dedicated upload bandwidth of 10Mbit/s, please use an upload chunk size smaller than 37.5 MB.

An example resumable upload initialization request:

POST /1.1/ton/bucket/{bucket}?resumable=true HTTP/1.1
host: ton.twitter.com
content-length: 0
content-type: video/mp4
x-ton-content-type: video/mp4
x-ton-content-length: 516928473
authorization: OAuth oauth_consumer_key=\"XXXXXXXXXX\", oauth_nonce=\"XXXXXXXXXX", oauth_signature=\"XXXXXXXXXX\", oauth_signature_method=\"HMAC-SHA1\", oauth_timestamp=\"1426878860\", oauth_token=\"XXXXXXXXXX", oauth_version=\"1.0\"

The response:

HTTP/1.1 201 OK
date: Wed, 05 Nov 2014 22:50:16 UTC
location: /1.1/ton/bucket/{bucket}/SzFxGfAg_Zj.mp4?resumable=true&resumeId=28401873
x-ton-max-chunk-size: {max chunk size}
x-ton-min-chunk-size: {min chunk size, except the last chunk}
expires: Wed, 05 Nov 2014 23:50:16 UTC
content-length: 0

The initialization request requires the following headers:

  • authorization: See 3-legged authorization
  • content-length: Set to 0
  • content-type: The Content-Type of the asset to be uploaded, cf. [1]
  • x-ton-content-type: Identical to content-type
  • x-ton-content-length: Total number of bytes of the asset to be uploaded

The initialization response contains a Location which should be saved as it will be used in all subsequent requests.

After initialization, chunks can be uploaded.

An example resumable video upload request:

PUT /1.1/ton/bucket/{bucket}/SzFxGfAg_Zj.mp4?resumable=true&resumeId=28401873 HTTP/1.1
authorization: // oAuth1.0a (3-legged) details here
content-type: video/mp4
content-length: {number of bytes transferred in this request}
content-range: bytes {starting position, inclusive, 0-indexed}-{end position, inclusive}/{total content length}

{video bytes}

The response for each chunk except the last:

HTTP/1.1 308 Resume Incomplete
date: Wed, 05 Nov 2014 23:20:10 UTC
content-length: 0
range: 0-{current uploaded length}

The response for the last chunk:

HTTP/1.1 201 Created
date: Wed, 05 Nov 2014 23:30:10 UTC
location: /1.1/ton/bucket/{bucket}/SzFxGfAg_Zj.mp4
content-length: 0

Once completed, the location header should be saved as it may be necessary for subsequent Twitter API calls.