threads-api-ai
v1.1.0
Published
A Node.js client library for the Facebook Threads API with TypeScript support
Maintainers
Readme
threads-api-ai
A Node.js client library for the Facebook Threads API with full TypeScript support.
Features
- ✅ OAuth 2.0 Authentication - Complete authentication flow with short-lived and long-lived tokens
- ✅ User Profile API - Get user profile information and threads
- ✅ Publishing API - Create and publish text, image, video, and carousel posts
- ✅ TypeScript Support - Full type definitions for all API methods
- ✅ Promise-based - Modern async/await API
- ✅ Error Handling - Comprehensive error handling with detailed messages
- 🚧 More features coming soon - Insights, replies, webhooks, and more
Installation
npm install threads-api-aiPrerequisites
Before using this library, you need to:
- Create a Threads app in the Meta Developer Portal
- Get your App ID and App Secret
- Configure OAuth redirect URI in your app settings
- Request necessary permissions/scopes
Quick Start
import ThreadsAPI from 'threads-api-ai';
// Initialize the client
const client = new ThreadsAPI({
appId: 'YOUR_APP_ID',
appSecret: 'YOUR_APP_SECRET',
redirectUri: 'https://yourapp.com/callback'
});
// Step 1: Generate authorization URL
const authUrl = client.auth.getAuthorizationUrl([
'threads_basic',
'threads_content_publish'
], 'optional-state-for-csrf');
console.log('Visit this URL to authorize:', authUrl);
// Step 2: After user authorizes, exchange code for tokens
const code = 'CODE_FROM_CALLBACK';
const tokens = await client.auth.completeAuthFlow(code);
console.log('Access Token:', tokens.access_token);
console.log('Expires in:', tokens.expires_in, 'seconds');Authentication Guide
The Threads API uses OAuth 2.0 for authentication. This library provides methods for the complete authentication flow.
Available Scopes
threads_basic- Read basic profile informationthreads_content_publish- Publish content on behalf of the userthreads_manage_insights- Read insights and analyticsthreads_manage_replies- Manage replies to poststhreads_read_replies- Read replies to posts
Complete Authentication Flow
import ThreadsAPI from 'threads-api-ai';
const client = new ThreadsAPI({
appId: process.env.THREADS_APP_ID!,
appSecret: process.env.THREADS_APP_SECRET!,
redirectUri: 'https://yourapp.com/auth/callback'
});
// 1. Generate authorization URL
const authUrl = client.auth.getAuthorizationUrl([
'threads_basic',
'threads_content_publish'
], 'your-random-state-string');
// Redirect user to authUrl...
// User authorizes and is redirected back to your callback URL with a code
// 2. Exchange code for tokens (this method handles both short and long-lived tokens)
const tokens = await client.auth.completeAuthFlow(code);
// Save tokens.access_token securely - it's valid for ~60 daysManual Token Exchange
If you prefer to handle the token exchange manually:
// Get short-lived token (valid for ~1 hour)
const shortToken = await client.auth.getAccessToken(code);
// Exchange for long-lived token (valid for ~60 days)
const longToken = await client.auth.getLongLivedToken(shortToken.access_token);Refreshing Long-Lived Tokens
Long-lived tokens expire after ~60 days. Refresh them before they expire:
const refreshedToken = await client.auth.refreshLongLivedToken(
currentLongLivedToken
);
// Save the new token - it's valid for another ~60 daysExpress.js Example
Here's a complete example using Express.js:
import express from 'express';
import ThreadsAPI from 'threads-api-ai';
const app = express();
const client = new ThreadsAPI({
appId: process.env.THREADS_APP_ID!,
appSecret: process.env.THREADS_APP_SECRET!,
redirectUri: 'http://localhost:3000/auth/callback'
});
// Route to initiate OAuth
app.get('/auth/threads', (req, res) => {
const authUrl = client.auth.getAuthorizationUrl([
'threads_basic',
'threads_content_publish'
], req.session.state); // Use session-based state for security
res.redirect(authUrl);
});
// OAuth callback route
app.get('/auth/callback', async (req, res) => {
try {
const { code, state } = req.query;
// Verify state matches (CSRF protection)
if (state !== req.session.state) {
throw new Error('State mismatch');
}
// Complete auth flow and get long-lived token
const tokens = await client.auth.completeAuthFlow(code as string);
// Save tokens securely (e.g., in database)
req.session.accessToken = tokens.access_token;
res.send('Authentication successful!');
} catch (error) {
console.error('Auth error:', error);
res.status(500).send('Authentication failed');
}
});
app.listen(3000);User Profile API
Once you have an access token, you can retrieve user profile information and threads.
Get User Profile
// Get the authenticated user's profile
const profile = await client.profile.getProfile(accessToken);
console.log('User ID:', profile.id);
console.log('Username:', profile.username);
console.log('Profile Picture:', profile.threads_profile_picture_url);
console.log('Bio:', profile.threads_biography);
// Get specific fields only
const customProfile = await client.profile.getProfile(
accessToken,
['id', 'username'] // Only fetch these fields
);Get User's Threads
// Get the authenticated user's threads
const threads = await client.profile.getUserThreads(accessToken);
console.log('User threads:', threads.data);
// Get threads with custom fields and limit
const customThreads = await client.profile.getUserThreads(
accessToken,
'me', // or specific user ID
['id', 'text', 'permalink', 'timestamp'], // fields to retrieve
10 // limit
);Get Single Thread
// Get a specific thread by ID
const thread = await client.profile.getThread(accessToken, 'THREAD_ID');
console.log('Thread text:', thread.text);
console.log('Permalink:', thread.permalink);
console.log('Media URL:', thread.media_url);Publishing API
Create and publish text posts, images, videos, and carousels.
Publish a Text Post
// Simple text post (all in one step)
const result = await client.publishing.createAndPublishThread(
accessToken,
'me',
{
media_type: 'TEXT',
text: 'Hello from Threads API! 👋'
}
);
console.log('Published thread ID:', result.id);Publish an Image Post
// Post with image
const imagePost = await client.publishing.createAndPublishThread(
accessToken,
'me',
{
media_type: 'IMAGE',
image_url: 'https://example.com/image.jpg',
text: 'Check out this image!'
}
);Publish a Video Post
// Post with video
const videoPost = await client.publishing.createAndPublishThread(
accessToken,
'me',
{
media_type: 'VIDEO',
video_url: 'https://example.com/video.mp4',
text: 'Watch this video!'
}
);Publish a Carousel Post
// Create carousel items first
const item1 = await client.publishing.createCarouselItem(
accessToken,
'me',
{ image_url: 'https://example.com/image1.jpg' }
);
const item2 = await client.publishing.createCarouselItem(
accessToken,
'me',
{ image_url: 'https://example.com/image2.jpg' }
);
// Create and publish carousel
const carousel = await client.publishing.createAndPublishThread(
accessToken,
'me',
{
media_type: 'CAROUSEL',
carousel_item_ids: [item1.id, item2.id],
text: 'Swipe to see more!'
}
);Reply to a Thread
// Reply to another thread
const reply = await client.publishing.createAndPublishThread(
accessToken,
'me',
{
media_type: 'TEXT',
text: 'This is a reply!',
reply_to_id: 'PARENT_THREAD_ID'
}
);Control Who Can Reply
// Control reply permissions
const post = await client.publishing.createAndPublishThread(
accessToken,
'me',
{
media_type: 'TEXT',
text: 'Only people I follow can reply',
reply_control: 'accounts_you_follow' // or 'everyone' or 'mentioned_only'
}
);Manual Two-Step Publishing
If you need more control, you can manually create and publish in two steps:
// Step 1: Create thread container
const container = await client.publishing.createThread(
accessToken,
'me',
{
media_type: 'TEXT',
text: 'My post'
}
);
// Step 2: Publish the container
const published = await client.publishing.publishThread(
accessToken,
'me',
{
creation_id: container.id
}
);
console.log('Published thread ID:', published.id);Check Publishing Limits
// Get publishing rate limit info
const limits = await client.publishing.getPublishingLimit(accessToken);
console.log('Quota usage:', limits.data);Error Handling
The library throws detailed errors with API error codes and messages:
try {
const tokens = await client.auth.getAccessToken(code);
} catch (error) {
console.error(error.message);
// Example: "Threads API Error (190): Invalid OAuth access token"
}API Reference
ThreadsAPI
Main client class.
Constructor
new ThreadsAPI(config: ThreadsAPIConfig)Parameters:
config.appId(string) - Your Threads App IDconfig.appSecret(string) - Your Threads App Secretconfig.redirectUri(string) - OAuth redirect URIconfig.apiVersion(string, optional) - API version (default: 'v1.0')
Properties
auth- Authentication handlerprofile- User profile handlerpublishing- Publishing handler
ThreadsAuth
Authentication handler (accessible via client.auth).
Methods
getAuthorizationUrl(scopes, state?)
Generate OAuth authorization URL.
Parameters:
scopes(ThreadsScope[]) - Array of permission scopesstate(string, optional) - State parameter for CSRF protection
Returns: Authorization URL (string)
getAccessToken(code)
Exchange authorization code for short-lived access token.
Parameters:
code(string) - Authorization code from callback
Returns: Promise
getLongLivedToken(shortLivedToken)
Exchange short-lived token for long-lived token.
Parameters:
shortLivedToken(string) - Short-lived access token
Returns: Promise
refreshLongLivedToken(longLivedToken)
Refresh a long-lived token.
Parameters:
longLivedToken(string) - Current long-lived token
Returns: Promise
completeAuthFlow(code)
Complete full OAuth flow (recommended method).
Parameters:
code(string) - Authorization code from callback
Returns: Promise
ThreadsProfile
User profile handler (accessible via client.profile).
Methods
getProfile(accessToken, fields?)
Get the authenticated user's profile.
Parameters:
accessToken(string) - User's access tokenfields(string[], optional) - Fields to retrieve (default: id, username, threads_profile_picture_url, threads_biography)
Returns: Promise
getUserThreads(accessToken, userId?, fields?, limit?)
Get a user's threads.
Parameters:
accessToken(string) - User's access tokenuserId(string, optional) - User ID (default: 'me')fields(string[], optional) - Fields to retrievelimit(number, optional) - Number of threads (default: 25, max: 100)
Returns: Promise
getThread(accessToken, threadId, fields?)
Get a specific thread by ID.
Parameters:
accessToken(string) - User's access tokenthreadId(string) - Thread IDfields(string[], optional) - Fields to retrieve
Returns: Promise
ThreadsPublishing
Publishing handler (accessible via client.publishing).
Methods
createThread(accessToken, userId, params)
Create a thread container (step 1 of publishing).
Parameters:
accessToken(string) - User's access tokenuserId(string) - User ID (default: 'me')params(CreateThreadParams) - Thread creation parameters
Returns: Promise
publishThread(accessToken, userId, params)
Publish a thread container (step 2 of publishing).
Parameters:
accessToken(string) - User's access tokenuserId(string) - User ID (default: 'me')params(PublishThreadParams) - Publishing parameters
Returns: Promise
createAndPublishThread(accessToken, userId, params)
Create and publish a thread in one step (convenience method).
Parameters:
accessToken(string) - User's access tokenuserId(string) - User ID (default: 'me')params(CreateThreadParams) - Thread creation parameters
Returns: Promise
createCarouselItem(accessToken, userId, params)
Create a carousel item for carousel posts.
Parameters:
accessToken(string) - User's access tokenuserId(string) - User ID (default: 'me')params(CreateCarouselItemParams) - Carousel item parameters
Returns: Promise
getPublishingLimit(accessToken, userId?)
Get the publishing limit for the user.
Parameters:
accessToken(string) - User's access tokenuserId(string, optional) - User ID (default: 'me')
Returns: Promise
TypeScript Types
All types are exported and available for use:
import {
ThreadsAPIConfig,
ThreadsScope,
AccessTokenResponse,
LongLivedTokenResponse,
RefreshTokenResponse,
ThreadsUserProfile,
MediaType,
CreateThreadParams,
CreateThreadResponse,
PublishThreadParams,
PublishThreadResponse,
CreateCarouselItemParams,
Thread
} from 'threads-api-ai';Roadmap
- [x] OAuth 2.0 Authentication
- [x] User Profile API
- [x] Publishing API (create posts)
- [x] Text posts
- [x] Image posts
- [x] Video posts
- [x] Carousel posts
- [x] Reply control
- [x] Publishing limits
- [ ] Media API (upload images/videos)
- [ ] Insights API (analytics)
- [ ] Replies API (manage comments)
- [ ] Webhooks support
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
License
MIT
Support
For issues and questions, please use the GitHub Issues page.
Disclaimer
This is an unofficial library and is not affiliated with Meta Platforms, Inc.
