threads

package module
v1.0.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 13, 2025 License: MIT Imports: 15 Imported by: 0

README

Threads API Go Client

Go Reference Go Report Card

Production-ready Go client for the Threads API with complete endpoint coverage, OAuth 2.0 authentication, rate limiting, and comprehensive error handling.

Features

  • Complete API coverage (posts, users, replies, insights, locations)
  • OAuth 2.0 flow and existing token support
  • Intelligent rate limiting with exponential backoff
  • Type-safe error handling
  • Thread-safe concurrent usage
  • Comprehensive test coverage

Installation

go get github.com/tirthpatell/threads-go

Quick Start

With Existing Token
client, err := threads.NewClientWithToken("your-access-token", &threads.Config{
    ClientID:     "your-client-id",
    ClientSecret: "your-client-secret",
    RedirectURI:  "your-redirect-uri",
})

// Create a post
post, err := client.CreateTextPost(context.Background(), &threads.TextPostContent{
    Text: "Hello Threads!",
})
OAuth Flow
config := &threads.Config{
    ClientID:     "your-client-id",
    ClientSecret: "your-client-secret", 
    RedirectURI:  "your-redirect-uri",
    Scopes:       []string{"threads_basic", "threads_content_publish"},
}

client, err := threads.NewClient(config)

// Get authorization URL
authURL := client.GetAuthURL(config.Scopes)
// Redirect user to authURL

// Exchange authorization code for token
err = client.ExchangeCodeForToken("auth-code-from-callback")
err = client.GetLongLivedToken() // Convert to long-lived token
Environment Variables
export THREADS_CLIENT_ID="your-client-id"
export THREADS_CLIENT_SECRET="your-client-secret"
export THREADS_REDIRECT_URI="your-redirect-uri"
export THREADS_ACCESS_TOKEN="your-access-token"  # optional
client, err := threads.NewClientFromEnv()

Available Scopes

  • threads_basic - Basic profile access
  • threads_content_publish - Create and publish posts
  • threads_manage_insights - Access analytics data
  • threads_manage_replies - Manage replies and conversations
  • threads_read_replies - Read replies to posts
  • threads_keyword_search - Search functionality
  • threads_delete - Delete posts
  • threads_location_tagging - Location services

API Usage

Posts
// Create different post types
textPost, err := client.CreateTextPost(ctx, &threads.TextPostContent{
    Text: "Hello Threads!",
})

imagePost, err := client.CreateImagePost(ctx, &threads.ImagePostContent{
    Text: "Check this out!",
    ImageURL: "https://example.com/image.jpg",
})

// Get posts
post, err := client.GetPost(ctx, threads.PostID("123"))
posts, err := client.GetUserPosts(ctx, threads.UserID("456"), &threads.PostsOptions{Limit: 25})

// Delete post
err = client.DeletePost(ctx, threads.PostID("123"))
Users & Profiles
// Get user info
me, err := client.GetMe(ctx)
user, err := client.GetUser(ctx, threads.UserID("123"))

// Public profiles
publicUser, err := client.LookupPublicProfile(ctx, "@username")
posts, err := client.GetPublicProfilePosts(ctx, "username", nil)
Replies & Conversations
// Reply to posts
reply, err := client.ReplyToPost(ctx, threads.PostID("123"), &threads.PostContent{
    Text: "Great post!",
})

// Get replies
replies, err := client.GetReplies(ctx, threads.PostID("123"), &threads.RepliesOptions{Limit: 50})

// Manage visibility
err = client.HideReply(ctx, threads.PostID("456"))
Insights & Analytics
// Post insights
insights, err := client.GetPostInsights(ctx, threads.PostID("123"), []string{"views", "likes"})

// Account insights  
insights, err := client.GetAccountInsights(ctx, threads.UserID("456"), []string{"views"}, "lifetime")
Search & Locations
// Search posts by keyword
results, err := client.KeywordSearch(ctx, "golang", &threads.SearchOptions{Limit: 25})

// Search posts filtered by media type (new in v1.0.3)
imageResults, err := client.KeywordSearch(ctx, "nature", &threads.SearchOptions{
    MediaType: threads.MediaTypeImage,  // Filter for IMAGE posts only (TEXT, IMAGE, or VIDEO)
    Limit: 25,
})

// Search posts by topic tag
tagResults, err := client.KeywordSearch(ctx, "#technology", &threads.SearchOptions{
    SearchMode: threads.SearchModeTag,
    Limit: 25,
})

// Location search
locations, err := client.SearchLocations(ctx, "New York", nil, nil)
Pagination & Iterators

For large datasets, use iterators to automatically handle pagination:

// Posts iterator
userID := threads.ConvertToUserID("user_id")
iterator := threads.NewPostIterator(client, userID, &threads.PostsOptions{
    Limit: 25,
})

for iterator.HasNext() {
    response, err := iterator.Next(ctx)
    if err != nil {
        log.Fatal(err)
    }
    
    for _, post := range response.Data {
        fmt.Printf("Post: %s\n", post.Text)
    }
}

// Replies iterator
replyIterator := threads.NewReplyIterator(client, threads.PostID("123"), &threads.RepliesOptions{
    Limit: 50,
})

// Search iterator
searchIterator := threads.NewSearchIterator(client, "golang", "keyword", &threads.SearchOptions{
    Limit: 25,
})

// Collect all results at once
allPosts, err := iterator.Collect(ctx)

Configuration

config := &threads.Config{
    ClientID:     "your-client-id",
    ClientSecret: "your-client-secret",
    RedirectURI:  "https://yourapp.com/callback",
    Scopes:       []string{"threads_basic", "threads_content_publish"},
    HTTPTimeout:  30 * time.Second,
    Debug:        false,
}

For advanced configuration including retry logic, custom logging, and token storage, see the GoDoc documentation.

Error Handling

The client provides typed errors for different scenarios:

switch {
case threads.IsAuthenticationError(err):
    // Handle authentication issues
case threads.IsRateLimitError(err):
    rateLimitErr := err.(*threads.RateLimitError)
    time.Sleep(rateLimitErr.RetryAfter)
case threads.IsValidationError(err):
    validationErr := err.(*threads.ValidationError)
    log.Printf("Invalid %s: %s", validationErr.Field, err.Error())
}

Error types: AuthenticationError, RateLimitError, ValidationError, NetworkError, APIError

Testing

# Unit tests
go test ./...

# Integration tests (requires valid credentials)
export THREADS_ACCESS_TOKEN="your-token"
go test ./tests/integration/...

Contributing

See CONTRIBUTING.md for guidelines.

Official Documentation

License

MIT License - see LICENSE file for details.

Documentation

Overview

Package threads provides a comprehensive Go client for the Threads API by Meta.

The Threads API allows developers to build applications that interact with Threads, Meta's social media platform. This package provides a clean, idiomatic Go interface for all Threads API endpoints including authentication, posts, users, replies, insights, and more.

Quick Start

For users with an existing access token:

client, err := threads.NewClientWithToken("your-access-token", &threads.Config{
	ClientID:     "your-client-id",
	ClientSecret: "your-client-secret",
	RedirectURI:  "your-redirect-uri",
})
if err != nil {
	log.Fatal(err)
}

// Create a post
post, err := client.CreateTextPost(ctx, &threads.TextPostContent{
	Text: "Hello from Go!",
})

For OAuth 2.0 authentication flow:

config := &threads.Config{
	ClientID:     "your-client-id",
	ClientSecret: "your-client-secret",
	RedirectURI:  "your-redirect-uri",
	Scopes:       []string{"threads_basic", "threads_content_publish"},
}

client, err := threads.NewClient(config)
if err != nil {
	log.Fatal(err)
}

// Get authorization URL
authURL := client.GetAuthURL(config.Scopes)
// Direct user to authURL, then exchange code for token
err = client.ExchangeCodeForToken("auth-code-from-callback")

For complete API documentation: https://developers.facebook.com/docs/threads

Index

Constants

View Source
const (
	// Text limits
	MaxTextLength = 500 // Maximum characters for post text

	// Pagination limits
	MaxPostsPerRequest = 100 // Maximum posts per API request
	DefaultPostsLimit  = 25  // Default number of posts if not specified

	// Carousel limits
	MinCarouselItems = 2  // Minimum items in a carousel
	MaxCarouselItems = 20 // Maximum items in a carousel

	// Video processing
	VideoProcessingPollInterval = 10 * time.Second // How often to check video processing status
	VideoProcessingMaxAttempts  = 30               // Maximum attempts to check video status

	// Reply processing
	ReplyPublishDelay = 10 * time.Second // Recommended delay before publishing reply

	// Search constraints
	MinSearchTimestamp = 1688540400 // Minimum timestamp for search queries (July 5, 2023)

	// Library version
	Version = "1.0.3"

	// HTTP client defaults
	DefaultHTTPTimeout = 30 * time.Second // Default HTTP request timeout
	DefaultUserAgent   = "threads-go/" + Version
)

API Limits

View Source
const (
	// Post fields
	PostExtendedFields = "" /* 219-byte string literal not displayed */

	// User fields
	UserProfileFields = "id,username,name,threads_profile_picture_url,threads_biography,is_verified"

	// Reply fields (includes additional reply-specific fields)
	ReplyFields = "" /* 266-byte string literal not displayed */

	// Container status fields
	ContainerStatusFields = "id,status,error_message"

	// Location fields
	LocationFields = "id,address,name,city,country,latitude,longitude,postal_code"

	// Publishing limit fields
	PublishingLimitFields = "" /* 133-byte string literal not displayed */
)

Field Sets for API requests

View Source
const (
	ContainerStatusInProgress = "IN_PROGRESS"
	ContainerStatusFinished   = "FINISHED"
	ContainerStatusPublished  = "PUBLISHED"
	ContainerStatusError      = "ERROR"
	ContainerStatusExpired    = "EXPIRED"
)

Container Status values

View Source
const (
	MediaTypeText     = "TEXT"
	MediaTypeImage    = "IMAGE"
	MediaTypeVideo    = "VIDEO"
	MediaTypeCarousel = "CAROUSEL"
)

Media Types

