I've successfully been able to query the Twitter Ads API with GET requests, but I'm trying to POST (to generate reports) and those keep failing with an UNAUTHROIZED_ACCESS "This request is not properly authenticated" error from Twitter.
I have been able to successfully run the query from Postman, so my credentials are OK. I have tried a couple of oAuth libraries (the oauth and oauth-1.0a libraries from npm) and I believe the root cause may be in the way they're generating the oAuth signature in the header.
Here's some test code which shows the problem:
let key = TWITTER_CONSUMER_API_KEY;
let secret = TWITTER_CONSUMER_API_SECRET_KEY;
let urlPost = 'https://ads-api.twitter.com/11/stats/jobs/accounts/<<accountid>>?entity=CAMPAIGN&entity_ids=i8be1&granularity=DAY&metric_groups=BILLING,ENGAGEMENT,MEDIA,WEB_CONVERSION&start_time=2022-06-12T00:00:00+10:00&end_time=2022-07-27T00:00:00+10:00&placement=ALL_ON_TWITTER';
let urlGet = 'https://ads-api.twitter.com/11/stats/jobs/accounts/<<accountid>>';
let oauth_token = <<OAUTH TOKEN>>;
let oauth_token_secret = <<OAUTH TOKEN SECRET>>;
// METHOD 1
const OAuth = require('oauth-1.0a')
const oauthConsumer = OAuth({
consumer: {
key: key,
secret: secret
},
signature_method: 'HMAC-SHA1',
hash_function(base_string, key) {
return crypto
.createHmac('sha1', key)
.update(base_string)
.digest('base64')
}
});
const authHeaderPost = oauthConsumer.toHeader(oauthConsumer.authorize({
url: urlPost,
method: 'POST',
}, {key: oauth_token, secret: oauth_token_secret}));
const authHeaderGet = oauthConsumer.toHeader(oauthConsumer.authorize({
url: urlGet,
method: 'GET',
}, {key: oauth_token, secret: oauth_token_secret}));
let initialResponse = await fetch(urlGet, {
method: 'GET',
headers: new Headers({
Authorization: authHeaderGet["Authorization"]
})
});
console.log(`[TEST] Method 1 GET Received Successful?`, initialResponse.status >= 200 && initialResponse.status <= 299);
initialResponse = await fetch(urlPost, {
method: 'POST',
headers: new Headers({
Authorization: authHeaderPost["Authorization"]
})
});
console.log(`[TEST] Method 1 POST Received Successful?`, initialResponse.status >= 200 && initialResponse.status <= 299);
// METHOD 2
import oauth from 'oauth'; // This is the npm library "oauth"
let extra_params = {};
const oAuthConsumer2 = new oauth.OAuth(
'https://api.twitter.com/oauth/request_token', 'https://api.twitter.com/oauth/access_token',
key,
secret,
'1.0', ``, 'HMAC-SHA1'
);
let orderedParametersPost= oAuthConsumer2._prepareParameters(oauth_token, oauth_token_secret, "POST", urlPost, extra_params);
let headerPost = oAuthConsumer2._buildAuthorizationHeaders(orderedParametersPost);
let orderedParametersGet= oAuthConsumer2._prepareParameters(oauth_token, oauth_token_secret, "GET", urlGet, extra_params);
let headerGet = oAuthConsumer2._buildAuthorizationHeaders(orderedParametersGet);
initialResponse = await fetch(urlGet, {
method: 'GET',
headers: new Headers({
Authorization: headerGet
})
});
console.log(`[TEST] Method 2 GET Received Successful?`, initialResponse.status >= 200 && initialResponse.status <= 299);
initialResponse = await fetch(urlPost, {
method: 'POST',
headers: new Headers({
Authorization: headerPost
})
});
console.log(`[TEST] Method 2 POST Received Successful?`, initialResponse.status >= 200 && initialResponse.status <= 299);
console.log(`[TEST ************************************************************************************************************************************************************]`);
}
The results are that both GET requests work successfully, but both POST requests fail.
Is there something I'm doing incorrectly?