This guide walks through everyday tasks with Titen, from connecting your first Threads account to scheduling posts and reading analytics.
New here? Follow the Deployment Guide first to get the server running.
- Web Dashboard
- Connecting a Threads Account
- Creating Posts
- Scheduling Posts
- Managing Comments
- Viewing Analytics
- Uploading Media
- CLI Quick Reference
- MCP / AI Agent Integration
Titen includes a built-in web dashboard served at the root URL.
- Navigate to
http://your-server:7845/login(or your domain). - Enter your API key (the value of
TITEN_API_KEY). - Click Login. A session cookie is set (valid for 7 days).
Dev mode: If
TITEN_API_KEYis not set, the dashboard is accessible without login. Never use this in production.
| Section | URL | Purpose |
|---|---|---|
| Accounts | /admin/accounts |
Manage connected Threads accounts |
| Posts | /admin/posts |
View and create posts |
| Schedules | /admin/schedules |
View and create scheduled posts |
| Comments | /admin/comments |
Browse comment sentiment per post |
| Analytics | /admin/analytics |
Performance metrics over time |
Titen uses the Threads Graph API. You need a Threads account and a Meta for Developers app.
- Go to Meta for Developers.
- Create a new app (type: Business).
- Add the Threads API product.
- Navigate to Threads → API Setup to find your App ID and App Secret.
- Generate a long-lived access token via the OAuth flow or the Token Generator tool.
# Set your API key (if auth is enabled)
export TITEN_API_KEY=your-key
export TITEN_URL=http://localhost:7845
# Add the account
titen account add mybrand \
--access-token "YOUR_LONG_LIVED_TOKEN" \
--user-id "THREADS_USER_ID" \
--expires-at "2026-12-01T00:00:00Z"Alternatively, use the web dashboard:
- Go to Accounts → click Add Account.
- Enter username, access token, and optional user ID.
- Click Save.
The cleanest method, no manual token copying:
- Set these environment variables on the server:
THREADS_APP_ID=your_app_id THREADS_APP_SECRET=your_app_secret THREADS_REDIRECT_URI=https://your-domain.com/auth/callback - From the dashboard Accounts page, click Connect via OAuth.
Or call the API:
curl -X POST http://localhost:7845/api/threads/oauth/initiate \ -H "X-API-Key: your-key" - You'll be redirected to Threads to authorize. After approval, the token is stored automatically.
# List all accounts
titen account list
# Check token validity
titen token-check
# Fetch profile (confirms API connectivity)
titen account status <account_id>| Type | Fields Required | Notes |
|---|---|---|
TEXT |
text |
Up to 500 characters (Threads limit) |
IMAGE |
image_url or uploaded media |
One image per post |
VIDEO |
video_url |
Processed by Threads (may take up to 2 min) |
# Text post (published immediately)
titen post create mybrand --text "Hello from Titen!"
# Image post
titen post create mybrand \
--media-type IMAGE \
--image-url "https://example.com/photo.jpg" \
--text "Check this out"
# Video post
curl -X POST http://localhost:7845/api/posts \
-H "X-API-Key: your-key" \
-H "Content-Type: application/json" \
-d '{
"account_id": 1,
"media_type": "VIDEO",
"video_url": "https://example.com/video.mp4"
}'# Text post
curl -X POST http://localhost:7845/api/posts \
-H "X-API-Key: your-key" \
-H "Content-Type: application/json" \
-d '{
"account_id": 1,
"media_type": "TEXT",
"text": "Hello from Titen!"
}'
# Image post
curl -X POST http://localhost:7845/api/posts \
-H "X-API-Key: your-key" \
-H "Content-Type: application/json" \
-d '{
"account_id": 1,
"media_type": "IMAGE",
"image_url": "https://example.com/photo.jpg"
}'
# Video post
curl -X POST http://localhost:7845/api/posts \
-H "X-API-Key: your-key" \
-H "Content-Type: application/json" \
-d '{
"account_id": 1,
"media_type": "VIDEO",
"video_url": "https://example.com/video.mp4"
}'- Go to Posts → click New Post.
- Select account, choose media type, enter text or URL.
- Click Publish for immediate posting.
The scheduler runs as a background task inside the server. It checks for due schedules every 60 seconds (configurable via TITEN_SCHEDULER_INTERVAL_SECS).
# Schedule a text post for tomorrow at 9 AM
titen schedule add mybrand \
--text "Good morning!" \
--at "2026-08-05T09:00:00+07:00"
# Schedule an image post
titen schedule add mybrand \
--text "Product launch!" \
--media-type IMAGE \
--at "2026-08-05T14:00:00+07:00"curl -X POST http://localhost:7845/api/schedules \
-H "X-API-Key: your-key" \
-H "Content-Type: application/json" \
-d '{
"account_id": 1,
"media_type": "TEXT",
"text": "Scheduled post content",
"scheduled_at": "2026-08-05T09:00:00+07:00"
}'# List all schedules
titen schedule list
# Filter by account or status
titen schedule list --account 1 --status pending
# View upcoming (next 10)
titen schedule upcoming
# Cancel a schedule
titen schedule cancel <schedule_id>Schedule created (status: pending)
│
▼
Scheduler tick (every 60s)
│
├── claim_schedule() - atomic UPDATE WHERE status='pending'
│ (prevents double-posting if running multiple instances)
│
├── status → processing
│
├── Create media container on Threads API
│
├── Wait for container ready:
│ • TEXT: immediate
│ • IMAGE: ~30 seconds
│ • VIDEO: up to 4.5 minutes (polled, timeout-bounded)
│
├── Publish container
│
└── status → published (or failed on error)
Comments are not synced automatically. Fetch them on demand:
# Fetch latest comments for a post
titen comment fetch <post_id>
# List stored comments
titen comment list <post_id># Analyze sentiment of stored comments
titen comment sentiment <post_id>
# Summary across a post
titen analytics sentiment-summary <post_id>The sentiment engine is pluggable:
| Engine | Env Var Value | Description |
|---|---|---|
| Keyword (default) | keyword |
Simple keyword-based scoring, no deps |
| ONNX | onnx |
Local ML model (requires model file) |
| LLM | llm |
Uses an LLM API (requires API key) |
| Custom API | custom_api |
Your own sentiment endpoint |
Set via: TITEN_SENTIMENT_ENGINE=keyword
# Fetch and store insights from Threads
titen post insights <post_id>
# Time-series trend for a post
titen analytics trend <post_id># Summary for an account (date range)
titen analytics posts mybrand --from 2026-08-01 --to 2026-08-31# Post analytics
curl http://localhost:7845/api/analytics/posts?account_id=1\&from=2026-08-01\&to=2026-08-31 \
-H "X-API-Key: your-key"
# Trend for a specific post
curl http://localhost:7845/api/analytics/posts/42/trend \
-H "X-API-Key: your-key"Media uploads require S3-compatible storage to be configured.
Set these environment variables:
TITEN_S3_ENDPOINT=https://s3.example.com
TITEN_S3_BUCKET=titen-media
TITEN_S3_REGION=us-east-1
TITEN_S3_ACCESS_KEY=your-access-key
TITEN_S3_SECRET_KEY=your-secret-key
TITEN_S3_PUBLIC_URL=https://cdn.example.com # optional, for public accessMinIO works great for self-hosted setups. See the Deployment Guide.
titen media upload /path/to/image.jpg --content-type image/jpeg
titen media list
titen media delete <media_id>curl -X POST http://localhost:7845/api/media \
-H "X-API-Key: your-key" \
-F "file=@/path/to/image.jpg"titen serve [--host 0.0.0.0] [--port 7845] [--mcp]
# Accounts
titen account list
titen account add <username> --access-token <TOKEN> [--user-id <ID>] [--expires-at <ISO>]
titen account remove <id>
titen account refresh <id>
titen account status <id>
titen token-check
# Posts
titen post create <account> --text <TEXT> [--media-type TEXT|IMAGE] [--image-url <URL>]
titen post delete <post_id>
titen post insights <post_id>
# Schedules
titen schedule add <account> --text <TEXT> --at <ISO8601> [--media-type TEXT|IMAGE]
titen schedule list [--account <id>] [--status <status>]
titen schedule cancel <id>
titen schedule upcoming
# Comments
titen comment fetch <post_id>
titen comment list <post_id>
titen comment sentiment <post_id>
# Analytics
titen analytics posts <account> [--from <date>] [--to <date>]
titen analytics trend <post_id>
titen analytics sentiment-summary <post_id>
# Media
titen media list
titen media upload <file_path> [--content-type <mime>]
titen media delete <id>
Titen ships with an MCP server (titen-mcp) for integration with AI tools.
Add to ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) or ~/.config/Claude/claude_desktop_config.json (Linux):
{
"mcpServers": {
"titen": {
"command": "/path/to/titen-mcp",
"env": {
"TITEN_DB_PATH": "/path/to/titen.db"
}
}
}
}Add to your MCP settings (Settings → MCP):
{
"mcp": {
"titen": {
"command": "/path/to/titen-mcp",
"env": {
"TITEN_DB_PATH": "/path/to/titen.db"
}
}
}
}| Tool | Description |
|---|---|
list_accounts |
List all Threads accounts |
get_account |
Get account by ID |
create_post |
Create and publish a post |
schedule_post |
Schedule a post |
list_schedules |
List scheduled posts |
cancel_schedule |
Cancel a schedule |
fetch_comments |
Fetch comments from Threads |
get_post_sentiment |
Analyze comment sentiment |
get_post_analytics |
Analytics for a post |
get_account_analytics |
Analytics summary per account |
upload_media |
Upload media to S3 |
refresh_token |
Refresh an account token |
check_tokens |
Batch token expiry check |
"Use titen to post 'Hello world from my AI assistant!' to my account @mybrand."
Claude will call create_post with the appropriate parameters.