View Source
const (
	ErrEmptyPostID      = "Post ID is required"
	ErrEmptyUserID      = "User ID is required"
	ErrEmptyContainerID = "Container ID is required"
	ErrEmptySearchQuery = "Search query is required"
)

Error messages

View Source
const (
	BaseAPIURL = "https://graph.threads.net"
)

API Endpoints

View Source
const (
	// MinInsightTimestamp is the earliest Unix timestamp that can be used (1712991600)
	MinInsightTimestamp int64 = 1712991600
)

Constants for API limitations

Variables

This section is empty.

Functions

func IsAPIError

func IsAPIError(err error) bool

IsAPIError checks if an error is a general API error. These are typically server-side issues that may require support. Returns true if the error is of type *APIError.

func IsAuthenticationError

func IsAuthenticationError(err error) bool

IsAuthenticationError checks if an error is an authentication error. This is useful for implementing retry logic or handling authentication failures. Returns true if the error is of type *AuthenticationError.

func IsNetworkError

func IsNetworkError(err error) bool

IsNetworkError checks if an error is a network error. Network errors may be temporary and can often be retried. Returns true if the error is of type *NetworkError.

func IsRateLimitError

func IsRateLimitError(err error) bool

IsRateLimitError checks if an error is a rate limit error. Use this to implement backoff strategies when rate limited. Returns true if the error is of type *RateLimitError.

func IsValidationError

func IsValidationError(err error) bool

IsValidationError checks if an error is a validation error. This helps identify client-side input errors that need correction. Returns true if the error is of type *ValidationError.

Types

type APIError

type APIError struct {
	*BaseError
	RequestID string `json:"request_id,omitempty"`
}

APIError represents general server-side API errors not covered by other error types. The RequestID can be used for debugging with Threads API support. Common HTTP status codes: 500 (Internal Server Error), 503 (Service Unavailable).

func NewAPIError

func NewAPIError(code int, message, details, requestID string) *APIError

NewAPIError creates a new API error with optional request ID. The requestID parameter helps with debugging and should be included when available from API response headers.

type AccountInsightMetric

type AccountInsightMetric string

AccountInsightMetric represents available account insight metrics

const (
	// AccountInsightViews represents the total views across all account posts
	AccountInsightViews AccountInsightMetric = "views"
	// AccountInsightLikes represents the total likes across all account posts
	AccountInsightLikes AccountInsightMetric = "likes"
	// AccountInsightReplies represents the total replies across all account posts
	AccountInsightReplies AccountInsightMetric = "replies"
	// AccountInsightReposts represents the total reposts across all account posts
	AccountInsightReposts AccountInsightMetric = "reposts"
	// AccountInsightQuotes represents the total quotes across all account posts
	AccountInsightQuotes AccountInsightMetric = "quotes"
	// AccountInsightClicks represents the total clicks across all account posts
	AccountInsightClicks AccountInsightMetric = "clicks"
	// AccountInsightFollowersCount represents the account's follower count
	AccountInsightFollowersCount AccountInsightMetric = "followers_count"
	// AccountInsightFollowerDemographics represents the demographic breakdown of followers
	AccountInsightFollowerDemographics AccountInsightMetric = "follower_demographics"
)

type AccountInsightsOptions

type AccountInsightsOptions struct {
	Metrics   []AccountInsightMetric `json:"metrics,omitempty"`
	Period    InsightPeriod          `json:"period,omitempty"`
	Since     *time.Time             `json:"since,omitempty"`
	Until     *time.Time             `json:"until,omitempty"`
	Breakdown string                 `json:"breakdown,omitempty"` // For follower_demographics: country, city, age, or gender
}

AccountInsightsOptions represents options for account insights requests

type AuthenticationError

type AuthenticationError struct {
	*BaseError
}

AuthenticationError represents authentication-related errors such as invalid tokens, expired tokens, or missing authentication credentials. Common HTTP status codes: 401 (Unauthorized), 403 (Forbidden).

func NewAuthenticationError

func NewAuthenticationError(code int, message, details string) *AuthenticationError

NewAuthenticationError creates a new authentication error with the specified details. Use this when authentication fails, tokens are invalid/expired, or credentials are missing. The code parameter should typically be 401 or 403.

type Authenticator

type Authenticator interface {
	// GetAuthURL generates an authorization URL for the OAuth 2.0 flow
	GetAuthURL(scopes []string) string

	// ExchangeCodeForToken exchanges an authorization code for an access token
	ExchangeCodeForToken(ctx context.Context, code string) error

	// GetLongLivedToken converts a short-lived token to a long-lived token
	GetLongLivedToken(ctx context.Context) error

	// RefreshToken refreshes the current access token
	RefreshToken(ctx context.Context) error

	// DebugToken validates and returns information about a token
	DebugToken(ctx context.Context, inputToken string) (*DebugTokenResponse, error)

	// SetTokenFromDebugInfo sets token info from debug token response
	SetTokenFromDebugInfo(accessToken string, debugResp *DebugTokenResponse) error

	// GetTokenDebugInfo returns detailed token information
	GetTokenDebugInfo() map[string]interface{}
}

Authenticator handles OAuth 2.0 authentication and token management

type BaseError

type BaseError struct {
	Code    int    `json:"code"`
	Message string `json:"message"`
	Type    string `json:"type"`
	Details string `json:"details,omitempty"`
}

BaseError represents a base error type for all Threads API errors. For error handling patterns, see: https://developers.facebook.com/docs/threads/troubleshooting

func (*BaseError) Error

func (e *BaseError) Error() string

Error implements the error interface

type CarouselPostContent

type CarouselPostContent struct {
	Text                    string       `json:"text,omitempty"`
	Children                []string     `json:"children"` // Container IDs
	ReplyControl            ReplyControl `json:"reply_control,omitempty"`
	ReplyTo                 string       `json:"reply_to_id,omitempty"`
	TopicTag                string       `json:"topic_tag,omitempty"`
	AllowlistedCountryCodes []string     `json:"allowlisted_country_codes,omitempty"`
	LocationID              string       `json:"location_id,omitempty"`
	// QuotedPostID makes this a quote post when provided
	// Leave empty for regular image posts
	QuotedPostID string `json:"quoted_post_id,omitempty"`
}

CarouselPostContent represents content for carousel posts. Set QuotedPostID to create a quote post, or leave empty for regular carousel posts.

type ChildPost

type ChildPost struct {
	ID string `json:"id"`
}

ChildPost represents a child post in a carousel

type ChildrenData

type ChildrenData struct {
	Data []ChildPost `json:"data"`
}

ChildrenData represents the children structure for carousel posts

type Client

type Client struct {
	// contains filtered or unexported fields
}

Client provides access to the Threads API with thread-safe operations. It implements the ClientInterface and all its composed interfaces.

func NewClient

func NewClient(config *Config) (*Client, error)

NewClient creates a new Threads API client with the provided configuration. The client is thread-safe and can be used concurrently from multiple goroutines.

func NewClientFromEnv

func NewClientFromEnv() (*Client, error)

NewClientFromEnv creates a new Threads API client using environment variables. This is a convenience function that combines NewConfigFromEnv and NewClient.

func NewClientWithToken

func NewClientWithToken(accessToken string, config *Config) (*Client, error)

NewClientWithToken creates a new Threads API client with an existing access token. The function validates the token by calling the debug_token endpoint.

func (*Client) ClearToken

func (c *Client) ClearToken() error

ClearToken removes the current token from the client and storage

func (*Client) Clone

func (c *Client) Clone() (*Client, error)

Clone creates a new client instance with the same configuration but separate token storage and state

func (*Client) CloneWithConfig

func (c *Client) CloneWithConfig(newConfig *Config) (*Client, error)

CloneWithConfig creates a new client instance with a different configuration

func (*Client) CreateCarouselPost

func (c *Client) CreateCarouselPost(ctx context.Context, content *CarouselPostContent) (*Post, error)

CreateCarouselPost creates a new carousel post on Threads

func (*Client) CreateImagePost

func (c *Client) CreateImagePost(ctx context.Context, content *ImagePostContent) (*Post, error)

CreateImagePost creates a new image post on Threads

func (*Client) CreateMediaContainer

func (c *Client) CreateMediaContainer(ctx context.Context, mediaType, mediaURL, altText string) (ContainerID, error)

CreateMediaContainer creates a media container for use in carousel posts

func (*Client) CreateQuotePost

func (c *Client) CreateQuotePost(ctx context.Context, content interface{}, quotedPostID string) (*Post, error)

CreateQuotePost creates a new quote post on Threads CreateQuotePost creates a quote post using any supported content type with a quoted post ID. This method acts as a router, directing to the appropriate creation method based on content type.

Supported content types:

  • *TextPostContent: Creates a text quote post
  • *ImagePostContent: Creates an image quote post
  • *VideoPostContent: Creates a video quote post
  • *CarouselPostContent: Creates a carousel quote post

The quotedPostID parameter specifies which post to quote.

func (*Client) CreateReply

func (c *Client) CreateReply(ctx context.Context, content *PostContent) (*Post, error)

CreateReply creates a reply to a specific post or reply

func (*Client) CreateTextPost

func (c *Client) CreateTextPost(ctx context.Context, content *TextPostContent) (*Post, error)

CreateTextPost creates a new text post on Threads

func (*Client) CreateVideoPost

func (c *Client) CreateVideoPost(ctx context.Context, content *VideoPostContent) (*Post, error)

CreateVideoPost creates a new video post on Threads

func (*Client) DebugToken

func (c *Client) DebugToken(ctx context.Context, inputToken string) (*DebugTokenResponse, error)

DebugToken calls the debug_token endpoint to get detailed token information. If inputToken is empty, it will debug the client's current access token. This method is useful for validating token status, checking expiration times, and retrieving token metadata like scopes and user information.

func (*Client) DeletePost

func (c *Client) DeletePost(ctx context.Context, postID PostID) error

DeletePost deletes a specific post by ID with proper validation and confirmation

func (*Client) DeletePostWithConfirmation

func (c *Client) DeletePostWithConfirmation(ctx context.Context, postID PostID, confirmationCallback func(post *Post) bool) error

DeletePostWithConfirmation deletes a post with an additional confirmation step

