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 and persist the returned state in the user's session
authURL, state, err := client.GetAuthURL(config.Scopes)
// Direct user to authURL. On the callback, exchange the code AND verify state:
err = client.ExchangeCodeForToken(ctx, code, state, receivedState)
For complete API documentation: https://developers.facebook.com/docs/threads
Index ¶
- Constants
- func IsAPIError(err error) bool
- func IsAuthenticationError(err error) bool
- func IsNetworkError(err error) bool
- func IsRateLimitError(err error) bool
- func IsTransientError(err error) bool
- func IsValidationError(err error) bool
- type APIError
- type AccountInsightMetric
- type AccountInsightsOptions
- type AppAccessTokenResponse
- type ApprovalStatus
- type AuthenticationError
- type Authenticator
- type BaseError
- type CarouselPostContent
- type ChildPost
- type ChildrenData
- type Client
- func (c *Client) ApprovePendingReply(ctx context.Context, replyID PostID) error
- func (c *Client) ClearToken() error
- func (c *Client) Clone() (*Client, error)
- func (c *Client) CloneWithConfig(newConfig *Config) (*Client, error)
- func (c *Client) CreateCarouselPost(ctx context.Context, content *CarouselPostContent) (*Post, error)
- func (c *Client) CreateImagePost(ctx context.Context, content *ImagePostContent) (*Post, error)
- func (c *Client) CreateMediaContainer(ctx context.Context, mediaType, mediaURL, altText string) (ContainerID, error)
- func (c *Client) CreateQuotePost(ctx context.Context, content interface{}, quotedPostID string) (*Post, error)
- func (c *Client) CreateReply(ctx context.Context, content *PostContent) (*Post, error)
- func (c *Client) CreateTextPost(ctx context.Context, content *TextPostContent) (*Post, error)
- func (c *Client) CreateVideoPost(ctx context.Context, content *VideoPostContent) (*Post, error)
- func (c *Client) DebugToken(ctx context.Context, inputToken string) (*DebugTokenResponse, error)
- func (c *Client) DeletePost(ctx context.Context, postID PostID) (string, error)
- func (c *Client) DeletePostWithConfirmation(ctx context.Context, postID PostID, confirmationCallback func(post *Post) bool) (string, error)
- func (c *Client) DisableRateLimiting()
- func (c *Client) EnableRateLimiting()
- func (c *Client) EnsureValidToken(ctx context.Context) error
- func (c *Client) ExchangeCodeForToken(ctx context.Context, code, expectedState, receivedState string) error
- func (c *Client) GetAccessToken() string
- func (c *Client) GetAccountInsights(ctx context.Context, userID UserID, metrics []string, period string) (*InsightsResponse, error)
- func (c *Client) GetAccountInsightsWithOptions(ctx context.Context, userID UserID, opts *AccountInsightsOptions) (*InsightsResponse, error)
- func (c *Client) GetAppAccessToken(ctx context.Context) (*AppAccessTokenResponse, error)
- func (c *Client) GetAppAccessTokenShorthand() string
- func (c *Client) GetAuthURL(scopes []string) (authURL, state string, err error)
- func (c *Client) GetAvailableAccountInsightMetrics() []AccountInsightMetric
- func (c *Client) GetAvailableFollowerDemographicsBreakdowns() []FollowerDemographicsBreakdown
- func (c *Client) GetAvailableInsightPeriods() []InsightPeriod
- func (c *Client) GetAvailablePostInsightMetrics() []PostInsightMetric
- func (c *Client) GetConfig() *Config
- func (c *Client) GetContainerStatus(ctx context.Context, containerID ContainerID) (*ContainerStatus, error)
- func (c *Client) GetConversation(ctx context.Context, postID PostID, opts *RepliesOptions) (*RepliesResponse, error)
- func (c *Client) GetLocation(ctx context.Context, locationID LocationID) (*Location, error)
- func (c *Client) GetLongLivedToken(ctx context.Context) error
- func (c *Client) GetMe(ctx context.Context) (*User, error)
- func (c *Client) GetPendingReplies(ctx context.Context, postID PostID, opts *PendingRepliesOptions) (*RepliesResponse, error)
- func (c *Client) GetPost(ctx context.Context, postID PostID) (*Post, error)
- func (c *Client) GetPostInsights(ctx context.Context, postID PostID, metrics []string) (*InsightsResponse, error)
- func (c *Client) GetPostInsightsWithOptions(ctx context.Context, postID PostID, opts *PostInsightsOptions) (*InsightsResponse, error)
- func (c *Client) GetPublicProfilePosts(ctx context.Context, username string, opts *PostsOptions) (*PostsResponse, error)
- func (c *Client) GetPublishingLimits(ctx context.Context) (*PublishingLimits, error)
- func (c *Client) GetRateLimitStatus() RateLimitStatus
- func (c *Client) GetReplies(ctx context.Context, postID PostID, opts *RepliesOptions) (*RepliesResponse, error)
- func (c *Client) GetTokenDebugInfo() map[string]interface{}
- func (c *Client) GetTokenInfo() *TokenInfo
- func (c *Client) GetUser(ctx context.Context, userID UserID) (*User, error)
- func (c *Client) GetUserFields(ctx context.Context, userID UserID, fields []string) (*User, error)
- func (c *Client) GetUserGhostPosts(ctx context.Context, userID UserID, opts *PaginationOptions) (*PostsResponse, error)
- func (c *Client) GetUserMentions(ctx context.Context, userID UserID, opts *PostsOptions) (*PostsResponse, error)
- func (c *Client) GetUserPosts(ctx context.Context, userID UserID, opts *PaginationOptions) (*PostsResponse, error)
- func (c *Client) GetUserPostsWithOptions(ctx context.Context, userID UserID, opts *PostsOptions) (*PostsResponse, error)
- func (c *Client) GetUserReplies(ctx context.Context, userID UserID, opts *PostsOptions) (*RepliesResponse, error)
- func (c *Client) HideReply(ctx context.Context, replyID PostID) error
- func (c *Client) IgnorePendingReply(ctx context.Context, replyID PostID) error
- func (c *Client) IsAuthenticated() bool
- func (c *Client) IsNearRateLimit(threshold float64) bool
- func (c *Client) IsRateLimited() bool
- func (c *Client) IsTokenExpired() bool
- func (c *Client) IsTokenExpiringSoon(within time.Duration) bool
- func (c *Client) KeywordSearch(ctx context.Context, query string, opts *SearchOptions) (*PostsResponse, error)
- func (c *Client) LoadTokenFromStorage() error
- func (c *Client) LookupPublicProfile(ctx context.Context, username string) (*PublicUser, error)
- func (c *Client) RefreshToken(ctx context.Context) error
- func (c *Client) ReplyToPost(ctx context.Context, postID PostID, content *PostContent) (*Post, error)
- func (c *Client) RepostPost(ctx context.Context, postID PostID) (*Post, error)
- func (c *Client) SearchLocations(ctx context.Context, query string, latitude, longitude *float64) (*LocationSearchResponse, error)
- func (c *Client) SetTokenFromDebugInfo(accessToken string, debugResp *DebugTokenResponse) error
- func (c *Client) SetTokenInfo(tokenInfo *TokenInfo) error
- func (c *Client) TestAPICall(method, path string, params map[string]string) (*Response, error)
- func (c *Client) UnhideReply(ctx context.Context, replyID PostID) error
- func (c *Client) UpdateConfig(newConfig *Config) error
- func (c *Client) ValidateCarouselChildren(childrenIDs []string) error
- func (c *Client) ValidateCarouselPostContent(content *CarouselPostContent) error
- func (c *Client) ValidateCountryCodes(codes []string) error
- func (c *Client) ValidateImagePostContent(content *ImagePostContent) error
- func (c *Client) ValidateTextPostContent(content *TextPostContent) error
- func (c *Client) ValidateToken() error
- func (c *Client) ValidateTopicTag(tag string) error
- func (c *Client) ValidateVideoPostContent(content *VideoPostContent) error
- func (c *Client) WaitForRateLimit(ctx context.Context) error
- type ClientInterface
- type Config
- type ConfigValidator
- type ContainerBuilder
- func (b *ContainerBuilder) AddChild(childID string) *ContainerBuilder
- func (b *ContainerBuilder) Build() url.Values
- func (b *ContainerBuilder) SetAllowlistedCountryCodes(codes []string) *ContainerBuilder
- func (b *ContainerBuilder) SetAltText(altText string) *ContainerBuilder
- func (b *ContainerBuilder) SetAutoPublishText(autoPublish bool) *ContainerBuilder
- func (b *ContainerBuilder) SetChildren(childIDs []string) *ContainerBuilder
- func (b *ContainerBuilder) SetEnableReplyApprovals(enable bool) *ContainerBuilder
- func (b *ContainerBuilder) SetGIFAttachment(gifAttachment *GIFAttachment) *ContainerBuilder
- func (b *ContainerBuilder) SetImageURL(imageURL string) *ContainerBuilder
- func (b *ContainerBuilder) SetIsCarouselItem(isCarouselItem bool) *ContainerBuilder
- func (b *ContainerBuilder) SetIsGhostPost(isGhostPost bool) *ContainerBuilder
- func (b *ContainerBuilder) SetIsSpoilerMedia(isSpoilerMedia bool) *ContainerBuilder
- func (b *ContainerBuilder) SetLinkAttachment(linkURL string) *ContainerBuilder
- func (b *ContainerBuilder) SetLocationID(locationID string) *ContainerBuilder
- func (b *ContainerBuilder) SetMediaType(mediaType string) *ContainerBuilder
- func (b *ContainerBuilder) SetPollAttachment(poll *PollAttachment) *ContainerBuilder
- func (b *ContainerBuilder) SetQuotePostID(quotePostID string) *ContainerBuilder
- func (b *ContainerBuilder) SetReplyControl(replyControl ReplyControl) *ContainerBuilder
- func (b *ContainerBuilder) SetReplyTo(replyToID string) *ContainerBuilder
- func (b *ContainerBuilder) SetText(text string) *ContainerBuilder
- func (b *ContainerBuilder) SetTextAttachment(textAttachment *TextAttachment) *ContainerBuilder
- func (b *ContainerBuilder) SetTextEntities(entities []TextEntity) *ContainerBuilder
- func (b *ContainerBuilder) SetTopicTag(tag string) *ContainerBuilder
- func (b *ContainerBuilder) SetVideoURL(videoURL string) *ContainerBuilder
- type ContainerID
- type ContainerStatus
- type DebugTokenResponse
- type FollowerDemographicsBreakdown
- type GIFAttachment
- type GIFProvider
- type HTTPClient
- func (h *HTTPClient) DELETE(path string, accessToken string) (*Response, error)
- func (h *HTTPClient) Do(opts *RequestOptions, accessToken string) (*Response, error)
- func (h *HTTPClient) GET(path string, queryParams url.Values, accessToken string) (*Response, error)
- func (h *HTTPClient) POST(path string, body interface{}, accessToken string) (*Response, error)
- func (h *HTTPClient) PUT(path string, body interface{}, accessToken string) (*Response, error)
- type HideStatus
- type ImagePostContent
- type Insight
- type InsightPeriod
- type InsightsProvider
- type InsightsResponse
- type Location
- type LocationID
- type LocationManager
- type LocationSearchResponse
- type Logger
- type LongLivedTokenResponse
- type MemoryTokenStorage
- type NetworkError
- type PaginationOptions
- type Paging
- type PagingCursors
- type PendingRepliesOptions
- type PollAttachment
- type PollResult
- type Post
- type PostContent
- type PostCreator
- type PostDeleter
- type PostID
- type PostInsightMetric
- type PostInsightsOptions
- type PostIterator
- type PostManager
- type PostOwner
- type PostReader
- type PostValidator
- type PostsOptions
- type PostsResponse
- type PublicUser
- type PublishingLimits
- type QuotaConfig
- type RateLimitController
- type RateLimitError
- type RateLimitInfo
- type RateLimitStatus
- type RateLimiter
- func (rl *RateLimiter) GetQueueLength() int
- func (rl *RateLimiter) GetStatus() RateLimitStatus
- func (rl *RateLimiter) IsNearLimit(threshold float64) bool
- func (rl *RateLimiter) IsRateLimited() bool
- func (rl *RateLimiter) MarkRateLimited(resetTime time.Time)
- func (rl *RateLimiter) ProcessQueue(ctx context.Context, processor func() error) error
- func (rl *RateLimiter) QueueRequest(ctx context.Context) error
- func (rl *RateLimiter) Reset()
- func (rl *RateLimiter) ShouldWait() bool
- func (rl *RateLimiter) UpdateFromHeaders(rateLimitInfo *RateLimitInfo)
- func (rl *RateLimiter) Wait(ctx context.Context) error
- type RateLimiterConfig
- type RecentSearch
- type RepliesOptions
- type RepliesResponse
- type ReplyAudience
- type ReplyControl
- type ReplyIterator
- type ReplyManager
- type RepostContent
- type RequestOptions
- type Response
- type RetryConfig
- type SearchIterator
- type SearchMode
- type SearchOptions
- type SearchProvider
- type SearchType
- type TextAttachment
- type TextEntitiesResponse
- type TextEntity
- type TextPostContent
- type TextStylingInfo
- type Time
- type TokenInfo
- type TokenResponse
- type TokenStorage
- type TotalValue
- type User
- type UserID
- type UserManager
- type ValidationError
- type Validator
- func (v *Validator) ValidateAltText(altText string) error
- func (v *Validator) ValidateCarouselChildren(childrenCount int) error
- func (v *Validator) ValidateCountryCodes(codes []string) error
- func (v *Validator) ValidateGIFAttachment(gifAttachment *GIFAttachment) error
- func (v *Validator) ValidateLinkCount(text string, linkAttachmentURL string) error
- func (v *Validator) ValidateMediaURL(mediaURL, mediaType string) error
- func (v *Validator) ValidatePaginationOptions(opts *PaginationOptions) error
- func (v *Validator) ValidatePollAttachment(poll *PollAttachment) error
- func (v *Validator) ValidatePostContent(content interface{}, _ int) error
- func (v *Validator) ValidatePostsOptions(opts *PostsOptions) error
- func (v *Validator) ValidateSearchOptions(opts *SearchOptions) error
- func (v *Validator) ValidateTextAttachment(textAttachment *TextAttachment) error
- func (v *Validator) ValidateTextEntities(entities []TextEntity) error
- func (v *Validator) ValidateTextLength(text string, fieldName string) error
- func (v *Validator) ValidateTopicTag(tag string) error
- type Value
- type VideoPostContent
Constants ¶
const ( // Text limits MaxTextLength = 500 // Maximum characters for post text MaxTextAttachmentLength = 10000 // Maximum characters for text attachment plaintext MaxTextEntities = 10 // Maximum text spoiler entities per post MaxLinks = 5 // Maximum number of links in a post // 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 // Reply processing ReplyPublishDelay = 10 * time.Second // Recommended delay before publishing reply // Poll limits MinPollOptions = 2 // Minimum poll options (A and B required) MaxPollOptions = 4 // Maximum poll options MaxPollOptionLength = 25 // Maximum characters per poll option // Alt text limits MaxAltTextLength = 1000 // Maximum characters for alt text // Search constraints MinSearchTimestamp = 1688540400 // Minimum timestamp for search queries (July 5, 2023) // Library version Version = "1.8.0" // HTTP client defaults DefaultHTTPTimeout = 30 * time.Second // Default HTTP request timeout DefaultUserAgent = "threads-go/" + Version )
API Limits
const ( // Post fields PostExtendedFields = "" /* 506-byte string literal not displayed */ // Ghost Post fields GhostPostFields = "" /* 156-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 = "" /* 320-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 = "" /* 166-byte string literal not displayed */ )
Field Sets for API requests
const ( ContainerStatusInProgress = "IN_PROGRESS" ContainerStatusFinished = "FINISHED" ContainerStatusPublished = "PUBLISHED" ContainerStatusError = "ERROR" ContainerStatusExpired = "EXPIRED" // Container polling configuration DefaultContainerPollMaxAttempts = 30 // Maximum number of polling attempts DefaultContainerPollInterval = 1 * time.Second // Interval between polling attempts )
Container Status values
const ( MediaTypeText = "TEXT" MediaTypeImage = "IMAGE" MediaTypeVideo = "VIDEO" MediaTypeCarousel = "CAROUSEL" // Response media types (returned by the API when retrieving posts) MediaTypeResponseText = "TEXT_POST" MediaTypeResponseCarousel = "CAROUSEL_ALBUM" MediaTypeAudio = "AUDIO" MediaTypeRepostFacade = "REPOST_FACADE" )
Media Types
const ( ContainerErrFailedDownloadingVideo = "FAILED_DOWNLOADING_VIDEO" ContainerErrFailedProcessingAudio = "FAILED_PROCESSING_AUDIO" ContainerErrFailedProcessingVideo = "FAILED_PROCESSING_VIDEO" ContainerErrInvalidAspectRatio = "INVALID_ASPEC_RATIO" // Note: API has typo "ASPEC" ContainerErrInvalidBitRate = "INVALID_BIT_RATE" ContainerErrInvalidDuration = "INVALID_DURATION" ContainerErrInvalidFrameRate = "INVALID_FRAME_RATE" ContainerErrInvalidAudioChannels = "INVALID_AUDIO_CHANNELS" ContainerErrInvalidAudioChannelLayout = "INVALID_AUDIO_CHANNEL_LAYOUT" ContainerErrUnknown = "UNKNOWN" )
Container error messages returned by the API
const ( ErrEmptyPostID = "Post ID is required" ErrEmptyUserID = "User ID is required" ErrEmptyContainerID = "Container ID is required" ErrEmptySearchQuery = "Search query is required" )
Error messages
const ( // ErrCodeLinkLimitExceeded is returned when a post contains more than 5 unique links. // This error occurs during media container creation (POST /{threads-user-id}/threads). // Reduce the number of unique links to 5 or fewer to resolve. ErrCodeLinkLimitExceeded = "THREADS_API__LINK_LIMIT_EXCEEDED" // ErrCodeFeatureNotAvailable is returned when a feature is not available for the user. // For example, geo-gating requires feature approval before it can be used. ErrCodeFeatureNotAvailable = "THREADS_API__FEATURE_NOT_AVAILABLE" // ErrCodeGeoGatingInvalidCountryCodes is returned when invalid country codes // are provided for geo-gated posts. ErrCodeGeoGatingInvalidCountryCodes = "THREADS_API__GEO_GATING_INVALID_COUNTRY_CODES" )
API Error Codes returned by the Threads API
const (
BaseAPIURL = "https://graph.threads.net"
)
API Endpoints
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 ¶
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 ¶
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 ¶
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 ¶
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 IsTransientError ¶ added in v1.7.0
IsTransientError checks if an error is marked as transient by the API. Transient errors are temporary and the request can be retried. Uses errors.As to support wrapped errors, consistent with other IsXxx helpers.
func IsValidationError ¶
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 ¶
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 ¶
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. // Note: This metric is noted as "in development" in the API documentation. 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 AppAccessTokenResponse ¶ added in v1.8.0
type AppAccessTokenResponse struct {
AccessToken string `json:"access_token"`
TokenType string `json:"token_type"`
}
AppAccessTokenResponse represents the response from the client_credentials token endpoint. Unlike user token responses, app access tokens do not include expires_in or user_id fields.
type ApprovalStatus ¶ added in v1.5.0
type ApprovalStatus string
ApprovalStatus represents the approval status filter for pending replies
const ( // ApprovalStatusPending filters to show only pending replies ApprovalStatusPending ApprovalStatus = "pending" // ApprovalStatusIgnored filters to show only ignored replies ApprovalStatusIgnored ApprovalStatus = "ignored" )
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 and
// returns the random state embedded in it. Callers MUST persist the state
// and pass it as expectedState on the callback to prevent CSRF / code
// fixation (see Client.GetAuthURL for details).
GetAuthURL(scopes []string) (authURL, state string, err error)
// ExchangeCodeForToken exchanges an authorization code for an access
// token. expectedState is the value returned by GetAuthURL (persisted in
// the user's session); receivedState is the state echoed by the provider
// on the callback. A mismatch is refused before any network call.
ExchangeCodeForToken(ctx context.Context, code, expectedState, receivedState 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{}
// GetAppAccessToken generates an app access token via the client_credentials flow
GetAppAccessToken(ctx context.Context) (*AppAccessTokenResponse, error)
// GetAppAccessTokenShorthand returns the TH|APP_ID|APP_SECRET shorthand token
GetAppAccessTokenShorthand() string
}
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"`
IsTransient bool `json:"is_transient,omitempty"`
HTTPStatusCode int `json:"http_status_code,omitempty"`
ErrorSubcode int `json:"error_subcode,omitempty"`
}
BaseError represents a base error type for all Threads API errors. For error handling patterns, see: https://developers.facebook.com/docs/threads/troubleshooting
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"`
// TextEntities marks specific text ranges as spoilers
// Max 10 entities per post. Each entity specifies offset and length of spoiler text.
TextEntities []TextEntity `json:"text_entities,omitempty"`
// IsSpoilerMedia marks ALL carousel media (images/videos) as spoilers
IsSpoilerMedia bool `json:"is_spoiler_media,omitempty"`
// EnableReplyApprovals enables reply approvals on the post; replies must be approved before publishing
EnableReplyApprovals bool `json:"enable_reply_approvals,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 ¶
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 ¶
NewClientFromEnv creates a new Threads API client using environment variables. This is a convenience function that combines NewConfigFromEnv and NewClient.
func NewClientWithToken ¶
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) ApprovePendingReply ¶ added in v1.5.0
ApprovePendingReply approves a pending reply, making it publicly visible
func (*Client) ClearToken ¶
ClearToken removes the current token from the client and storage
func (*Client) Clone ¶
Clone creates a new client instance with the same configuration but separate token storage and state
func (*Client) CloneWithConfig ¶
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 ¶
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 ¶
CreateReply creates a reply to a specific post or reply
func (*Client) CreateTextPost ¶
CreateTextPost creates a new text post on Threads
func (*Client) CreateVideoPost ¶
CreateVideoPost creates a new video post on Threads
func (*Client) DebugToken ¶
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 ¶
DeletePost deletes a specific post by ID with proper validation and confirmation. Returns the deleted post ID as reported by the API. If the API response cannot be parsed, the returned ID will be an empty string; a non-nil error is only returned when the HTTP request itself fails or the server returns a non-200 status. Note: The API enforces a limit of 100 deletes per 24-hour window. Check PublishingLimits.DeleteQuotaUsage via GetPublishingLimits to monitor usage. The threads_delete permission scope is required for this endpoint.
func (*Client) DeletePostWithConfirmation ¶
func (c *Client) DeletePostWithConfirmation(ctx context.Context, postID PostID, confirmationCallback func(post *Post) bool) (string, 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. The change is propagated to the underlying HTTPClient so it takes effect on the request path (HTTPClient holds its own rate-limiter reference).
func (*Client) EnableRateLimiting ¶
func (c *Client) EnableRateLimiting()
EnableRateLimiting re-enables rate limiting with a new rate limiter and installs it on the underlying HTTPClient.
func (*Client) EnsureValidToken ¶
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, expectedState, receivedState string) error
ExchangeCodeForToken exchanges an authorization code for an access token. This should be called after the user authorizes your app and the provider redirects back with a code and state.
expectedState is the state value that was returned by GetAuthURL and persisted in the user's session; receivedState is the state query parameter echoed on the callback. Both must be non-empty and must match (compared in constant time). A mismatch indicates an OAuth CSRF / authorization-code fixation attack and the exchange is refused before any network call.
The resulting token is automatically stored in the client and token storage.
func (*Client) GetAccessToken ¶
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) GetAppAccessToken ¶ added in v1.8.0
func (c *Client) GetAppAccessToken(ctx context.Context) (*AppAccessTokenResponse, error)
GetAppAccessToken generates an app access token via the client_credentials OAuth flow. Unlike user access tokens, the returned token is NOT stored in the client — app tokens serve a different purpose and should be managed separately by the caller. This requires ClientID and ClientSecret to be set in the client configuration.
NOTE: The Threads API requires GET for this endpoint (not the POST + body approach specified in RFC 6749 §4.4). As a result, client_secret appears in the request URL. Only call this from a server-side environment.
func (*Client) GetAppAccessTokenShorthand ¶ added in v1.8.0
GetAppAccessTokenShorthand returns the shorthand app token in the form TH|<APP_ID>|<APP_SECRET>. This can be used directly as an access token for certain API operations without making an API call. See the Threads API documentation for which endpoints accept this format. Returns an empty string if ClientID or ClientSecret are not configured.
func (*Client) GetAuthURL ¶
GetAuthURL generates the authorization URL for the OAuth 2.0 flow along with the random state parameter embedded in it. Callers MUST persist the returned state in the user's session (e.g. a signed cookie) and pass it as expectedState to ExchangeCodeForToken when the provider redirects back, comparing it against the state echoed on the callback. This is required by RFC 6749 §10.12 and OAuth 2.0 Security BCP §4.7 to prevent login/CSRF and authorization-code fixation attacks.
If scopes are not provided, defaults to threads_basic and threads_content_publish. Returns an error if the system's secure random source is unavailable; in that case no URL is returned so callers cannot accidentally issue a flow with a guessable state (fail closed).
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) GetContainerStatus ¶ added in v1.0.4
func (c *Client) GetContainerStatus(ctx context.Context, containerID ContainerID) (*ContainerStatus, error)
GetContainerStatus retrieves the status of a media container This is useful for checking if a video or image container has finished processing before attempting to publish it. Returns container status information including: - ID: The container ID - Status: Current status (IN_PROGRESS, FINISHED, PUBLISHED, ERROR, EXPIRED) - ErrorMessage: Error details if status is ERROR
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 ¶
GetLocation retrieves location details
func (*Client) GetLongLivedToken ¶
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) GetPendingReplies ¶ added in v1.5.0
func (c *Client) GetPendingReplies(ctx context.Context, postID PostID, opts *PendingRepliesOptions) (*RepliesResponse, error)
GetPendingReplies retrieves pending replies for a post with reply approvals enabled
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. If rate limiting has been disabled via DisableRateLimiting, returns a zero RateLimitStatus.
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 ¶
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 ¶
GetTokenInfo returns the current token information in a thread-safe manner
func (*Client) GetUserFields ¶
GetUserFields retrieves specific fields for a user
func (*Client) GetUserGhostPosts ¶ added in v1.2.0
func (c *Client) GetUserGhostPosts(ctx context.Context, userID UserID, opts *PaginationOptions) (*PostsResponse, error)
GetUserGhostPosts retrieves ghost posts from a specific user. Ghost posts are text-only posts that expire after 24 hours.
func (*Client) GetUserMentions ¶
func (c *Client) GetUserMentions(ctx context.Context, userID UserID, opts *PostsOptions) (*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) IgnorePendingReply ¶ added in v1.5.0
IgnorePendingReply ignores a pending reply (it can still be approved later)
func (*Client) IsAuthenticated ¶
IsAuthenticated returns true if the client has a valid access token
func (*Client) IsNearRateLimit ¶
IsNearRateLimit returns true if the client is close to hitting rate limits. Returns false if rate limiting has been disabled.
func (*Client) IsRateLimited ¶
IsRateLimited returns true if the client is currently rate limited by the API. Returns false if rate limiting has been disabled.
func (*Client) IsTokenExpired ¶
IsTokenExpired returns true if the current token is expired
func (*Client) IsTokenExpiringSoon ¶
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 ¶
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 ¶
LookupPublicProfile looks up a public profile by username
func (*Client) RefreshToken ¶
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 ¶
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 ¶
SetTokenInfo sets the token information in a thread-safe manner
func (*Client) TestAPICall ¶
TestAPICall makes a test API call (for testing purposes only)
func (*Client) UnhideReply ¶
UnhideReply unhides a specific reply that was previously hidden
func (*Client) UpdateConfig ¶
UpdateConfig updates the client configuration with validation Note: This does not affect already established connections
func (*Client) ValidateCarouselChildren ¶
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 ¶
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 ¶
ValidateToken validates the current token by making a test API call
func (*Client) ValidateTopicTag ¶
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
type ClientInterface ¶
type ClientInterface interface {
Authenticator
PostManager
UserManager
ReplyManager
InsightsProvider
LocationManager
SearchProvider
RateLimitController
}
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 ¶
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
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) SetEnableReplyApprovals ¶ added in v1.5.0
func (b *ContainerBuilder) SetEnableReplyApprovals(enable bool) *ContainerBuilder
SetEnableReplyApprovals enables reply approvals on the post
func (*ContainerBuilder) SetGIFAttachment ¶ added in v1.1.0
func (b *ContainerBuilder) SetGIFAttachment(gifAttachment *GIFAttachment) *ContainerBuilder
SetGIFAttachment adds a GIF attachment to the post Can only be used with TEXT-only posts (not with image, video, or carousel posts) Supported providers: TENOR (deprecated, sunset March 31, 2026) and GIPHY
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) SetIsGhostPost ¶ added in v1.2.0
func (b *ContainerBuilder) SetIsGhostPost(isGhostPost bool) *ContainerBuilder
SetIsGhostPost marks the post as a ghost post (text-only, expires in 24h, no replies allowed). Ghost posts are only supported for TEXT media type. If the builder's media_type is already set to a non-TEXT value this call is silently ignored; if a non-TEXT type is set after this call, SetMediaType will automatically clear the flag.
func (*ContainerBuilder) SetIsSpoilerMedia ¶ added in v1.0.4
func (b *ContainerBuilder) SetIsSpoilerMedia(isSpoilerMedia bool) *ContainerBuilder
SetIsSpoilerMedia marks media (IMAGE, VIDEO, CAROUSEL) as spoilers For CAROUSEL media type, this marks ALL media in the carousel as spoilers
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. If a non-TEXT type is set, any previously set is_ghost_post flag is cleared since ghost posts are only supported for TEXT.
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) SetTextAttachment ¶ added in v1.0.4
func (b *ContainerBuilder) SetTextAttachment(textAttachment *TextAttachment) *ContainerBuilder
SetTextAttachment adds a text attachment to the post Can only be used with TEXT-only posts (not with polls or other media) Max 10,000 characters in the plaintext field
func (*ContainerBuilder) SetTextEntities ¶ added in v1.0.4
func (b *ContainerBuilder) SetTextEntities(entities []TextEntity) *ContainerBuilder
SetTextEntities adds text spoiler entities Marks specific text ranges as spoilers using offset and length Max 10 entities per post
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 ContainerStatus ¶ added in v1.0.4
type ContainerStatus struct {
ID string `json:"id"`
Status string `json:"status"`
ErrorMessage string `json:"error_message,omitempty"`
}
ContainerStatus represents the status of a media container Used to check processing status before publishing posts
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 GIFAttachment ¶ added in v1.1.0
type GIFAttachment struct {
// GIFID is the ID of the GIF from the provider's API response
GIFID string `json:"gif_id"`
// Provider is the GIF provider ("TENOR" or "GIPHY")
Provider GIFProvider `json:"provider"`
}
GIFAttachment represents a GIF attachment for text posts GIFs can only be attached to text-only posts (not image, video, or carousel posts) Supported providers: TENOR (deprecated, sunset March 31, 2026) and GIPHY
type GIFProvider ¶ added in v1.1.0
type GIFProvider string
GIFProvider represents supported GIF providers
const ( // GIFProviderTenor is the Tenor GIF provider. // Deprecated: Tenor API will be sunsetted by March 31, 2026. Use GIFProviderGiphy instead. GIFProviderTenor GIFProvider = "TENOR" // GIFProviderGiphy is the GIPHY GIF provider GIFProviderGiphy GIFProvider = "GIPHY" )
type HTTPClient ¶
type HTTPClient struct {
// contains filtered or unexported fields
}
HTTPClient wraps the standard HTTP client with additional functionality.
rateLimiter is stored in an atomic.Pointer so Client.DisableRateLimiting and Client.EnableRateLimiting can swap it safely under a concurrent request path without tearing. Readers must go through getRateLimiter().
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
type HideStatus ¶ added in v1.8.0
type HideStatus string
HideStatus represents the visibility status of a reply
const ( HideStatusNotHushed HideStatus = "NOT_HUSHED" HideStatusUnhushed HideStatus = "UNHUSHED" HideStatusHidden HideStatus = "HIDDEN" HideStatusCovered HideStatus = "COVERED" HideStatusBlocked HideStatus = "BLOCKED" HideStatusRestricted HideStatus = "RESTRICTED" )
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"`
// TextEntities marks specific text ranges as spoilers
// Max 10 entities per post. Each entity specifies offset and length of spoiler text.
TextEntities []TextEntity `json:"text_entities,omitempty"`
// IsSpoilerMedia marks the image as a spoiler
IsSpoilerMedia bool `json:"is_spoiler_media,omitempty"`
// EnableReplyApprovals enables reply approvals on the post; replies must be approved before publishing
EnableReplyApprovals bool `json:"enable_reply_approvals,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 ¶
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.
func NewNetworkErrorWithCause ¶ added in v1.7.0
func NewNetworkErrorWithCause(code int, message, details string, temporary bool, cause error) *NetworkError
NewNetworkErrorWithCause creates a new network error that wraps an underlying cause. The cause is accessible via Unwrap(), enabling errors.Is/errors.As on the original error.
func (*NetworkError) Unwrap ¶ added in v1.7.0
func (e *NetworkError) Unwrap() error
Unwrap returns the underlying error, enabling errors.Is/errors.As to inspect the original cause (e.g., context.Canceled).
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 PendingRepliesOptions ¶ added in v1.5.0
type PendingRepliesOptions 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 (default), false for chronological
ApprovalStatus ApprovalStatus `json:"approval_status,omitempty"` // Filter by approval status: "pending" or "ignored"
}
PendingRepliesOptions represents options for retrieving pending replies
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 ReplyAudience `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 HideStatus `json:"hide_status,omitempty"`
TopicTag string `json:"topic_tag,omitempty"`
GhostPostStatus string `json:"ghost_post_status,omitempty"`
// GhostPostExpirationTimestamp is only present for ghost posts (ghost_post_status != "").
// omitempty is safe here: the zero Time value is omitted on marshal, and absent fields
// are left at zero on unmarshal.
GhostPostExpirationTimestamp Time `json:"ghost_post_expiration_timestamp,omitempty"`
// IsVerified indicates if the post author's profile is verified on Threads.
// Available for replies and mentions. For conversations, only available on direct replies.
IsVerified bool `json:"is_verified,omitempty"`
// ProfilePictureURL is the URL of the post author's profile picture on Threads.
// Available for replies and mentions. For conversations, only available on direct replies.
ProfilePictureURL string `json:"profile_picture_url,omitempty"`
// ReplyApprovalStatus is the approval status of a pending reply ("pending" or "ignored")
ReplyApprovalStatus string `json:"reply_approval_status,omitempty"`
IsSpoilerMedia bool `json:"is_spoiler_media,omitempty"`
TextEntities *TextEntitiesResponse `json:"text_entities,omitempty"`
TextAttachment *TextAttachment `json:"text_attachment,omitempty"`
AllowlistedCountryCodes []string `json:"allowlisted_country_codes,omitempty"`
LocationID string `json:"location_id,omitempty"`
Location *Location `json:"location,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)
// GetContainerStatus retrieves the status of a media container
GetContainerStatus(ctx context.Context, containerID ContainerID) (*ContainerStatus, error)
}
PostCreator handles creation of different post types
type PostDeleter ¶
type PostDeleter interface {
// DeletePost deletes a specific post and returns the deleted post ID
DeletePost(ctx context.Context, postID PostID) (string, error)
// DeletePostWithConfirmation deletes a post with confirmation and returns the deleted post ID
DeletePostWithConfirmation(ctx context.Context, postID PostID, confirmationCallback func(post *Post) bool) (string, error)
}
PostDeleter handles post deletion operations
type PostID ¶
type PostID string
PostID represents a unique identifier for a post
func ConvertToPostID ¶
ConvertToPostID safely converts a string to PostID
type PostInsightMetric ¶
type PostInsightMetric string
PostInsightMetric represents available post insight metrics
const ( // PostInsightViews represents the number of times a post was viewed. // Note: This metric is noted as "in development" in the API documentation. 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" // Note: This metric is noted as "in development" in the API documentation. 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 *PostsOptions) (*PostsResponse, error)
// GetUserGhostPosts retrieves ghost posts from a specific user
GetUserGhostPosts(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 ¶
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"`
SearchQuotaUsage int `json:"search_quota_usage"`
SearchConfig QuotaConfig `json:"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.
Rate limit defaults per the API documentation:
- Posts: 250 per 24 hours
- Replies: 1000 per 24 hours
- Deletes: 100 per 24 hours
- Search: 2200 per 24 hours
- Location search: 500 per 24 hours
Additionally, API calls are subject to a rate limit calculated as 4800 × Number of Impressions (minimum 10 impressions), with separate CPU-time based limits.
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 ¶
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
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 RecentSearch ¶ added in v1.8.0
RecentSearch represents a recently searched keyword with its timestamp
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 ¶
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 ReplyAudience ¶ added in v1.8.0
type ReplyAudience string
ReplyAudience represents the audience restriction returned by the API when reading posts. This is the read-side counterpart to ReplyControl (which is used for creation). The API returns reply_audience in UPPERCASE values.
const ( ReplyAudienceEveryone ReplyAudience = "EVERYONE" ReplyAudienceAccountsYouFollow ReplyAudience = "ACCOUNTS_YOU_FOLLOW" ReplyAudienceMentionedOnly ReplyAudience = "MENTIONED_ONLY" ReplyAudienceParentPostAuthorOnly ReplyAudience = "PARENT_POST_AUTHOR_ONLY" ReplyAudienceFollowersOnly ReplyAudience = "FOLLOWERS_ONLY" )
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 ¶
func (r *ReplyIterator) Next(ctx context.Context) (*RepliesResponse, error)
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)
// GetPendingReplies retrieves pending replies for a post with reply approvals enabled
GetPendingReplies(ctx context.Context, postID PostID, opts *PendingRepliesOptions) (*RepliesResponse, error)
// ApprovePendingReply approves a pending reply, making it publicly visible
ApprovePendingReply(ctx context.Context, replyID PostID) error
// IgnorePendingReply ignores a pending reply (it can still be approved later)
IgnorePendingReply(ctx context.Context, replyID PostID) 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 ¶
func (s *SearchIterator) Next(ctx context.Context) (*PostsResponse, error)
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
AuthorUsername string `json:"author_username,omitempty"` // Filter by author username (exact match, without @)
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 TextAttachment ¶ added in v1.0.4
type TextAttachment struct {
Plaintext string `json:"plaintext"` // Required: The text content (max 10K chars)
LinkAttachmentURL string `json:"link_attachment_url,omitempty"` // Optional: URL to include
TextWithStylingInfo []TextStylingInfo `json:"text_with_styling_info,omitempty"` // Optional: Styling information
}
TextAttachment represents a text attachment with optional styling Text attachments allow up to 10,000 characters of long-form content Can only be used with TEXT-only posts (not with polls or other media)
type TextEntitiesResponse ¶ added in v1.8.0
type TextEntitiesResponse struct {
Data []TextEntity `json:"data"`
}
TextEntitiesResponse wraps text entities as returned by the API. The API returns text_entities as {"data": [...]} rather than a flat array.
type TextEntity ¶ added in v1.0.4
type TextEntity struct {
EntityType string `json:"entity_type"` // "SPOILER" or "spoiler"
Offset int `json:"offset"` // Starting position of the spoiler (0-indexed)
Length int `json:"length"` // Length of the spoiler text from offset
}
TextEntity represents a spoiler entity within text content Used to mark specific ranges of text as spoilers using offset and length
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"`
// TextEntities marks specific text ranges as spoilers
// Max 10 entities per post. Each entity specifies offset and length of spoiler text.
TextEntities []TextEntity `json:"text_entities,omitempty"`
// TextAttachment allows adding longer text content with styling
// Can only be used with TEXT-only posts (not with polls or other media types)
// Max 10,000 characters in plaintext field
TextAttachment *TextAttachment `json:"text_attachment,omitempty"`
// GIFAttachment allows attaching a GIF to the text post
// Can only be used with TEXT-only posts (not with image, video, or carousel posts)
// Supported providers: TENOR (deprecated) and GIPHY
GIFAttachment *GIFAttachment `json:"gif_attachment,omitempty"`
// IsGhostPost marks the post as a ghost post (text-only, expires in 24h, no replies allowed)
IsGhostPost bool `json:"is_ghost_post,omitempty"`
// EnableReplyApprovals enables reply approvals on the post; replies must be approved before publishing
EnableReplyApprovals bool `json:"enable_reply_approvals,omitempty"`
}
TextPostContent represents content for text posts. Set QuotedPostID to create a quote post, or leave empty for regular text posts.
type TextStylingInfo ¶ added in v1.0.4
type TextStylingInfo struct {
Offset int `json:"offset"` // Starting position for styling (0-indexed)
Length int `json:"length"` // Length of text to style from offset
StylingInfo []string `json:"styling_info"` // Array of styles: "bold", "italic", "highlight", "underline", "strikethrough"
}
TextStylingInfo represents styling to apply to a range of text in a text attachment
type 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 ¶
MarshalJSON implements json.Marshaler for Time
func (*Time) UnmarshalJSON ¶
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"`
LinkURL string `json:"link_url,omitempty"` // URL for click metrics
}
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
IsEligibleForGeoGating bool `json:"is_eligible_for_geo_gating,omitempty"` // Whether geo-gating is available for this user
RecentlySearchedKeywords []RecentSearch `json:"recently_searched_keywords,omitempty"` // Recently searched keywords with timestamps
}
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 ¶
ConvertToUserID safely converts a string to UserID
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 ¶
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 (*Validator) ValidateAltText ¶ added in v1.8.0
ValidateAltText validates alt text for media posts. Alt text is optional but cannot exceed MaxAltTextLength characters.
func (*Validator) ValidateCarouselChildren ¶
ValidateCarouselChildren validates carousel children count
func (*Validator) ValidateCountryCodes ¶
ValidateCountryCodes validates ISO 3166-1 alpha-2 country codes
func (*Validator) ValidateGIFAttachment ¶ added in v1.1.0
func (v *Validator) ValidateGIFAttachment(gifAttachment *GIFAttachment) error
ValidateGIFAttachment validates GIF attachment structure and content
func (*Validator) ValidateLinkCount ¶ added in v1.2.0
ValidateLinkCount validates that the text does not contain more than the allowed number of links
func (*Validator) ValidateMediaURL ¶
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) ValidatePollAttachment ¶ added in v1.8.0
func (v *Validator) ValidatePollAttachment(poll *PollAttachment) error
ValidatePollAttachment validates poll attachment options. The API requires MinPollOptions (2) to MaxPollOptions (4) options. Options A and B are required; options C and D are optional. Each provided option must be 1-MaxPollOptionLength (25) characters.
func (*Validator) ValidatePostContent ¶
ValidatePostContent performs common validation for all post types
func (*Validator) ValidatePostsOptions ¶ added in v1.8.0
func (v *Validator) ValidatePostsOptions(opts *PostsOptions) error
ValidatePostsOptions validates PostsOptions including pagination and timestamp fields.
func (*Validator) ValidateSearchOptions ¶
func (v *Validator) ValidateSearchOptions(opts *SearchOptions) error
ValidateSearchOptions validates search parameters
func (*Validator) ValidateTextAttachment ¶ added in v1.0.4
func (v *Validator) ValidateTextAttachment(textAttachment *TextAttachment) error
ValidateTextAttachment validates text attachment structure and content
func (*Validator) ValidateTextEntities ¶ added in v1.0.4
func (v *Validator) ValidateTextEntities(entities []TextEntity) error
ValidateTextEntities validates text spoiler entities
func (*Validator) ValidateTextLength ¶
ValidateTextLength validates text doesn't exceed maximum length. The Threads API limits text posts to 500 characters (Unicode code points), not 500 bytes. Using utf8.RuneCountInString ensures CJK and other multi-byte characters are correctly counted as 1 character each.
func (*Validator) ValidateTopicTag ¶
ValidateTopicTag validates a topic tag according to Threads API rules
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"`
// TextEntities marks specific text ranges as spoilers
// Max 10 entities per post. Each entity specifies offset and length of spoiler text.
TextEntities []TextEntity `json:"text_entities,omitempty"`
// IsSpoilerMedia marks the video as a spoiler
IsSpoilerMedia bool `json:"is_spoiler_media,omitempty"`
// EnableReplyApprovals enables reply approvals on the post; replies must be approved before publishing
EnableReplyApprovals bool `json:"enable_reply_approvals,omitempty"`
}
VideoPostContent represents content for video posts. Set QuotedPostID to create a quote post, or leave empty for regular video posts.
Source Files
¶
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. |