Audiences
TON Upload
The TON (Twitter Object Nest) API allows implementers to upload media and various assets to Twitter. In this document we will cover authentication & authorization, usage, principles, and provide examples to get started.
Please consult with your Platform Relations representative or Ads API Partner Engineer on details specific to your integration; the below information may not be true for your integration. This document covers upload only. The TON API supports other operations but they are not covered in this document, as they are not needed for the upload API.
Authentication & Authorization¶
The TON API requires 3-legged authorization
Usage¶
The TON API supports non-resumable and resumable upload methods based on the size of the file. For files less than 64MB, non-resumable may be used. For files greater than or equal to 64MB, resumable must be used. Resumable uploads require chunk sizes of less than 64MB. Calculation of 64MB is based on 1024 bytes (64 * 1024 * 1024).
If your dedicated upload bandwidth for the TON Upload is less than ~20 Mbit/s we recommend using resumable upload even for files less than 64MB in size.
Principles¶
- The endpoint for the TON API is
ton.twitter.com - All requests must be made over HTTPS
- All responses are in
JSON - The Content-Type of your request cannot be
"application/x-www-form-urlencoded" - The Content-Type of your request will be a valid media type as defined by IANA: http://www.iana.org/assignments/media-types/media-types.xhtml
- Chunks should be in integer multiples of
x-ton-min-chunk-size(except the last). - The
locationheader after upload should be saved to be used in subsequent Twitter APIs, such as the Video API.
Buckets¶
For Tailored Audiences, please use the bucket name ta_partner.
Note that the ta_partner bucket also requires the x-ton-expires header to be set with an expiration date up to 7 days from the current date (see the ton-upload example script for more detail). For all other TON API buckets, this header is optional however it’s safe and a good practice to pass this header all the time and buckets that do not require it will simply ignore it.
Each bucket can be configured to support additional requirements. To confirm requirements for other features using the TON API, please refer to the documentation of that feature.
Examples¶
Included below are several examples on how to get started using the TON API. Please note that your Application ID must be whitelisted for the bucket that you are attempting to use.
Twurl¶
Twurl is a Ruby gem that is like curl, but tailored specifically for the Twitter API. Once configured, it can be used to make requests similar to curl.
An example non-resumable request:
twurl -t -H ton.twitter.com /1.1/ton/bucket/product_bucket_name -X POST -A "Content-Type: image/jpeg" -A "Content-Length: 136" --data "MY PRECIOUS BYTES"
You can find a sample Ruby TON upload script that depends on Twurl here.
Single Chunk Upload¶
Photo uploads and small tailored audiences will typically be under 64MB and can use non-resumable upload.
An example non-resumable photo upload request:
POST /1.1/ton/bucket/{bucket} HTTP/1.1
Host: ton.twitter.com
Content-Type: image/jpeg
Content-Length: {number_of_bytes}
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"
{image bytes}
The response:
HTTP/1.1 201 OK
Date: Wed, 05 Nov 2014 22:50:16 UTC
Content-Length: 0
Location: /1.1/ton/bucket/{bucket}/AzGxDfEg_Hj.jpg
Once completed, the Location header should be saved as it may be used in subsequent Twitter API calls.
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.