func (*Client) DisableRateLimiting

func (c *Client) DisableRateLimiting()

DisableRateLimiting disables the rate limiter entirely Use with caution - this will allow unlimited requests to the API

func (*Client) EnableRateLimiting

func (c *Client) EnableRateLimiting()

EnableRateLimiting re-enables rate limiting with a new rate limiter

func (*Client) EnsureValidToken

func (c *Client) EnsureValidToken(ctx context.Context) error

EnsureValidToken ensures the client has a valid, non-expired token It will attempt to refresh the token if it's expired or expiring soon

func (*Client) ExchangeCodeForToken

func (c *Client) ExchangeCodeForToken(ctx context.Context, code string) error

ExchangeCodeForToken exchanges an authorization code for an access token. This should be called after the user authorizes your app, and you receive the code from the redirect URI callback. The resulting token is automatically stored in the client and token storage.

func (*Client) GetAccessToken

func (c *Client) GetAccessToken() string

GetAccessToken returns the current access token in a thread-safe manner. This method is primarily intended for debugging and testing purposes. For production use, the client handles token management automatically.

func (*Client) GetAccountInsights

func (c *Client) GetAccountInsights(ctx context.Context, userID UserID, metrics []string, period string) (*InsightsResponse, error)

GetAccountInsights retrieves insights for a user account

func (*Client) GetAccountInsightsWithOptions

func (c *Client) GetAccountInsightsWithOptions(ctx context.Context, userID UserID, opts *AccountInsightsOptions) (*InsightsResponse, error)

GetAccountInsightsWithOptions retrieves insights for a user account with advanced options

func (*Client) GetAuthURL

func (c *Client) GetAuthURL(scopes []string) string

GetAuthURL generates the authorization URL for OAuth 2.0 flow. Users should be redirected to this URL to grant permissions to your app. If scopes are not provided, defaults to threads_basic and threads_content_publish. Returns the complete authorization URL including all necessary parameters.

func (*Client) GetAvailableAccountInsightMetrics

func (c *Client) GetAvailableAccountInsightMetrics() []AccountInsightMetric

GetAvailableAccountInsightMetrics returns all available account insight metrics

func (*Client) GetAvailableFollowerDemographicsBreakdowns

func (c *Client) GetAvailableFollowerDemographicsBreakdowns() []FollowerDemographicsBreakdown

GetAvailableFollowerDemographicsBreakdowns returns all available breakdown options for follower demographics

func (*Client) GetAvailableInsightPeriods

func (c *Client) GetAvailableInsightPeriods() []InsightPeriod

GetAvailableInsightPeriods returns all available insight periods

func (*Client) GetAvailablePostInsightMetrics

func (c *Client) GetAvailablePostInsightMetrics() []PostInsightMetric

GetAvailablePostInsightMetrics returns all available post insight metrics

func (*Client) GetConfig

func (c *Client) GetConfig() *Config

GetConfig returns a copy of the client configuration

func (*Client) GetConversation

func (c *Client) GetConversation(ctx context.Context, postID PostID, opts *RepliesOptions) (*RepliesResponse, error)

GetConversation retrieves a flattened conversation thread for a specific post

func (*Client) GetLocation

func (c *Client) GetLocation(ctx context.Context, locationID LocationID) (*Location, error)

GetLocation retrieves location details

func (*Client) GetLongLivedToken

func (c *Client) GetLongLivedToken(ctx context.Context) error

GetLongLivedToken converts a short-lived token to a long-lived token. Short-lived tokens expire in 1 hour while long-lived tokens last for 60 days. This method requires an existing valid short-lived token in the client. The long-lived token automatically replaces the short-lived token in storage.

func (*Client) GetMe

func (c *Client) GetMe(ctx context.Context) (*User, error)

GetMe retrieves the authenticated user's profile information

func (*Client) GetPost

func (c *Client) GetPost(ctx context.Context, postID PostID) (*Post, error)

GetPost retrieves a specific post by ID with all available fields

func (*Client) GetPostInsights

func (c *Client) GetPostInsights(ctx context.Context, postID PostID, metrics []string) (*InsightsResponse, error)

GetPostInsights retrieves insights for a specific post. For insights API documentation, see: https://developers.facebook.com/docs/threads/insights

func (*Client) GetPostInsightsWithOptions

func (c *Client) GetPostInsightsWithOptions(ctx context.Context, postID PostID, opts *PostInsightsOptions) (*InsightsResponse, error)

GetPostInsightsWithOptions retrieves insights for a specific post with advanced options

func (*Client) GetPublicProfilePosts

func (c *Client) GetPublicProfilePosts(ctx context.Context, username string, opts *PostsOptions) (*PostsResponse, error)

GetPublicProfilePosts retrieves posts from a public profile by username

func (*Client) GetPublishingLimits

func (c *Client) GetPublishingLimits(ctx context.Context) (*PublishingLimits, error)

GetPublishingLimits retrieves the current API quota usage for the user

func (*Client) GetRateLimitStatus

func (c *Client) GetRateLimitStatus() RateLimitStatus

GetRateLimitStatus returns the current rate limit status

func (*Client) GetReplies

func (c *Client) GetReplies(ctx context.Context, postID PostID, opts *RepliesOptions) (*RepliesResponse, error)

GetReplies retrieves replies to a specific post with pagination support

func (*Client) GetTokenDebugInfo

func (c *Client) GetTokenDebugInfo() map[string]interface{}

GetTokenDebugInfo returns detailed token information for debugging purposes. This method provides comprehensive information about the current token state including expiration times, validity checks, and calculated values useful for troubleshooting. The returned map contains various fields like has_token, is_authenticated, expires_at, etc.

func (*Client) GetTokenInfo

func (c *Client) GetTokenInfo() *TokenInfo

GetTokenInfo returns the current token information in a thread-safe manner

func (*Client) GetUser

func (c *Client) GetUser(ctx context.Context, userID UserID) (*User, error)

GetUser retrieves user profile information by user ID

func (*Client) GetUserFields

func (c *Client) GetUserFields(ctx context.Context, userID UserID, fields []string) (*User, error)

GetUserFields retrieves specific fields for a user

func (*Client) GetUserMentions

func (c *Client) GetUserMentions(ctx context.Context, userID UserID, opts *PaginationOptions) (*PostsResponse, error)

GetUserMentions retrieves posts where the user is mentioned

func (*Client) GetUserPosts

func (c *Client) GetUserPosts(ctx context.Context, userID UserID, opts *PaginationOptions) (*PostsResponse, error)

GetUserPosts retrieves posts from a specific user with pagination support

func (*Client) GetUserPostsWithOptions

func (c *Client) GetUserPostsWithOptions(ctx context.Context, userID UserID, opts *PostsOptions) (*PostsResponse, error)

GetUserPostsWithOptions retrieves posts from a specific user with enhanced options

func (*Client) GetUserReplies

func (c *Client) GetUserReplies(ctx context.Context, userID UserID, opts *PostsOptions) (*RepliesResponse, error)

GetUserReplies retrieves all replies created by a user

func (*Client) HideReply

func (c *Client) HideReply(ctx context.Context, replyID PostID) error

HideReply hides a specific reply for moderation purposes

func (*Client) IsAuthenticated

func (c *Client) IsAuthenticated() bool

IsAuthenticated returns true if the client has a valid access token

func (*Client) IsNearRateLimit

func (c *Client) IsNearRateLimit(threshold float64) bool

IsNearRateLimit returns true if the client is close to hitting rate limits

func (*Client) IsRateLimited

func (c *Client) IsRateLimited() bool

IsRateLimited returns true if the client is currently rate limited by the API

func (*Client) IsTokenExpired

func (c *Client) IsTokenExpired() bool

IsTokenExpired returns true if the current token is expired

func (*Client) IsTokenExpiringSoon

func (c *Client) IsTokenExpiringSoon(within time.Duration) bool

IsTokenExpiringSoon returns true if the token expires within the given duration

func (*Client) KeywordSearch

func (c *Client) KeywordSearch(ctx context.Context, query string, opts *SearchOptions) (*PostsResponse, error)

KeywordSearch searches for public Threads media by keyword

func (*Client) LoadTokenFromStorage

func (c *Client) LoadTokenFromStorage() error

LoadTokenFromStorage attempts to load a previously stored token from the configured storage. If a valid token is found, it's automatically set as the active token for the client. Returns an error if no token is found, if the token is expired, or if loading fails.

func (*Client) LookupPublicProfile

func (c *Client) LookupPublicProfile(ctx context.Context, username string) (*PublicUser, error)

LookupPublicProfile looks up a public profile by username

func (*Client) RefreshToken

func (c *Client) RefreshToken(ctx context.Context) error

RefreshToken refreshes the current access token before it expires. This extends the validity of your existing token without requiring user re-authorization. The refreshed token automatically replaces the current token in storage. Note: Only long-lived tokens can be refreshed.

func (*Client) ReplyToPost

func (c *Client) ReplyToPost(ctx context.Context, postID PostID, content *PostContent) (*Post, error)

ReplyToPost creates a reply to a specific post

func (*Client) RepostPost

func (c *Client) RepostPost(ctx context.Context, postID PostID) (*Post, error)

RepostPost reposts an existing post on Threads using the direct repost endpoint

func (*Client) SearchLocations

func (c *Client) SearchLocations(ctx context.Context, query string, latitude, longitude *float64) (*LocationSearchResponse, error)

SearchLocations searches for locations by query, latitude/longitude

func (*Client) SetTokenFromDebugInfo

func (c *Client) SetTokenFromDebugInfo(accessToken string, debugResp *DebugTokenResponse) error

SetTokenFromDebugInfo creates and sets token info from debug token response. This method takes the response from the debug_token endpoint and creates a properly configured TokenInfo struct with accurate expiration times based on the API response. This is useful for setting up tokens when you have the debug information available.

func (*Client) SetTokenInfo

func (c *Client) SetTokenInfo(tokenInfo *TokenInfo) error

SetTokenInfo sets the token information in a thread-safe manner

func (*Client) TestAPICall

func (c *Client) TestAPICall(method, path string, params map[string]string) (*Response, error)

