Ads Targeting - upload CSV file to TON bucket




I am trying to upload twitter ids list to a csv file in ta_partner.
The following twurl command works fine:

twurl -t -H /1.1/ton/bucket/ta_partner -X POST -A “X-TON-Expires: Sat, 10 Nov 2015 23:01:50 GMT” -A “Content-Type: text/csv” -A “Content-Length: 0” --data "100000075"
I am getting a 201 Created. with location in the header.

I am trying to upload the same from PHP CURL
I compare the OAuth , and its the same. BUT response is 403 Forbidden,


$res = $this->http("", "100000075");
function http($url, $postfields = NULL)
    $ci = curl_init();
    $headers = array(
        'Content-Type: text/csv',
        'Content-Length: 0',
        'X-TON-Content-Type: text/csv',
        'X-TON-Content-Length: 9',
        'X-TON-Expires: '. date('D, d M Y H:i:s T', strtotime("+6 day")),
    $oauth = array(
        'oauth_consumer_key' => $this->app_id,
        'oauth_nonce' => md5(mt_rand()), // random number
        'oauth_signature_method' => 'HMAC-SHA1',
        'oauth_timestamp' => time(),
        'oauth_token' => $this->access_token, // connection token
        'oauth_version' => '1.0',

    $oauth['oauth_body_hash'] = base64_encode(sha1($postfields, true));
    $oauth = $this->_createSignature($oauth, $url);
    array_push($headers, $this->_buildAuthorizationHeader($oauth));
    curl_setopt($ci, CURLOPT_USERAGENT, "OAuth gem v0.4.7");
    curl_setopt($ci, CURLOPT_HTTPHEADER, $headers);
    curl_setopt($ci, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ci, CURLOPT_HEADER, true);
    curl_setopt($ci, CURLOPT_VERBOSE, true);
    $fp = fopen('/tmp//errorlog.txt', 'w');
    curl_setopt($ci, CURLOPT_STDERR, $fp);
    curl_setopt($ci, CURLOPT_POST, true);
    curl_setopt($ci, CURLOPT_POSTFIELDS, $postfields);

    curl_setopt($ci, CURLOPT_URL, $url);
    $response = curl_exec($ci);
    $pieces  = explode("\\r\\r", $response);
    curl_close ($ci);
    return $response;

function _createSignature($oauth, $url)
    $composite_key = rawurlencode($this->app_secret) . '&' . rawurlencode($this->user_secret);
    $oauth_signature = base64_encode(hash_hmac('sha1', $this->_buildBaseString($url, 'POST', $oauth), $composite_key, true));
    $oauth['oauth_signature'] = $oauth_signature;
    return $oauth;

function _buildBaseString($baseURI, $method, &$params)
    $r = array();
    foreach($params as $key=>$value){
        $r[] = "$key=" . rawurlencode($value);
    return $method."&" . rawurlencode($baseURI) . '&' . rawurlencode(implode('&', $r));

function _buildAuthorizationHeader($oauth)
    $r = 'Authorization: OAuth ';
    $values = array();
    foreach($oauth as $key=>$value)
        $values[] = $key. '=\"' . rawurlencode($value) . '\"';
    $r .= implode(', ', $values);
    return $r;

What am i doing wrong? I am sending the exact same thing in twurl and it works.


Hi @idan_hen! Try sending the header X-TON-Expires as date('r', strtotime('+6 day')) instead of date('D, d M Y H:i:s T', strtotime("+6 day")) - there’s a difference in the timezone formatting.

Another thing: I’m not sending the headers Content-Length, X-TON-Content-Type, X-TON-Content-Length, I’m just setting the Content-Type header (I’m using the Twitter module for the Zend Framework 2).

Try removing these and see if it works.

Uploading data to TON API fails using PHP cURL

@idan_hen @majoritasdev is spot on regarding the time format.

In addition, it may be helpful take a look at this gist I just created which is an abbreviated request log of a complete TON upload session. This will show you all the headers and values you should be setting throughout the session.