Threads Publishing

Learn how to connect Threads accounts and publish text posts, photos, carousels, videos, and long-form threads.

Connecting Threads Account

Prerequisites

Connection Steps

  1. Click the "Connect Threads" button on the dashboard
  2. Log in to Threads (if not already logged in)
  3. Authorize Boring to access your Threads account
  4. Grant the required permissions:
    • threads_basic - Basic account information
    • threads_content_publish - Publish content
    • threads_manage_replies - Create and manage thread replies (required for long-form threads)
    • threads_manage_insights - Access analytics and insights
    • threads_read_replies - Read replies to posts
  5. Click "Authorize"

Your Threads account will appear in the Authorized Accounts list with:

Token Information

Note: Unlike Instagram, Threads tokens auto-refresh! You shouldn't need to manually reconnect.

Supported Content Types

Threads supports the most diverse content types:

Type Description Media Count Text Format Example
Text Text-only post 0 String Quick thoughts, updates
Photo Single image 1 String Image with caption
Carousel Multiple images 2-20 String Photo series, guides
Video Video content 1 String Short videos, clips
Thread Long-form thread 0-1 Array Multi-post stories

Key Feature: Threads is the only platform that supports:

Publishing Examples

1. Text-Only Post

{
  "post": {
    "accountId": "your-threads-account-id",
    "content": {
      "text": "Just launched our new feature! Check it out πŸš€",
      "mediaUrls": [],
      "platform": "threads"
    },
    "target": {
      "targetType": "threads"
    }
  }
}

Result: Simple text post on Threads.

Text Requirements:

2. Single Photo Post

{
  "post": {
    "accountId": "your-threads-account-id",
    "content": {
      "text": "Beautiful morning view πŸŒ…",
      "mediaUrls": ["https://example.com/morning.jpg"],
      "platform": "threads"
    },
    "target": {
      "targetType": "threads"
    }
  }
}

Result: Image post with caption on Threads.

Photo Requirements:

3. Carousel Post

{
  "post": {
    "accountId": "your-threads-account-id",
    "content": {
      "text": "Our journey in photos πŸ“Έ",
      "mediaUrls": [
        "https://example.com/photo1.jpg",
        "https://example.com/photo2.jpg",
        "https://example.com/photo3.jpg",
        "https://example.com/photo4.jpg",
        "https://example.com/photo5.jpg"
      ],
      "platform": "threads"
    },
    "target": {
      "targetType": "threads"
    }
  }
}

Result: Carousel post with multiple swipeable images.

Carousel Requirements:

4. Video Post

{
  "post": {
    "accountId": "your-threads-account-id",
    "content": {
      "text": "Quick demo of our new app feature πŸŽ₯",
      "mediaUrls": ["https://example.com/demo.mp4"],
      "platform": "threads"
    },
    "target": {
      "targetType": "threads"
    }
  }
}

Result: Video post on Threads.

Video Requirements:

Note: Video processing is asynchronous and may take a few minutes.

5. Long-Form Thread (Multi-Post)

This is the most powerful feature of Threads!

{
  "post": {
    "accountId": "your-threads-account-id",
    "content": {
      "text": [
        "Let me tell you a story about building our product 🧡",
        "It all started with a simple idea: make social media publishing easier for developers.",
        "We researched the pain points: token management, platform differences, complex APIs.",
        "So we built Boring: one API to rule them all. Simple, secure, and reliable.",
        "Today we're proud to support Facebook, Instagram, and Threads. More platforms coming soon!",
        "Thank you for being part of our journey πŸ™"
      ],
      "mediaUrls": [],
      "platform": "threads"
    },
    "target": {
      "targetType": "threads"
    }
  }
}

Result: A connected thread with 6 posts, each replying to the previous one.

Thread Requirements:

Note: Requires threads_manage_replies permission!

Text Format Detection

Boring API automatically detects the post type based on the text field:

Text Format Result
"text": "string" Single post (text, photo, carousel, or video)
"text": ["s1", "s2"] Long-form thread (multi-post)

Examples:

# Single post
{"text": "Hello world", "mediaUrls": []}

# Single post with photo
{"text": "Check this out", "mediaUrls": ["image.jpg"]}

# Carousel
{"text": "Photo series", "mediaUrls": ["img1.jpg", "img2.jpg"]}

# Long-form thread (6 posts)
{"text": ["Post 1", "Post 2", "Post 3", "Post 4", "Post 5", "Post 6"], "mediaUrls": []}

API Request Format

Full Example (Python) - Long-Form Thread

import requests

API_URL = "https://boring.aiagent-me.com/v2/posts"
API_KEY = "boring_xxxxxxxxxxxxx"
ACCOUNT_ID = "your-threads-account-id"

# Create a long-form thread
thread_content = [
    "🚨 Product Launch Alert! 🚨",

    "We're excited to announce Boring API v3.0 with Threads integration!",

    "What's new:\nβœ… Text-only posts\nβœ… Carousels up to 20 images\nβœ… Long-form threads\nβœ… Auto token refresh",

    "Why Threads?\n\nThreads is perfect for storytelling, updates, and engaging with your audience in a conversational way.",

    "Getting started is easy:\n1. Sign in\n2. Connect Threads\n3. Generate API key\n4. Start publishing",

    "Check out our docs at boring-doc.aiagent-me.com for examples and guides!",

    "What would you like to see next? Reply and let us know! πŸ’¬"
]