TestAPICall makes a test API call (for testing purposes only)

func (*Client) UnhideReply

func (c *Client) UnhideReply(ctx context.Context, replyID PostID) error

UnhideReply unhides a specific reply that was previously hidden

func (*Client) UpdateConfig

func (c *Client) UpdateConfig(newConfig *Config) error

UpdateConfig updates the client configuration with validation Note: This does not affect already established connections

func (*Client) ValidateCarouselChildren

func (c *Client) ValidateCarouselChildren(childrenIDs []string) error

ValidateCarouselChildren validates carousel children containers

func (*Client) ValidateCarouselPostContent

func (c *Client) ValidateCarouselPostContent(content *CarouselPostContent) error

ValidateCarouselPostContent validates carousel post content according to Threads API limits

func (*Client) ValidateCountryCodes

func (c *Client) ValidateCountryCodes(codes []string) error

ValidateCountryCodes validates country codes

func (*Client) ValidateImagePostContent

func (c *Client) ValidateImagePostContent(content *ImagePostContent) error

ValidateImagePostContent validates image post content according to Threads API limits

func (*Client) ValidateTextPostContent

func (c *Client) ValidateTextPostContent(content *TextPostContent) error

ValidateTextPostContent validates text post content according to Threads API limits

func (*Client) ValidateToken

func (c *Client) ValidateToken() error

ValidateToken validates the current token by making a test API call

func (*Client) ValidateTopicTag

func (c *Client) ValidateTopicTag(tag string) error

ValidateTopicTag validates a topic tag format

func (*Client) ValidateVideoPostContent

func (c *Client) ValidateVideoPostContent(content *VideoPostContent) error

ValidateVideoPostContent validates video post content according to Threads API limits

func (*Client) WaitForRateLimit

func (c *Client) WaitForRateLimit(ctx context.Context) error

WaitForRateLimit blocks until it's safe to make another request

type ClientInterface

ClientInterface is the main interface that composes all Threads API functionality This replaces the large monolithic interface with smaller, focused interfaces

type Config

type Config struct {
	// ClientID is your Threads app's client ID (required).
	// This is provided when you create a Threads app in the Meta Developer Console.
	ClientID string

	// ClientSecret is your Threads app's client secret (required).
	// This is provided when you create a Threads app in the Meta Developer Console.
	// Keep this secret and never expose it in client-side code.
	ClientSecret string

	// RedirectURI is the URI where users will be redirected after authorization (required).
	// This must match exactly with the redirect URI configured in your app settings.
	// Must be a valid HTTP or HTTPS URL.
	RedirectURI string

	// Scopes defines the permissions your app is requesting (required).
	// Available scopes include:
	// - threads_basic: Basic profile access
	// - threads_content_publish: Create and publish posts
	// - threads_manage_insights: Access analytics data
	// - threads_manage_replies: Manage replies and conversations
	// - threads_read_replies: Read replies to posts
	// - threads_manage_mentions: Manage mentions
	// - threads_keyword_search: Search functionality
	// - threads_delete: Delete posts
	// - threads_location_tagging: Location services
	// - threads_profile_discovery: Public profile lookup
	Scopes []string

	// HTTPTimeout sets the timeout for HTTP requests (optional).
	// Default: 30 seconds. Set to 0 for no timeout (not recommended).
	HTTPTimeout time.Duration

	// RetryConfig configures retry behavior for failed requests (optional).
	// If nil, default retry configuration will be used.
	RetryConfig *RetryConfig

	// Logger provides structured logging for debugging and monitoring (optional).
	// If nil, no logging will be performed. Implement the Logger interface
	// to provide custom logging behavior.
	Logger Logger

	// TokenStorage provides persistent token storage (optional).
	// If nil, tokens will be stored in memory only and lost when the client
	// is destroyed. Implement the TokenStorage interface for persistence.
	TokenStorage TokenStorage

	// BaseURL is the base URL for the Threads API (optional).
	// Default: "https://graph.threads.net". Only change this for testing
	// or if using a proxy/gateway.
	BaseURL string

	// UserAgent is the User-Agent header sent with requests (optional).
	// Default: "threads-go/<version>". Customize this to identify your application.
	UserAgent string

	// Debug enables debug mode with verbose logging (optional).
	// Default: false. When true, detailed request/response information
	// will be logged if a Logger is provided.
	Debug bool
}

Config holds configuration settings for the Threads API client. Required fields: ClientID, ClientSecret, RedirectURI. All other fields have sensible defaults.

func NewConfig

func NewConfig() *Config

NewConfig creates a new configuration with sensible defaults.

func NewConfigFromEnv

func NewConfigFromEnv() (*Config, error)

NewConfigFromEnv creates a new configuration from environment variables. Required: THREADS_CLIENT_ID, THREADS_CLIENT_SECRET, THREADS_REDIRECT_URI.

func (*Config) SetDefaults

func (c *Config) SetDefaults()

SetDefaults sets default values for any unset configuration options

func (*Config) Validate

func (c *Config) Validate() error

Validate validates the configuration and returns an error if invalid

type ConfigValidator

type ConfigValidator struct{}

ConfigValidator validates client configuration

func NewConfigValidator

func NewConfigValidator() *ConfigValidator

NewConfigValidator creates a new config validator

func (*ConfigValidator) Validate

func (cv *ConfigValidator) Validate(c *Config) error

Validate validates the entire configuration

type ContainerBuilder

type ContainerBuilder struct {
	// contains filtered or unexported fields
}

ContainerBuilder helps build container creation parameters

func NewContainerBuilder

func NewContainerBuilder() *ContainerBuilder

NewContainerBuilder creates a new container builder

func (*ContainerBuilder) AddChild

func (b *ContainerBuilder) AddChild(childID string) *ContainerBuilder

AddChild adds a child container ID (for carousel posts)

func (*ContainerBuilder) Build

func (b *ContainerBuilder) Build() url.Values

Build returns the built parameters

func (*ContainerBuilder) SetAllowlistedCountryCodes

func (b *ContainerBuilder) SetAllowlistedCountryCodes(codes []string) *ContainerBuilder

SetAllowlistedCountryCodes sets geo-gating country codes

func (*ContainerBuilder) SetAltText

func (b *ContainerBuilder) SetAltText(altText string) *ContainerBuilder

SetAltText sets the alt text for media

func (*ContainerBuilder) SetAutoPublishText

func (b *ContainerBuilder) SetAutoPublishText(autoPublish bool) *ContainerBuilder

SetAutoPublishText sets whether to auto-publish text posts

func (*ContainerBuilder) SetChildren

func (b *ContainerBuilder) SetChildren(childIDs []string) *ContainerBuilder

SetChildren sets all children container IDs at once (for carousel posts)

func (*ContainerBuilder) SetImageURL

func (b *ContainerBuilder) SetImageURL(imageURL string) *ContainerBuilder

SetImageURL sets the image URL for image posts

func (*ContainerBuilder) SetIsCarouselItem

func (b *ContainerBuilder) SetIsCarouselItem(isCarouselItem bool) *ContainerBuilder

SetIsCarouselItem marks this as a carousel item

func (*ContainerBuilder) SetLinkAttachment

func (b *ContainerBuilder) SetLinkAttachment(linkURL string) *ContainerBuilder

SetLinkAttachment sets the link attachment

func (*ContainerBuilder) SetLocationID

func (b *ContainerBuilder) SetLocationID(locationID string) *ContainerBuilder

SetLocationID sets the location ID

func (*ContainerBuilder) SetMediaType

func (b *ContainerBuilder) SetMediaType(mediaType string) *ContainerBuilder

SetMediaType sets the media type

func (*ContainerBuilder) SetPollAttachment

func (b *ContainerBuilder) SetPollAttachment(poll *PollAttachment) *ContainerBuilder

SetPollAttachment sets the poll attachment

func (*ContainerBuilder) SetQuotePostID

func (b *ContainerBuilder) SetQuotePostID(quotePostID string) *ContainerBuilder

SetQuotePostID sets the quoted post ID

func (*ContainerBuilder) SetReplyControl

func (b *ContainerBuilder) SetReplyControl(replyControl ReplyControl) *ContainerBuilder

SetReplyControl sets who can reply to the post

func (*ContainerBuilder) SetReplyTo

func (b *ContainerBuilder) SetReplyTo(replyToID string) *ContainerBuilder

SetReplyTo sets the ID of the post being replied to

func (*ContainerBuilder) SetText

func (b *ContainerBuilder) SetText(text string) *ContainerBuilder

SetText sets the text content

func (*ContainerBuilder) SetTopicTag

func (b *ContainerBuilder) SetTopicTag(tag string) *ContainerBuilder

SetTopicTag sets the topic tag

func (*ContainerBuilder) SetVideoURL

func (b *ContainerBuilder) SetVideoURL(videoURL string) *ContainerBuilder

SetVideoURL sets the video URL for video posts

type ContainerID

type ContainerID string

ContainerID represents a unique identifier for a media container

func ConvertToContainerID

func ConvertToContainerID(s string) ContainerID

ConvertToContainerID safely converts a string to ContainerID

func (ContainerID) String

func (id ContainerID) String() string

String returns the string representation of the ContainerID

func (ContainerID) Valid

func (id ContainerID) Valid() bool

Valid checks if the ContainerID is not empty

type DebugTokenResponse

type DebugTokenResponse struct {
	Data struct {
		Type                string   `json:"type"`
		Application         string   `json:"application"`
		DataAccessExpiresAt int64    `json:"data_access_expires_at"`
		ExpiresAt           int64    `json:"expires_at"`
		IsValid             bool     `json:"is_valid"`
		IssuedAt            int64    `json:"issued_at"`
		Scopes              []string `json:"scopes"`
		UserID              string   `json:"user_id"`
	} `json:"data"`
}

DebugTokenResponse represents the response from the debug_token endpoint

type FollowerDemographicsBreakdown

type FollowerDemographicsBreakdown string

FollowerDemographicsBreakdown represents breakdown options for follower demographics

