Using Threads API to increase social media activity.
I recently created (and wrote about here) a simple program that would post a daily motivational quote on X/Twitter and Bluesky. I wanted to add to that code to also post the inspirational messages to Threads. While the Threads API at first seemed like it would prove more challenging (which is why I focused on X/Twitter and Bluesky initially), once I read through the documentation, it was fairly straightforward to implement.
Getting started
Similar to X/Twitter, in order to utilize the API for Threads you must create a developer account. Once your developer account is created (using your Facebook login information) and you are signed in, you can create your first app.
Once you click the “Create new app” button, you will follow several prompts. The first page will prompt you to name your app. On the second page, you will need to select “Access the Threads API” as the use case. On the following page, you will be asked if you have a business portfolio you want to connect to. On the final page, you will finalize the app and click “Go to dashboard”.
App customization and requirements
Once you reach your dashboard, you again will have steps to follow to finish creating the app. The first step will be to access the Threads API. In this step, you will customize the use cases for the app. Since our goal is to modify our social media bot to be able to post to Threads, make sure that “threads_basic” and “threads_publish_content” are selected.
Going back to the dashboard, the next step is “Test use cases”. Both uses we selected in the previous step need to be tested. You will use the provided Graph API Explorer in order to test the API. In order to use this though, we will first have to add ourselves as a test user. Assuming you have already created a Threads account, you will add your account by clicking “App Roles” on the bottom left of the page, a click “Roles”. Search for your Threads account and add it as a Tester.
Next, you have to accept the invitation on your Threads account by accessing the privacy settings. On the privacy page, you will click “Account”, “Website Permissions”, and select the “Invites” tab. Approve the invitation for your app.
Back on your API dashboard, you can now go back to the testing page and open the Graph API explorer. On the Graph API explorer page, be sure to change the options on the top left of the screen to “GET” and “threads.net”. Then click the “Generate Threads Access Token” button on the right hand side. A pop up will appear requesting access with your Threads account.
Once you have your access token, you can now submit your GET request by clicking the “Submit” button on the top right of the page. Once you get the results, change the request from “GET” to “POST”, and submit again. I did not bother filling in any parameters, and you will get an error code. This does not matter for testing, as the POST request still sent. We will do further testing once our API is usable in Python.
Using the dashboard
Once your testing is complete, back on the dashboard you can finally click “Finish Customization”. Note that this may not work immediately, as the tests can take up to 24 hours to register. You may have to pause this project and resume the next day. Once your app is ready, your dashboard will look like this:
On your dashboard, go to “App settings”, and select “Basic”. On this page, you need to save the App ID and App secret. We will use these later to make our API calls.
One final step we need to take is to configure OAuth. Back on your dashboard, at the bottom click “Access the Threads API”. Click “Settings”, and you will add https://oauth.pstmn.io/v1/callback
to the “Redirect Callback URLs” field, and click “save”.
Get your authorization code
We are finally done using the developer portal and the dashboard. We still need to generate an authorization code before we can submit requests through the Threads API. The following URL should be visited in your browser, replacing the [fields] with the information you saved (your “client_id” is your App id, the “redirect_url” is the redirect callback URL, and the “scopes” will be “threads_basic,threads_content_publish”. You will be redirected to a page that will display your authorization code in the URL. Copy this code down.
https://threads.net/oauth/authorize?
client_id=[CLIENT ID]&
redirect_uri=[REDIRECT URL]
&scope=[SCOPES]
&response_type=code
Request an access token and user ID
Now that you have your authorization code, along with your client ID and client secret (your app ID and app secret), it is time to request your access token and user ID. (Starting to get confused with all the different IDs, secrets, and tokens? Make sure you are clearly marking everything in your notes.)
You will use the following curl command:
curl -X POST \
https://graph.threads.net/oauth/access_token \
-F client_id=[CLIENT ID] \
-F client_secret=[CLIENT SECRET] \
-F grant_type=authorization_code \
-F redirect_uri=[REDIRECT URL] \
-F code=[AUTH CODE]
I used command prompt, and the response will be sent as a JSON containing your access token and user ID:
The returned access token is considered a “short lived” access token, meaning it will last for a couple hours before being deleted. We want to convert this to a “long lived” access token, which will be good for 60 days. To do this, we have to use curl one more time:
curl -i -X GET "https://graph.threads.net/access_token
?grant_type=th_exchange_token
&client_secret=[CLIENT SECRET]
&access_token=[SHORT_LIVED_ACCESS_TOKEN]"
Again, using command prompt, you will receive the token with an expiration of 5184000 seconds, which is 60 days.
Renewing your long lived access token
One thing to note before we finally modify our social media bot Python script: since the access token will expire in 60 days, we want to have a way to renew the token as part of our script. To do this, the API documentation directs us to use the following curl command:
curl -i -X GET "https://graph.threads.net/refresh_access_token
?grant_type=th_refresh_token
&access_token=<LONG_LIVED_ACCESS_TOKEN>"
Using this curl command as an example, we can simply write a GET command using the requests module in Python. We will remember this as we modify our existing program.
Modifying our social media bot
We can now finally begin to modify our Python script. Read my previous article for the guide on making the script, or view my GitHub to find the final project code. The very first step is to place our user ID and access token in our .env file.
Use the same method of os.getenv(“VARIABLE_NAME”) to retrieve the ID and token from the .env file.
We will take care of renewing our long lived access token first. Since it lasts for 60 days, I decided to renew it every 50 days, just to be safe. (Plus, 50 seems like a nice round number). Since we have a variable already counting since the first day of the year, I simply use the remainder calculation (%) to check if dividing the number of days by 50 returns 0. If it does (meaning it has been 50 days), then use the requests.get command to get renew our access token.
The response from the GET command will return the following JSON:
{
"access_token": "<LONG_LIVED_USER_ACCESS_TOKEN>",
"token_type": "bearer",
"expires_in": 5183944 // number of seconds until token expires
}
Using this, we can get the new access token by accessing the JSON in the response data and referencing “access_token”. We then use os.putenv(‘VARIABLE_NAME’) to store the new token in our .env file.
Now that that is done, we can write the code to post a new thread to our Threads page. According to the API documentation, this is a two step process. We first create a media container, and then we publish that container. To do this, we need the following variables:
container_url = f'https://graph.threads.net/v1.0/{THREADS_USER_ID}/threads'
publish_url = f'https://graph.threads.net/v1.0/{THREADS_USER_ID}/threads_publish'
headers = {
'Content-Type': 'application/json'
}
container_params = {
'media_type': 'TEXT',
'text': f"{quote}",
'access_token': THREADS_ACCESS_TOKEN
}
We will then use a POST command with the container URL, headers, and container parameters. The response will be a JSON containing the media container ID. We will store this ID.
{
"id": "1234567" // Threads Media Container ID
}
Using the container ID and our access token, we can use another POST command to upload our post of Threads.
The last step is to test our code. I modified the text to simply read “Test”.
With that, we have implemented code to use the Threads API to post our message on Threads, in addition to X/Twitter and Bluesky. My hope is that these daily motivational messages being posted on my accounts will in a small way help inspire someone to achieve something great every day.
The final code can be found on my GitHub. Feel free to reach out if you have any questions, and please follow me on Threads, X/Twitter, and Bluesky to receive your daily motivational message!