post_data = {
    "post": {
        "accountId": ACCOUNT_ID,
        "content": {
            "text": thread_content,  # Array of strings = thread
            "mediaUrls": [],
            "platform": "threads"
        },
        "target": {
            "targetType": "threads"
        }
    }
}

headers = {
    "boring-api-key": API_KEY,
    "Content-Type": "application/json"
}

response = requests.post(API_URL, headers=headers, json=post_data)
result = response.json()

if result["success"]:
    print(f"Thread published! Main post ID: {result['data']['post_id']}")
    print(f"Total posts: {result['data']['thread_count']}")
else:
    print(f"Error: {result['message']}")

Success Response (Thread)

{
  "success": true,
  "message": "Post published successfully",
  "data": {
    "post_id": "17885748657253466",
    "post_type": "thread",
    "platform": "threads",
    "page_name": "your_username",
    "thread_count": 7,
    "post_ids": [
      "17885748657253466",
      "17885748657253467",
      "17885748657253468",
      "17885748657253469",
      "17885748657253470",
      "17885748657253471",
      "17885748657253472"
    ],
    "published_at": "2025-01-20T10:30:00Z"
  }
}

Media URL Requirements

Same as other platforms:

Supported formats:

Best Practices

1. Long-Form Threads

Structure your thread:

Example thread structure:

thread = [
    "🧡 Why [topic] matters (thread)",  # Hook
    "First, let's define [topic]...",    # Context
    "The main problem is...",            # Problem
    "Here's how we solve it...",         # Solution
    "Real example: [case study]",        # Evidence
    "Key takeaway: [summary]",           # Summary
    "What do you think? [CTA]"           # Engagement
]

2. Text-Only Posts

Perfect for:

Tips:

3. Carousels

Threads supports up to 20 images!

Use cases:

4. Video Content

Best practices:

5. Engagement

Threads is built for conversation:

Troubleshooting

Common Errors

Error: "Invalid text format for thread"

Error: "Missing threads_manage_replies permission"

Error: "Token expired"

Error: "Carousel size exceeds limit"

Error: "Text exceeds maximum length"

Publishing Delays

Threads posts may take time to process:

The API handles retries automatically.

Advanced Features

Dynamic Thread Generation

Generate threads from long text:

def split_into_thread(long_text, max_chars=450):
    """Split long text into thread posts"""
    sentences = long_text.split('. ')
    posts = []
    current_post = ""

    for sentence in sentences:
        if len(current_post) + len(sentence) < max_chars:
            current_post += sentence + '. '
        else:
            posts.append(current_post.strip())
            current_post = sentence + '. '

    if current_post:
        posts.append(current_post.strip())

    return posts

# Usage
article = "Your very long article text here..."
thread_posts = split_into_thread(article)

post_data = {
    "post": {
        "accountId": ACCOUNT_ID,
        "content": {
            "text": thread_posts,  # Automatically becomes a thread
            "mediaUrls": [],
            "platform": "threads"
        },
        "target": {"targetType": "threads"}
    }
}

Thread with Images

Add an image to the first post of a thread:

post_data = {
    "post": {
        "accountId": ACCOUNT_ID,
        "content": {
            "text": [
                "Here's our announcement πŸŽ‰",
                "This feature has been requested by many users.",
                "We're rolling it out today!"
            ],
            "mediaUrls": ["https://example.com/announcement.jpg"],  # Only first post gets image
            "platform": "threads"
        },
        "target": {"targetType": "threads"}
    }
}

Note: Currently, only the first post in a thread can have media attached.

Cross-Platform Publishing

Adapt content for Threads from other platforms:

def adapt_for_threads(content):
    text = content['text']

    # If text is very long, split into thread
    if len(text) > 450:
        return {
            "text": split_into_thread(text),
            "mediaUrls": content['mediaUrls'][:1],  # Only first image
            "platform": "threads"
        }
    else:
        return {
            "text": text,
            "mediaUrls": content['mediaUrls'][:20],  # Up to 20 images
            "platform": "threads"
        }

Rate Limits

Threads API rate limits:

Thread publishing: Each post in a thread counts as 1 API call.

Publishing History

View your Threads posts in the dashboard:

  1. Sign in to Boring Dashboard
  2. Scroll to "Recent Posts" section
  3. Filter by Threads platform

For thread posts, you'll see:

Feature Comparison

Feature Facebook Instagram Threads
Text-only βœ… ❌ βœ…
Single photo βœ… βœ… βœ…
Carousel βœ… (2-10) βœ… (2-10) βœ… (2-20)
Video βœ… βœ… (Reels) βœ…
Long-form thread ❌ ❌ βœ…
Max text Unlimited 2,200 500/post
Token expiry Never 60 days 60 days
Auto-refresh N/A ❌ βœ…

Next Steps