const (
	// BreakdownCountry represents follower demographics breakdown by country
	BreakdownCountry FollowerDemographicsBreakdown = "country"
	// BreakdownCity represents follower demographics breakdown by city
	BreakdownCity FollowerDemographicsBreakdown = "city"
	// BreakdownAge represents follower demographics breakdown by age group
	BreakdownAge FollowerDemographicsBreakdown = "age"
	// BreakdownGender represents follower demographics breakdown by gender
	BreakdownGender FollowerDemographicsBreakdown = "gender"
)

type HTTPClient

type HTTPClient struct {
	// contains filtered or unexported fields
}

HTTPClient wraps the standard HTTP client with additional functionality

func NewHTTPClient

func NewHTTPClient(config *Config, rateLimiter *RateLimiter) *HTTPClient

NewHTTPClient creates a new HTTP client with the provided configuration

func (*HTTPClient) DELETE

func (h *HTTPClient) DELETE(path string, accessToken string) (*Response, error)

DELETE performs a DELETE request

func (*HTTPClient) Do

func (h *HTTPClient) Do(opts *RequestOptions, accessToken string) (*Response, error)

Do executes an HTTP request with retry logic and error handling

func (*HTTPClient) GET

func (h *HTTPClient) GET(path string, queryParams url.Values, accessToken string) (*Response, error)

GET performs a GET request

func (*HTTPClient) POST

func (h *HTTPClient) POST(path string, body interface{}, accessToken string) (*Response, error)

POST performs a POST request

func (*HTTPClient) PUT

func (h *HTTPClient) PUT(path string, body interface{}, accessToken string) (*Response, error)

PUT performs a PUT request

type ImagePostContent

type ImagePostContent struct {
	Text                    string       `json:"text,omitempty"`
	ImageURL                string       `json:"image_url"`
	AltText                 string       `json:"alt_text,omitempty"`
	ReplyControl            ReplyControl `json:"reply_control,omitempty"`
	ReplyTo                 string       `json:"reply_to_id,omitempty"`
	TopicTag                string       `json:"topic_tag,omitempty"`
	AllowlistedCountryCodes []string     `json:"allowlisted_country_codes,omitempty"`
	LocationID              string       `json:"location_id,omitempty"`
	// QuotedPostID makes this a quote post when provided
	// Leave empty for regular image posts
	QuotedPostID string `json:"quoted_post_id,omitempty"`
}

ImagePostContent represents content for image posts. Set QuotedPostID to create a quote post, or leave empty for regular image posts.

type Insight

type Insight struct {
	Name        string      `json:"name"`
	Period      string      `json:"period"`
	Values      []Value     `json:"values"`
	Title       string      `json:"title"`
	Description string      `json:"description"`
	ID          string      `json:"id"`
	TotalValue  *TotalValue `json:"total_value,omitempty"`
}

Insight represents an individual analytics metric with its values over time. Common metrics include views, likes, replies, reposts, quotes, follows, etc. The Period field indicates the time aggregation (e.g., "day", "week", "lifetime").

type InsightPeriod

type InsightPeriod string

InsightPeriod represents the time period for insights

const (
	// InsightPeriodDay represents daily insights data
	InsightPeriodDay InsightPeriod = "day"
	// InsightPeriodLifetime represents lifetime/total insights data
	InsightPeriodLifetime InsightPeriod = "lifetime"
)

type InsightsProvider

type InsightsProvider interface {
	// GetPostInsights retrieves insights for a post
	GetPostInsights(ctx context.Context, postID PostID, metrics []string) (*InsightsResponse, error)

	// GetPostInsightsWithOptions retrieves post insights with options
	GetPostInsightsWithOptions(ctx context.Context, postID PostID, opts *PostInsightsOptions) (*InsightsResponse, error)

	// GetAccountInsights retrieves account-level insights
	GetAccountInsights(ctx context.Context, userID UserID, metrics []string, period string) (*InsightsResponse, error)

	// GetAccountInsightsWithOptions retrieves account insights with options
	GetAccountInsightsWithOptions(ctx context.Context, userID UserID, opts *AccountInsightsOptions) (*InsightsResponse, error)
}

InsightsProvider handles analytics and insights operations

type InsightsResponse

type InsightsResponse struct {
	Data []Insight `json:"data"`
}

InsightsResponse represents analytics and insights data for posts or user profiles. Contains an array of Insight objects with various metrics like views, likes, replies. Requires threads_manage_insights scope.

type Location

type Location struct {
	ID         string  `json:"id"`
	Name       string  `json:"name"`
	Address    string  `json:"address,omitempty"`
	City       string  `json:"city,omitempty"`
	Country    string  `json:"country,omitempty"`
	Latitude   float64 `json:"latitude,omitempty"`
	Longitude  float64 `json:"longitude,omitempty"`
	PostalCode string  `json:"postal_code,omitempty"`
}

Location represents a geographic location that can be tagged in posts. Use SearchLocations to find location IDs, then include the ID when creating posts. Requires threads_location_tagging scope.

type LocationID

type LocationID string

LocationID represents a unique identifier for a location

func ConvertToLocationID

func ConvertToLocationID(s string) LocationID

ConvertToLocationID safely converts a string to LocationID

func (LocationID) String

func (id LocationID) String() string

String returns the string representation of the LocationID

func (LocationID) Valid

func (id LocationID) Valid() bool

Valid checks if the LocationID is not empty

type LocationManager

type LocationManager interface {
	// SearchLocations searches for locations
	SearchLocations(ctx context.Context, query string, latitude, longitude *float64) (*LocationSearchResponse, error)

	// GetLocation retrieves location details
	GetLocation(ctx context.Context, locationID LocationID) (*Location, error)
}

LocationManager handles location-related operations

type LocationSearchResponse

type LocationSearchResponse struct {
	Data []Location `json:"data"`
}

LocationSearchResponse represents the response from location search endpoint. Contains an array of Location objects matching the search query. Use the location IDs from this response when creating location-tagged posts.

type Logger

type Logger interface {
	// Debug logs debug-level messages with optional structured fields.
	// Used for detailed tracing and development debugging.
	Debug(msg string, fields ...any)

	// Info logs informational messages with optional structured fields.
	// Used for general operational information.
	Info(msg string, fields ...any)

	// Warn logs warning messages with optional structured fields.
	// Used for potentially problematic situations that don't prevent operation.
	Warn(msg string, fields ...any)

	// Error logs error messages with optional structured fields.
	// Used for error conditions that may affect functionality.
	Error(msg string, fields ...any)
}

Logger interface for structured logging.

type LongLivedTokenResponse

type LongLivedTokenResponse struct {
	AccessToken string `json:"access_token"`
	TokenType   string `json:"token_type"`
	ExpiresIn   int64  `json:"expires_in"`
}

LongLivedTokenResponse represents the response from long-lived token conversion endpoint. Long-lived tokens typically last for 60 days compared to short-lived tokens which last 1 hour. Convert short-lived tokens to long-lived tokens for better user experience.

type MemoryTokenStorage

type MemoryTokenStorage struct {
	// contains filtered or unexported fields
}

MemoryTokenStorage provides in-memory token storage (default)

func (*MemoryTokenStorage) Delete

func (m *MemoryTokenStorage) Delete() error

Delete removes the token from memory

func (*MemoryTokenStorage) Load

func (m *MemoryTokenStorage) Load() (*TokenInfo, error)

Load retrieves the token from memory

func (*MemoryTokenStorage) Store

func (m *MemoryTokenStorage) Store(token *TokenInfo) error

Store saves the token in memory

type NetworkError

type NetworkError struct {
	*BaseError
	Temporary bool `json:"temporary"`
}

NetworkError represents network-related errors such as connection failures, timeouts, or DNS resolution issues. The Temporary field indicates if the error is likely transient and the request can be retried.

func NewNetworkError

func NewNetworkError(code int, message, details string, temporary bool) *NetworkError

NewNetworkError creates a new network error with temporary status. Set temporary to true for transient errors that may succeed on retry. The code may be 0 for client-side network failures.

type PaginationOptions

type PaginationOptions struct {
	Limit  int    `json:"limit,omitempty"`
	Before string `json:"before,omitempty"`
	After  string `json:"after,omitempty"`
}

PaginationOptions represents standard pagination parameters for API requests. Limit controls the number of results per page (max varies by endpoint). Use Before/After cursors from previous responses to navigate pages.

type Paging

type Paging struct {
	Cursors *PagingCursors `json:"cursors,omitempty"`
	Before  string         `json:"before,omitempty"` // Deprecated: use Cursors.Before
	After   string         `json:"after,omitempty"`  // Deprecated: use Cursors.After
}

Paging represents pagination information for navigating through result sets. Use Before/After cursors to fetch previous/next pages of results. The direct Before/After fields are deprecated; use Cursors instead.

type PagingCursors

type PagingCursors struct {
	Before string `json:"before,omitempty"`
	After  string `json:"after,omitempty"`
}

PagingCursors represents cursor-based pagination for efficient data retrieval. Before cursor fetches older items, After cursor fetches newer items. These are opaque strings that should not be modified.

type PollAttachment

type PollAttachment struct {
	OptionA string `json:"option_a"`
	OptionB string `json:"option_b"`
	OptionC string `json:"option_c,omitempty"`
	OptionD string `json:"option_d,omitempty"`
}

PollAttachment represents poll options when creating a post with a poll. Polls must have at least options A and B. Options C and D are optional. Polls automatically expire after 24 hours.

type PollResult

type PollResult struct {
	OptionA                string  `json:"option_a"`
	OptionB                string  `json:"option_b"`
	OptionC                string  `json:"option_c,omitempty"`
	OptionD                string  `json:"option_d,omitempty"`
	OptionAVotesPercentage float64 `json:"option_a_votes_percentage"`
	OptionBVotesPercentage float64 `json:"option_b_votes_percentage"`
	OptionCVotesPercentage float64 `json:"option_c_votes_percentage,omitempty"`
	OptionDVotesPercentage float64 `json:"option_d_votes_percentage,omitempty"`
	TotalVotes             int     `json:"total_votes"`
	ExpirationTimestamp    Time    `json:"expiration_timestamp"`
}

PollResult represents poll results and voting statistics when retrieving posts with polls. Contains the poll options and their vote percentages. The ExpirationTimestamp indicates when the poll closes (typically 24 hours after creation). TotalVotes shows the total number of votes cast in the poll.

