I'm encountering an issue with an Axios POST request to the Threads API in my Node.js application. The request works perfectly in Postman but fails with a 400 Bad Request error when trying to post video content through the script. Below are the details of my implementation.
module.exports = async (title, url) => {
try {
// create media container
console.log(
"video_url",
url,
"text:",
title,
"access_token",
process.env.THREADS_ACCESS_TOKEN
);
const mediaContainer = await axios.post(
"https://graph.threads.net/v1.0/8063816050370756/threads",
{
media_type: "VIDEO",
video_url: url,
text: title,
access_token: process.env.THREADS_ACCESS_TOKEN, // change token in 60 days from august 25 2024
}
);
const mediaID = mediaContainer.data.id;
console.log("***** MEDIA ID *****", mediaID);
// post -> THE FOLLOWING CALL RETURN 400 BAD REQUEST
const postId = await axios.post(
"https://graph.threads.net/v1.0/8063816050370756/threads_publish",
{
creation_id: mediaID,
access_token: process.env.THREADS_ACCESS_TOKEN,
}
);
console.log(postId);
} catch (err) {
console.log("Error in uploading to Threads...moving on", err.message);
}
};
Details:
The first POST request to https://graph.threads.net/v1.0/8063816050370756/threads works correctly and returns a mediaID. The second POST request to https://graph.threads.net/v1.0/8063816050370756/threads_publish fails with a 400 Bad Request. Posting text using the same endpoint works perfectly.
Things I've Tried:
Solved. When it comes to video, the media container takes a while to be generated so I was basically trying to post it right after obtaining the media container id. I needed to implement a check on the status code.
Here's the full code:
module.exports = async (title, url) => {
try {
// create media container
console.log(
"video_url",
url,
"text:",
title,
"access_token",
process.env.THREADS_ACCESS_TOKEN
);
const mediaContainer = await axios.post(
"https://graph.threads.net/v1.0/8063816050370756/threads",
{
media_type: "VIDEO",
video_url: url,
redirect_uri: "https://oauth.pstmn.io/v1/callback",
text: title,
access_token: process.env.THREADS_ACCESS_TOKEN, // change token in 60 days from august 25 2024
}
);
const mediaID = mediaContainer.data.id;
console.log("***** MEDIA ID *****", mediaID);
// Step 2: Check the status of the media container
let status = "IN_PROGRESS";
while (status !== "FINISHED") {
console.log("Checking status for mediaID:", mediaID);
const statusCheck = await axios.get(
`https://graph.threads.net/v1.0/${mediaID}?fields=status&access_token=${process.env.THREADS_ACCESS_TOKEN}`
);
status = statusCheck.data.status;
console.log("Current status:", status);
if (status !== "FINISHED") {
// Wait for a few seconds before checking again
await new Promise((resolve) => setTimeout(resolve, 5000)); // 5-second delay
}
}
// post
const postId = await axios.post(
"https://graph.threads.net/v1.0/8063816050370756/threads_publish",
{
creation_id: mediaID,
redirect_uri: "https://oauth.pstmn.io/v1/callback",
access_token: process.env.THREADS_ACCESS_TOKEN,
}
);
console.log(postId);
} catch (err) {
if (err.response) {
console.log("Error in uploading to Threads...");
console.log("Status:", err.response.status);
console.log("Headers:", err.response.headers);
console.log("Data:", err.response.data);
} else {
console.log("Unknown error in uploading to Threads...", err.message);
}
}
};