This document captures a workflow that can be used to test certain APIs (e.g., Engagement) from Gnip/Twitter without the requirement of an application integrated with Sign In With Twitter. These APIs require an “application-user” authentication mechanism to allow a customer’s application to make requests on behalf of a different user using what’s called 3-legged OAuth1.0. This is hard to implement through cURL, as it is much easier to manage with an application that is using Sign in With Twitter. This document is intended to help those new to 3-legged OAuth and internal testing teams be able to troubleshoot issues and test API calls.

Important Disclaimer

Oauth1.0 technology is not managed by the Gnip or Twitter teams. See OAuth1.0 documentation here

Set-Up Steps 

1. Create an Application

Create an application on Twitter at apps.twitter.com

  • Make sure to include the website URL and the callback URL on the app settings page: https://apps.twitter.com/app/< appID >/settings]
  • Note that this associates an application with the Twitter @handle you are logged in with when you create the application.
  • The Application ID will be within the URL when viewing the specific application at apps.twitter.com, for example: https://apps.twitter.com/app/< appID >/show
  • This represents the @handle and Application ID for the “Application Context”.

2. Ensure that your Application is Approved

  • The Application ID must be authorized by Gnip to access the Engagement API.

3. Create Authorization Workflow

  • When using Application-User Authorization, a separate Twitter account is authorizing the application created above. For testing, create or use a separate Twitter account that you’d like to use as the “end user” in the workflow, or the user context. This should be different from the Twitter @handle that the application you set up in step 1 was created under.
  • This “end user” represents the @handle for the “User Context”
  • Create or find Tweets from the user “User Context”

4. Review Twitter Docs & Tools


Application ID Unique identifier for the applicaton created at apps.twitter.com and found in the URL when viewing the specific Application.
User Context @userhandle Twitter user who is also a user of your app service which is requesting permission from the @userhandle
Application Context @appuserhandle User which created and is linked to the application at apps.twitter.com. Only apps created by the logged in @appuserhandle will be shown on apps.twitter.com
Customer Key Represents the requesting app within each API call.
Access Token Represents the authorized user within each API call.

Granting OAuth Privileges for the Application & User using cURL 

Step 1: Request OAuth Token

The first step is to generate an OAuth Token associated with your Application ID.
Documentation: https://dev.twitter.com/oauth/reference/post/oauth/request_token

Request URL


For testing, set the Request Query to: oauth_callback=http://localhost

Example request: (all tokens & keys have been disabled)

curl --request 'POST' 'https://api.twitter.com/oauth/request_token' --data 'oauth_callback=http%3A%2F%2Flocalhost' --header 'Authorization: OAuth oauth_consumer_key="IkXz7Xqa9qjXXX9Xc3XXe5wXp", oauth_nonce="03cf5xx643xx021dxxx858b123160010", oauth_signature="2IxXXX9f3axXXw49KgXinXX7VsU%3D", oauth_signature_method="HMAC-SHA1", oauth_timestamp="1456270002", oauth_version="1.0"' --verbose

Example Response (all tokens & keys have been disabled)


Save the data in the response somewhere where you can access it later.

Step 2: Redirect Your Test User to Sign In With Twitter

Documentation: https://dev.twitter.com/oauth/reference/get/oauth/authenticate

Using the oauth_token value that was returned in the previous step, construct a URL like the following, and put it into a new, incognito browser window:

Example “Request” URL (all tokens & keys have been disabled)


When you go to this URL, you will be taken to a Twitter login screen. Login with the test Twitter account that you created in step 2 of the set-up steps above. Once you click Sign In, you’ll be directed to what looks like an error page (but that’s because we set the oauth_callback to local host). Note the presence of an oauth_token and oauth_verifier in the URL. Copy and paste those somewhere safe.

Example “Result” URL (all tokens & keys have been disabled)


Save the data in the response somewhere where you can access it later.

Step 3: Convert the token and verifier obtained in the previous step into an OAuth token and secret

Now that you have a token and verifier specific to the user, you’ll need to convert that into an oauth_token and oauth_token_secret that you will use to make a request to one of the Insights APIs on behalf of the user.

To do this, make a call to the oauth/access_token endpoint using the token (N0NkhwAXXXXXhWP3XXABUxB0xX4) and verifier (P34n2xiSZgX9XXXX7eVbI7hxKxxXduJR) received in the previous step.

Documentation: https://dev.twitter.com/oauth/reference/post/oauth/access_token

Request URL


Example Request (all tokens & keys have been disabled)

curl --request 'POST' 'https://api.twitter.com/oauth/access_token' --data 'oauth_token=N0NkhwAXXXXXhWP3XXABUxB0xX4&oauth_verifier=P34n2xiSZgX9XXXX7eVbI7hxKxxXduJR' --header 'Authorization: OAuth oauth_consumer_key="IkXz7Xqa9qjXXX9Xc3XXe5wXp", oauth_nonce="ed56341e15a963d0ff4f994f08b833c4", oauth_signature="PXXavJaXX6ZwS%2FXXXw5z%2BWohXXX%3D", oauth_signature_method="HMAC-SHA1", oauth_timestamp="1456271000", oauth_version="1.0"' --verbose

Example Response (all tokens & keys have been disabled)


Save the data in the response somewhere where you can access it later.

Step 4: Make an Authenticated Request On Behalf of Your User

Now you have an oauth_token and oauth_token_secret that you can use to make a request to the Engagement.

In order to do that, build a request to one of the APIs using OAuth1.0. The easiest way to do this is through an application like Postman or Paw, however you could also run this using cURL:

Engagement API

Example Request (all tokens & keys have been disabled)

curl --request 'POST' 'https://data-api.twitter.com/insights/engagement/totals' -H 'Content-Type: application/json' -H 'Accept-Encoding: gzip' --header 'Authorization: OAuth oauth_consumer_key="IkXz7Xqa9qjXXX9Xc3XXe5wXp", oauth_nonce="ebd833124f910e752a984fdcba774223", oauth_signature="Mt66S592Jrxl9%2Fg1mZ66oHPYJec%3D", oauth_signature_method="HMAC-SHA1", oauth_timestamp="1456468040", oauth_token="708815894368888784-Fm0xXqtc7CGxxXnlaDeXXXoXd0e2XzH", oauth_version="1.0"' --verbose --data '{"tweet_ids":["641302779852488704"],"engagement_types":["favorites"],"groupings": {"group1":{"group_by":["tweet.id","engagement.type"]}}}'

Example Response



Some possible errors & debugging:

{"errors":["The Application ID is not authorized."]}

Double check that your AppID making the request has been approved by the Gnip team for the endpoint.

{"errors":["error code: 3040, message: Bad signature"]}

Double check the syntax and paraemters/arguments in the call including the Authorization, Content-Type: application/json, and data format JSON. Refresh the nonce, signature or timestamp.

{"errors":["engagement_types: [impressions] is not one of [favorites,retweets,replies]"]}

Double check that you are querying for available engagement types for the endpoint.

{"errors":["Forbidden to access tweets for author id 2244994945: 689888120578412544"]}

Auth Token for Application-User has expired, is incorrect or access has not been granted for your app to query Tweets by the Author 2244994945. See GET users/show for more details.

Rate Limit

All steps of 3-legged Application-user OAuth are rate limited.