type Post

type Post struct {
	ID                string        `json:"id"`
	Text              string        `json:"text,omitempty"`
	MediaType         string        `json:"media_type,omitempty"`
	MediaURL          string        `json:"media_url,omitempty"`
	Permalink         string        `json:"permalink"`
	Timestamp         Time          `json:"timestamp"`
	Username          string        `json:"username"`
	Owner             *PostOwner    `json:"owner,omitempty"`
	IsReply           bool          `json:"is_reply"`
	ReplyTo           string        `json:"reply_to,omitempty"`
	MediaProductType  string        `json:"media_product_type"`
	Shortcode         string        `json:"shortcode,omitempty"`
	ThumbnailURL      string        `json:"thumbnail_url,omitempty"`
	AltText           string        `json:"alt_text,omitempty"`
	Children          *ChildrenData `json:"children,omitempty"`
	IsQuotePost       bool          `json:"is_quote_post,omitempty"`
	LinkAttachmentURL string        `json:"link_attachment_url,omitempty"`
	HasReplies        bool          `json:"has_replies,omitempty"`
	ReplyAudience     string        `json:"reply_audience,omitempty"`
	QuotedPost        *Post         `json:"quoted_post,omitempty"`
	RepostedPost      *Post         `json:"reposted_post,omitempty"`
	GifURL            string        `json:"gif_url,omitempty"`
	PollAttachment    *PollResult   `json:"poll_attachment,omitempty"`
	RootPost          *Post         `json:"root_post,omitempty"`
	RepliedTo         *Post         `json:"replied_to,omitempty"`
	IsReplyOwnedByMe  bool          `json:"is_reply_owned_by_me,omitempty"`
	HideStatus        string        `json:"hide_status,omitempty"`
	TopicTag          string        `json:"topic_tag,omitempty"`
}

Post represents a Threads post with all its metadata and content. This is the primary data structure returned by most post-related API operations. Posts can contain text, images, videos, carousels, or be quote/reply posts.

type PostContent

type PostContent struct {
	Text      string `json:"text,omitempty"`
	MediaType string `json:"media_type,omitempty"`
	ReplyTo   string `json:"reply_to_id,omitempty"`
}

PostContent represents generic post content interface. This is a base structure for creating various types of posts. For specific post types, use TextPostContent, ImagePostContent, etc.

type PostCreator

type PostCreator interface {
	// CreateTextPost creates a new text post
	CreateTextPost(ctx context.Context, content *TextPostContent) (*Post, error)

	// CreateImagePost creates a new image post
	CreateImagePost(ctx context.Context, content *ImagePostContent) (*Post, error)

	// CreateVideoPost creates a new video post
	CreateVideoPost(ctx context.Context, content *VideoPostContent) (*Post, error)

	// CreateCarouselPost creates a carousel post with multiple media items
	CreateCarouselPost(ctx context.Context, content *CarouselPostContent) (*Post, error)

	// CreateQuotePost creates a quote post using any supported content type
	CreateQuotePost(ctx context.Context, content interface{}, quotedPostID string) (*Post, error)

	// RepostPost reposts an existing post
	RepostPost(ctx context.Context, postID PostID) (*Post, error)

	// CreateMediaContainer creates a media container for carousel items
	CreateMediaContainer(ctx context.Context, mediaType, mediaURL, altText string) (ContainerID, error)
}

PostCreator handles creation of different post types

type PostDeleter

type PostDeleter interface {
	// DeletePost deletes a specific post
	DeletePost(ctx context.Context, postID PostID) error

	// DeletePostWithConfirmation deletes a post with confirmation
	DeletePostWithConfirmation(ctx context.Context, postID PostID, confirmationCallback func(post *Post) bool) error
}

PostDeleter handles post deletion operations

type PostID

type PostID string

PostID represents a unique identifier for a post

func ConvertToPostID

func ConvertToPostID(s string) PostID

ConvertToPostID safely converts a string to PostID

func (PostID) String

func (id PostID) String() string

String returns the string representation of the PostID

func (PostID) Valid

func (id PostID) Valid() bool

Valid checks if the PostID is not empty

type PostInsightMetric

type PostInsightMetric string

PostInsightMetric represents available post insight metrics

const (
	// PostInsightViews represents the number of times a post was viewed
	PostInsightViews PostInsightMetric = "views"
	// PostInsightLikes represents the number of likes a post received
	PostInsightLikes PostInsightMetric = "likes"
	// PostInsightReplies represents the number of replies a post received
	PostInsightReplies PostInsightMetric = "replies"
	// PostInsightReposts represents the number of times a post was reposted
	PostInsightReposts PostInsightMetric = "reposts"
	// PostInsightQuotes represents the number of times a post was quoted
	PostInsightQuotes PostInsightMetric = "quotes"
	// PostInsightShares represents the number of times a post was shared
	PostInsightShares PostInsightMetric = "shares"
)

type PostInsightsOptions

type PostInsightsOptions struct {
	Metrics []PostInsightMetric `json:"metrics,omitempty"`
	Period  InsightPeriod       `json:"period,omitempty"`
	Since   *time.Time          `json:"since,omitempty"`
	Until   *time.Time          `json:"until,omitempty"`
}

PostInsightsOptions represents options for post insights requests

type PostIterator

type PostIterator struct {
	// contains filtered or unexported fields
}

PostIterator provides an iterator for paginating through posts

func NewPostIterator

func NewPostIterator(client PostReader, userID UserID, opts *PostsOptions) *PostIterator

NewPostIterator creates a new post iterator

func (*PostIterator) Collect

func (p *PostIterator) Collect(ctx context.Context) ([]Post, error)

Collect fetches all remaining pages and returns them as a single slice

func (*PostIterator) HasNext

func (p *PostIterator) HasNext() bool

HasNext returns true if there are more pages to fetch

func (*PostIterator) Next

func (p *PostIterator) Next(ctx context.Context) (*PostsResponse, error)

Next retrieves the next page of posts

func (*PostIterator) Reset

func (p *PostIterator) Reset()

Reset resets the iterator to start from the beginning

type PostManager

type PostManager interface {
	PostCreator
	PostReader
	PostDeleter
	PostValidator
}

PostManager handles post creation, retrieval, and management

type PostOwner

type PostOwner struct {
	ID string `json:"id"`
}

PostOwner represents the owner of a post (only available on top-level posts you own)

type PostReader

type PostReader interface {
	// GetPost retrieves a specific post by ID
	GetPost(ctx context.Context, postID PostID) (*Post, error)

	// GetUserPosts retrieves posts from a specific user
	GetUserPosts(ctx context.Context, userID UserID, opts *PaginationOptions) (*PostsResponse, error)

	// GetUserPostsWithOptions retrieves posts with enhanced filtering
	GetUserPostsWithOptions(ctx context.Context, userID UserID, opts *PostsOptions) (*PostsResponse, error)

	// GetUserMentions retrieves posts where the user is mentioned
	GetUserMentions(ctx context.Context, userID UserID, opts *PaginationOptions) (*PostsResponse, error)

	// GetPublishingLimits retrieves current API quota usage
	GetPublishingLimits(ctx context.Context) (*PublishingLimits, error)
}

PostReader handles post retrieval operations

type PostValidator

type PostValidator interface {
	// ValidateTextPostContent validates text post content
	ValidateTextPostContent(content *TextPostContent) error

	// ValidateImagePostContent validates image post content
	ValidateImagePostContent(content *ImagePostContent) error

	// ValidateVideoPostContent validates video post content
	ValidateVideoPostContent(content *VideoPostContent) error

	// ValidateCarouselPostContent validates carousel post content
	ValidateCarouselPostContent(content *CarouselPostContent) error

	// ValidateCarouselChildren validates carousel children containers
	ValidateCarouselChildren(childrenIDs []string) error

	// ValidateTopicTag validates a topic tag format
	ValidateTopicTag(tag string) error

	// ValidateCountryCodes validates country codes
	ValidateCountryCodes(codes []string) error
}

PostValidator provides validation for post content

type PostsOptions

type PostsOptions struct {
	Limit  int    `json:"limit,omitempty"`
	Before string `json:"before,omitempty"`
	After  string `json:"after,omitempty"`
	Since  int64  `json:"since,omitempty"` // Unix timestamp
	Until  int64  `json:"until,omitempty"` // Unix timestamp
}

PostsOptions represents enhanced options for posts requests with time filtering

type PostsResponse

type PostsResponse struct {
	Data   []Post `json:"data"`
	Paging Paging `json:"paging"`
}

PostsResponse represents a paginated response containing multiple posts. Use the Paging field to navigate through large result sets. This is returned by endpoints like GetUserPosts, SearchPosts, etc.

type PublicUser

type PublicUser struct {
	Username          string `json:"username"`
	Name              string `json:"name"`
	ProfilePictureURL string `json:"profile_picture_url"`
	Biography         string `json:"biography"`
	IsVerified        bool   `json:"is_verified"`
	FollowerCount     int    `json:"follower_count"`
	LikesCount        int    `json:"likes_count"`
	QuotesCount       int    `json:"quotes_count"`
	RepliesCount      int    `json:"replies_count"`
	RepostsCount      int    `json:"reposts_count"`
	ViewsCount        int    `json:"views_count"`
}

PublicUser represents a public Threads user profile retrieved via the threads_profile_discovery scope. This contains public-facing information about a user that can be accessed without authentication context.

type PublishingLimits

type PublishingLimits struct {
	QuotaUsage               int         `json:"quota_usage"`
	Config                   QuotaConfig `json:"config"`
	ReplyQuotaUsage          int         `json:"reply_quota_usage"`
	ReplyConfig              QuotaConfig `json:"reply_config"`
	DeleteQuotaUsage         int         `json:"delete_quota_usage"`
	DeleteConfig             QuotaConfig `json:"delete_config"`
	LocationSearchQuotaUsage int         `json:"location_search_quota_usage"`
	LocationSearchConfig     QuotaConfig `json:"location_search_config"`
}

