Receiving 401 Unauthorized for ads-api.twitter.com/2/stats/accounts/


#21

@juanshishido can you elaborate a little on the “improper encoding” here. I figured that it had something to do with how I was encoding my ISO 8601 timestamps (and therefore the signature) because I, like Matias, tried doing it with YYYY-mm-dd dates, which worked. But when I do encode my query string params, I still get a 401. This makes me feel like my signing method is correct (because I can get data when date is formatted like YYYY-mm-dd), but I’m handling the ISO 8601 case incorrectly.

URL looks like:

https://ads-api.twitter.com/4/stats/accounts/<ACCOUNT_ID>?entity=CAMPAIGN&metric_groups=ENGAGEMENT%2CBILLING&granularity=HOUR&placement_type=ALL_ON_TWITTER&entity_ids=<CAMPAIGN_ID>&start_time=2019-02-11T00%3A00%3A00Z&end_time=2019-02-12T00%3A00%3A00Z

#22

@wpercy I’m not sure whether you’re using third-party OAuth library or own logic, but your explanation is actually indicating the problem is around signing method. Please make sure you’re encoding the URI before you pass it to the OAuth library or own signing logic. Otherwise, it makes signature mismatch.


#23

Right, that isn’t answering my question though. I’m using my own signing method (the reasons for this are wildly elaborate, and trust me, I wish I didn’t have to). There are two steps during the signing process in which query string parameters are encoded.

when creating the parameter string:

  1. Percent encode every key and value that will be signed.

and when re-encoding the parameter string before appending it to the signature base string

  1. Percent encode the parameter string and append it to the output string.

So, when I’m passing in the URI to the first step, should the values of start_time and end_time already be encoded (as above) or should they be passed in unencoded, and only be encoded twice?

It should also be noted that when I make a request with the URL:

https://ads-api.twitter.com/4/stats/accounts/<ACCOUNT_ID>?entity=CAMPAIGN&metric_groups=ENGAGEMENT,BILLING&granularity=HOUR&placement=ALL_ON_TWITTER&start_time=2019-02-11&end_time=2019-02-12&entity_ids=<CAMPAIGN_ID>

it returns successfully, even through I didn’t encode the comma (,) in metric_groups=ENGAGEMENT,BILLING. Can you explain why that would return without being pre-encoded, but the datetime won’t?