PublishingLimits represents current API quota usage and limits for various operations. This helps track how many posts, replies, and other actions you can still perform within the rate limit window. Check these before performing bulk operations.

type QuotaConfig

type QuotaConfig struct {
	QuotaTotal    int `json:"quota_total"`
	QuotaDuration int `json:"quota_duration"`
}

QuotaConfig represents quota configuration for a specific operation type. QuotaTotal is the maximum allowed operations, QuotaDuration is the time window in seconds during which the quota applies.

type RateLimitController

type RateLimitController interface {
	// IsRateLimited returns true if currently rate limited
	IsRateLimited() bool

	// DisableRateLimiting disables rate limiting
	DisableRateLimiting()

	// EnableRateLimiting re-enables rate limiting
	EnableRateLimiting()

	// GetRateLimitStatus returns current rate limit status
	GetRateLimitStatus() RateLimitStatus

	// IsNearRateLimit checks if near rate limit threshold
	IsNearRateLimit(threshold float64) bool

	// WaitForRateLimit blocks until safe to make request
	WaitForRateLimit(ctx context.Context) error
}

RateLimitController manages rate limiting behavior

type RateLimitError

type RateLimitError struct {
	*BaseError
	RetryAfter time.Duration `json:"retry_after"`
}

RateLimitError represents rate limiting errors when API quota is exceeded. Contains RetryAfter duration indicating when the client can retry the request. Common HTTP status code: 429 (Too Many Requests).

func NewRateLimitError

func NewRateLimitError(code int, message, details string, retryAfter time.Duration) *RateLimitError

NewRateLimitError creates a new rate limit error with retry information. The retryAfter parameter indicates how long to wait before retrying. The code parameter should typically be 429.

type RateLimitInfo

type RateLimitInfo struct {
	Limit      int           `json:"limit"`
	Remaining  int           `json:"remaining"`
	Reset      time.Time     `json:"reset"`
	RetryAfter time.Duration `json:"retry_after,omitempty"`
}

RateLimitInfo contains rate limiting information from response headers

type RateLimitStatus

type RateLimitStatus struct {
	Limit     int           `json:"limit"`
	Remaining int           `json:"remaining"`
	ResetTime time.Time     `json:"reset_time"`
	ResetIn   time.Duration `json:"reset_in"`
}

RateLimitStatus represents the current rate limit status

type RateLimiter

type RateLimiter struct {
	// contains filtered or unexported fields
}

RateLimiter manages API rate limiting with intelligent backoff

func NewRateLimiter

func NewRateLimiter(config *RateLimiterConfig) *RateLimiter

NewRateLimiter creates a new rate limiter with the given configuration

func (*RateLimiter) GetQueueLength

func (rl *RateLimiter) GetQueueLength() int

GetQueueLength returns the current number of queued requests

func (*RateLimiter) GetStatus

func (rl *RateLimiter) GetStatus() RateLimitStatus

GetStatus returns current rate limit status

func (*RateLimiter) IsNearLimit

func (rl *RateLimiter) IsNearLimit(threshold float64) bool

IsNearLimit returns true if we're close to hitting the rate limit This is now informational only and doesn't block requests

func (*RateLimiter) IsRateLimited

func (rl *RateLimiter) IsRateLimited() bool

IsRateLimited returns true if we're currently rate limited by the API

func (*RateLimiter) MarkRateLimited

func (rl *RateLimiter) MarkRateLimited(resetTime time.Time)

MarkRateLimited marks that we've been rate limited by the API

func (*RateLimiter) ProcessQueue

func (rl *RateLimiter) ProcessQueue(ctx context.Context, processor func() error) error

ProcessQueue processes queued requests respecting rate limits

func (*RateLimiter) QueueRequest

func (rl *RateLimiter) QueueRequest(ctx context.Context) error

QueueRequest queues a request for later execution when rate limits allow

func (*RateLimiter) Reset

func (rl *RateLimiter) Reset()

Reset resets the rate limiter state (useful for testing)

func (*RateLimiter) ShouldWait

func (rl *RateLimiter) ShouldWait() bool

ShouldWait returns true if we should wait before making a request Only returns true if we've been explicitly rate limited by the API

func (*RateLimiter) UpdateFromHeaders

func (rl *RateLimiter) UpdateFromHeaders(rateLimitInfo *RateLimitInfo)

UpdateFromHeaders updates rate limit information from API response headers

func (*RateLimiter) Wait

func (rl *RateLimiter) Wait(ctx context.Context) error

Wait blocks until it's safe to make a request, only when actually rate limited

type RateLimiterConfig

type RateLimiterConfig struct {
	InitialLimit      int           // Initial rate limit (will be updated from API responses)
	BackoffMultiplier float64       // Exponential backoff multiplier
	MaxBackoff        time.Duration // Maximum backoff duration
	QueueSize         int           // Size of request queue
	Logger            Logger        // Logger instance
}

RateLimiterConfig holds configuration for the rate limiter

type RepliesOptions

type RepliesOptions struct {
	Limit   int    `json:"limit,omitempty"`
	Before  string `json:"before,omitempty"`
	After   string `json:"after,omitempty"`
	Reverse *bool  `json:"reverse,omitempty"` // true for reverse chronological, false for chronological (default: true)
}

RepliesOptions represents options for replies and conversation requests

type RepliesResponse

type RepliesResponse struct {
	Data   []Post `json:"data"`
	Paging Paging `json:"paging"`
}

RepliesResponse represents a paginated response containing reply posts. Use the Paging field to navigate through conversation threads. This is returned by endpoints like GetReplies, GetConversation, etc.

type ReplyControl

type ReplyControl string

ReplyControl defines who can reply to a post

const (
	// ReplyControlEveryone allows anyone to reply to the post
	ReplyControlEveryone ReplyControl = "everyone"
	// ReplyControlAccountsYouFollow allows only accounts you follow to reply
	ReplyControlAccountsYouFollow ReplyControl = "accounts_you_follow"
	// ReplyControlMentioned allows only mentioned users to reply
	ReplyControlMentioned ReplyControl = "mentioned_only"
	// ReplyControlParentPostAuthorOnly allows only the parent post author to reply
	ReplyControlParentPostAuthorOnly ReplyControl = "parent_post_author_only"
	// ReplyControlFollowersOnly allows only followers to reply to the post
	ReplyControlFollowersOnly ReplyControl = "followers_only"
)

type ReplyIterator

type ReplyIterator struct {
	// contains filtered or unexported fields
}

ReplyIterator provides an iterator for paginating through replies

func NewReplyIterator

func NewReplyIterator(client ReplyManager, postID PostID, opts *RepliesOptions) *ReplyIterator

NewReplyIterator creates a new reply iterator

func (*ReplyIterator) Collect

func (r *ReplyIterator) Collect(ctx context.Context) ([]Post, error)

Collect fetches all remaining pages and returns them as a single slice

func (*ReplyIterator) HasNext

func (r *ReplyIterator) HasNext() bool

HasNext returns true if there are more pages to fetch

func (*ReplyIterator) Next

Next retrieves the next page of replies

func (*ReplyIterator) Reset

func (r *ReplyIterator) Reset()

Reset resets the iterator to start from the beginning

type ReplyManager

type ReplyManager interface {
	// CreateReply creates a reply to a post
	CreateReply(ctx context.Context, content *PostContent) (*Post, error)

	// ReplyToPost creates a reply to a specific post
	ReplyToPost(ctx context.Context, postID PostID, content *PostContent) (*Post, error)

	// GetReplies retrieves replies to a post
	GetReplies(ctx context.Context, postID PostID, opts *RepliesOptions) (*RepliesResponse, error)

	// GetConversation retrieves a conversation thread
	GetConversation(ctx context.Context, postID PostID, opts *RepliesOptions) (*RepliesResponse, error)

	// HideReply hides a specific reply
	HideReply(ctx context.Context, replyID PostID) error

	// UnhideReply unhides a previously hidden reply
	UnhideReply(ctx context.Context, replyID PostID) error

	// GetUserReplies retrieves all replies by a user
	GetUserReplies(ctx context.Context, userID UserID, opts *PostsOptions) (*RepliesResponse, error)
}

ReplyManager handles reply and conversation operations

type RepostContent

type RepostContent struct {
	PostID string `json:"post_id"`
}

RepostContent represents the content required to create a repost. A repost shares another user's post to your profile without modifications. Only the original post ID is required.

type RequestOptions

type RequestOptions struct {
	Method      string
	Path        string
	QueryParams url.Values
	Body        interface{}
	Headers     map[string]string
	Context     context.Context
}

RequestOptions holds options for HTTP requests

type Response

type Response struct {
	*http.Response
	Body       []byte
	RequestID  string
	RateLimit  *RateLimitInfo
	Duration   time.Duration
	StatusCode int
}

Response wraps HTTP response with additional metadata

type RetryConfig

type RetryConfig struct {
	// MaxRetries is the maximum number of retry attempts (default: 3).
	// Set to 0 to disable retries. Higher values provide more resilience
	// but may increase latency for failing requests.
	MaxRetries int

	// InitialDelay is the delay before the first retry attempt (default: 1 second).
	// This delay is multiplied by BackoffFactor for subsequent retries.
	InitialDelay time.Duration

	// MaxDelay is the maximum delay between retry attempts (default: 30 seconds).
	// This prevents exponential backoff from creating excessively long delays.
	MaxDelay time.Duration

	// BackoffFactor is the multiplier for exponential backoff (default: 2.0).
	// Each retry delay is calculated as: min(InitialDelay * BackoffFactor^attempt, MaxDelay)
	BackoffFactor float64
}

RetryConfig defines retry behavior for failed requests with exponential backoff.

type SearchIterator

type SearchIterator struct {
	// contains filtered or unexported fields
}

SearchIterator provides an iterator for paginating through search results

func NewSearchIterator

func NewSearchIterator(client SearchProvider, query string, searchType string, opts *SearchOptions) *SearchIterator

NewSearchIterator creates a new search iterator

func (*SearchIterator) Collect

func (s *SearchIterator) Collect(ctx context.Context) ([]Post, error)

Collect fetches all remaining pages and returns them as a single slice

func (*SearchIterator) HasNext

func (s *SearchIterator) HasNext() bool

HasNext returns true if there are more pages to fetch

func (*SearchIterator) Next

Next retrieves the next page of search results

func (*SearchIterator) Reset

func (s *SearchIterator) Reset()

Reset resets the iterator to start from the beginning

type SearchMode

type SearchMode string

SearchMode defines the search mode

const (
	// SearchModeKeyword treats query as keyword (default)
	SearchModeKeyword SearchMode = "KEYWORD"
	// SearchModeTag treats query as topic tag
	SearchModeTag SearchMode = "TAG"
)

type SearchOptions

type SearchOptions struct {
	SearchType SearchType `json:"search_type,omitempty"`
	SearchMode SearchMode `json:"search_mode,omitempty"`
	MediaType  string     `json:"media_type,omitempty"` // Filter by media type: TEXT, IMAGE, or VIDEO
	Limit      int        `json:"limit,omitempty"`
	Since      int64      `json:"since,omitempty"` // Unix timestamp (must be >= 1688540400)
	Until      int64      `json:"until,omitempty"` // Unix timestamp
	Before     string     `json:"before,omitempty"`
	After      string     `json:"after,omitempty"`
}

SearchOptions represents options for keyword and topic tag search

type SearchProvider

type SearchProvider interface {
	// KeywordSearch searches posts by keyword
	KeywordSearch(ctx context.Context, query string, opts *SearchOptions) (*PostsResponse, error)
}

SearchProvider handles search operations

type SearchType

type SearchType string

SearchType defines the search behavior

const (
	// SearchTypeTop represents most popular search results (default)
	SearchTypeTop SearchType = "TOP"
	// SearchTypeRecent represents most recent search results
	SearchTypeRecent SearchType = "RECENT"
)

type TextPostContent

type TextPostContent struct {
	Text                    string          `json:"text"`
	LinkAttachment          string          `json:"link_attachment,omitempty"`
	PollAttachment          *PollAttachment `json:"poll_attachment,omitempty"`
	ReplyControl            ReplyControl    `json:"reply_control,omitempty"`
	ReplyTo                 string          `json:"reply_to_id,omitempty"`
	TopicTag                string          `json:"topic_tag,omitempty"`
	AllowlistedCountryCodes []string        `json:"allowlisted_country_codes,omitempty"`
	LocationID              string          `json:"location_id,omitempty"`
	AutoPublishText         bool            `json:"auto_publish_text,omitempty"`
	// QuotedPostID makes this a quote post when provided
	// Leave empty for regular text posts
	QuotedPostID string `json:"quoted_post_id,omitempty"`
}

TextPostContent represents content for text posts. Set QuotedPostID to create a quote post, or leave empty for regular text posts.

type Time

type Time struct {
	time.Time
}

Time is a custom time type that handles Threads API timestamp format. For timestamp format details, see: https://developers.facebook.com/docs/threads/reference

func (*Time) MarshalJSON

func (t *Time) MarshalJSON() ([]byte, error)

MarshalJSON implements json.Marshaler for Time

func (*Time) UnmarshalJSON

func (t *Time) UnmarshalJSON(data []byte) error

UnmarshalJSON implements json.Unmarshaler for Time

type TokenInfo

type TokenInfo struct {
	AccessToken string    `json:"access_token"`
	TokenType   string    `json:"token_type"`
	ExpiresAt   time.Time `json:"expires_at"`
	UserID      string    `json:"user_id"`
	CreatedAt   time.Time `json:"created_at"`
}

TokenInfo holds information about the current token

type TokenResponse

type TokenResponse struct {
	AccessToken string `json:"access_token"`
	TokenType   string `json:"token_type"`
	ExpiresIn   int64  `json:"expires_in,omitempty"`
	UserID      int64  `json:"user_id,omitempty"`
}

TokenResponse represents the response from token exchange endpoint. This structure is returned when exchanging an authorization code for an access token. The access token can then be used to authenticate API requests.

type TokenStorage

type TokenStorage interface {
	// Store saves a token to persistent storage.
	// Should return an error if the token cannot be saved.
	Store(token *TokenInfo) error

	// Load retrieves a token from persistent storage.
	// Should return an error if no token is found or cannot be loaded.
	Load() (*TokenInfo, error)

	// Delete removes a token from persistent storage.
	// Should return an error if the token cannot be deleted.
	Delete() error
}

TokenStorage interface for storing and retrieving tokens. The default MemoryTokenStorage loses tokens when the application terminates.

type TotalValue

type TotalValue struct {
	Value int `json:"value"`
}

TotalValue represents an aggregated metric value

type User

type User struct {
	ID             string `json:"id"`
	Username       string `json:"username"`
	Name           string `json:"name,omitempty"`            // Available with appropriate fields
	ProfilePicURL  string `json:"profile_pic_url,omitempty"` // Maps to threads_profile_picture_url
	Biography      string `json:"biography,omitempty"`       // Maps to threads_biography
	Website        string `json:"website,omitempty"`         // Not available in basic profile
	FollowersCount int    `json:"followers_count"`           // Not available in basic profile
	MediaCount     int    `json:"media_count"`               // Not available in basic profile
	IsVerified     bool   `json:"is_verified,omitempty"`     // Available with is_verified field
}

User represents a Threads user profile with app-scoped data. The user ID and other fields are specific to your app and cannot be used with other apps. Contains basic profile information accessible via API.

type UserID

type UserID string

UserID represents a unique identifier for a user

func ConvertToUserID

func ConvertToUserID(s string) UserID

ConvertToUserID safely converts a string to UserID

func (UserID) String

func (id UserID) String() string

String returns the string representation of the UserID

func (UserID) Valid

func (id UserID) Valid() bool

Valid checks if the UserID is not empty

type UserManager

type UserManager interface {
	// GetUser retrieves user profile information
	GetUser(ctx context.Context, userID UserID) (*User, error)

	// GetMe retrieves the authenticated user's profile
	GetMe(ctx context.Context) (*User, error)

	// GetUserFields retrieves specific user fields
	GetUserFields(ctx context.Context, userID UserID, fields []string) (*User, error)

	// LookupPublicProfile looks up a public profile by username
	LookupPublicProfile(ctx context.Context, username string) (*PublicUser, error)

	// GetPublicProfilePosts retrieves posts from a public profile
	GetPublicProfilePosts(ctx context.Context, username string, opts *PostsOptions) (*PostsResponse, error)
}

UserManager handles user profile operations

type ValidationError

type ValidationError struct {
	*BaseError
	Field string `json:"field,omitempty"`
}

ValidationError represents validation-related errors such as invalid parameters, missing required fields, or data that doesn't meet API requirements. The Field property indicates which field failed validation. Common HTTP status code: 400 (Bad Request).

func NewValidationError

func NewValidationError(code int, message, details, field string) *ValidationError

NewValidationError creates a new validation error with field information. The field parameter should indicate which input field failed validation. The code parameter should typically be 400.

type Validator

type Validator struct{}

Validator provides common validation methods

func NewValidator

func NewValidator() *Validator

NewValidator creates a new validator instance

func (*Validator) ValidateCarouselChildren

func (v *Validator) ValidateCarouselChildren(childrenCount int) error

ValidateCarouselChildren validates carousel children count

func (*Validator) ValidateCountryCodes

func (v *Validator) ValidateCountryCodes(codes []string) error

ValidateCountryCodes validates ISO 3166-1 alpha-2 country codes

func (*Validator) ValidateMediaURL

func (v *Validator) ValidateMediaURL(mediaURL, mediaType string) error

ValidateMediaURL validates media URLs for basic format and accessibility

func (*Validator) ValidatePaginationOptions

func (v *Validator) ValidatePaginationOptions(opts *PaginationOptions) error

ValidatePaginationOptions validates pagination parameters

func (*Validator) ValidatePostContent

func (v *Validator) ValidatePostContent(content interface{}, _ int) error

ValidatePostContent performs common validation for all post types

func (*Validator) ValidateSearchOptions

func (v *Validator) ValidateSearchOptions(opts *SearchOptions) error

ValidateSearchOptions validates search parameters

func (*Validator) ValidateTextLength

func (v *Validator) ValidateTextLength(text string, fieldName string) error

ValidateTextLength validates text doesn't exceed maximum length

func (*Validator) ValidateTopicTag

func (v *Validator) ValidateTopicTag(tag string) error

ValidateTopicTag validates a topic tag according to Threads API rules

type Value

type Value struct {
	Value   int    `json:"value"`
	EndTime string `json:"end_time,omitempty"`
}

Value represents a metric value with optional timestamp

type VideoPostContent

type VideoPostContent struct {
	Text                    string       `json:"text,omitempty"`
	VideoURL                string       `json:"video_url"`
	AltText                 string       `json:"alt_text,omitempty"`
	ReplyControl            ReplyControl `json:"reply_control,omitempty"`
	ReplyTo                 string       `json:"reply_to_id,omitempty"`
	TopicTag                string       `json:"topic_tag,omitempty"`
	AllowlistedCountryCodes []string     `json:"allowlisted_country_codes,omitempty"`
	LocationID              string       `json:"location_id,omitempty"`
	// QuotedPostID makes this a quote post when provided
	// Leave empty for regular image posts
	QuotedPostID string `json:"quoted_post_id,omitempty"`
}

VideoPostContent represents content for video posts. Set QuotedPostID to create a quote post, or leave empty for regular video posts.

Directories

Path Synopsis
examples
authentication command
Package main demonstrates the complete OAuth 2.0 authentication flow for the Threads API using the threads-go client library.
Package main demonstrates the complete OAuth 2.0 authentication flow for the Threads API using the threads-go client library.
basic-usage command
existing-token command
Package main demonstrates how to use the Threads API client with an existing access token.
Package main demonstrates how to use the Threads API client with an existing access token.
insights command
Package main demonstrates insights and analytics functionality using the Threads API.
Package main demonstrates insights and analytics functionality using the Threads API.
post-creation command
Package main demonstrates various post creation methods using the Threads API.
Package main demonstrates various post creation methods using the Threads API.
reply-management command
Package main demonstrates reply management functionality using the Threads API.
Package main demonstrates reply management functionality using the Threads API.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL