platform is an unofficial Go SDK collection for Facebook, Instagram, Threads, TikTok, X, and YouTube. Each platform is an independent package with typed request and response contracts, OAuth helpers, endpoint groups, scopes, named errors, and an injectable HTTP client.
This project is not affiliated with, endorsed by, or supported by any of the platforms it integrates with. You are responsible for complying with each provider's terms, developer policies, and API requirements.
Install
go get github.com/social-ally/platform
The module currently targets Go 1.26.
Packages
| Platform |
Go package |
Groups |
| Facebook |
facebook |
oauth, users, pages, publishing, analytics, reels |
| Instagram |
instagram/native, instagram/facebooklogin |
native for Instagram Login; facebooklogin for Facebook Login |
| Threads |
threads |
oauth, users, media, publishing, replies, insights, discovery, locations, display, troubleshooting |
| TikTok |
tiktok |
OAuth, users, videos, publishing |
| X |
x |
OAuth, users, posts, media, analytics |
| YouTube |
youtube |
OAuth, channels, videos, playlists, analytics |
Each package exports DisplayName, a primary BaseURL, scoped base URL constants where a provider has multiple API origins, and a platform-specific client type.
The following endpoint groups are derived from the checked-in platform schemas. They describe the full typed contract catalog; a group may contain endpoints that do not yet have a handwritten client method.
Within the Facebook, Instagram, and Threads packages, each endpoint group is kept in its own group file; shared models and reusable error contracts remain in types.go.
The Instagram login packages are the provider-facing API. Use instagram/native for Instagram Login (graph.instagram.com) or instagram/facebooklogin for the Facebook Login Instagram Graph API (graph.facebook.com). Both expose their own client and endpoint groups and reuse the shared typed models underneath.
Facebook
| Group |
Endpoints |
oauth |
authorize, exchange_code, exchange_long_lived_user_token, debug_token |
users |
get_me |
pages |
list_managed_pages, get_page |
publishing |
create_feed_post, upload_photo, start_video_upload, transfer_video_chunk, finish_video_upload, delete_post |
analytics |
get_page_insights |
reels |
create_reel, upload_local_reel, upload_hosted_reel, get_reel_status, publish_reel |
Instagram
instagram/native exposes Instagram Login groups: oauth, users, media,
publishing, insights, comment_moderation, messaging,
welcome_message_flows, messenger_profile, and webhooks.
instagram/facebooklogin exposes Facebook Login groups: oauth, pages,
users, media, publishing, insights, and comment_moderation.
| Group |
Endpoints |
native.oauth |
instagram_authorize, instagram_exchange_code, instagram_exchange_long_lived_token, instagram_refresh_long_lived_token |
facebooklogin.oauth |
facebook_authorize, facebook_exchange_code, facebook_exchange_long_lived_token |
facebooklogin.pages |
get_managed_pages, get_page_access_token |
native.users |
get_me, get_instagram_user, get_user_profile |
facebooklogin.users |
get_instagram_user, business_discovery |
native.media |
list_media, get_media, list_stories |
facebooklogin.media |
list_media, get_media, list_stories, list_tagged_media, hashtag_search, hashtag_top_media, hashtag_recent_media |
native.publishing |
create_media_container, get_container_status, publish_media, get_publishing_limit |
facebooklogin.publishing |
create_media_container, get_container_status, publish_media, get_publishing_limit |
native.insights |
get_account_insights, get_media_insights |
facebooklogin.insights |
get_account_insights, get_media_insights |
native.comment_moderation |
list_comments, list_replies, reply_to_comment, delete_comment, hide_or_unhide_comment, enable_or_disable_comments, private_reply |
facebooklogin.comment_moderation |
list_comments, list_replies, reply_to_comment, delete_comment, hide_or_unhide_comment, enable_or_disable_comments, private_reply |
native.messaging |
send_text_message, send_image_message, send_published_post, send_quick_replies, send_button_template, send_generic_template, send_sticker, react_or_unreact_to_message, send_typing_indicator, get_message, upload_message_attachment |
native.welcome_message_flows |
list_welcome_message_flows, get_welcome_message_flow, create_welcome_message_flow, update_welcome_message_flow, delete_welcome_message_flow |
native.messenger_profile |
get_messenger_profile, set_messenger_profile, delete_messenger_profile |
native.webhooks |
verify_webhook, receive_webhook |
Threads
| Group |
Endpoints |
oauth |
authorize, exchange_code, exchange_long_lived_token, refresh_long_lived_token, get_app_access_token |
users |
get_me, get_app_scoped_profile, lookup_profile |
media |
list_threads, get_thread, list_user_replies, delete_thread |
publishing |
create_text_container, create_image_container, create_video_container, create_image_carousel_item, create_video_carousel_item, create_carousel_container, create_quote_container, publish_thread, repost_thread |
replies |
get_replies, get_pending_replies, get_conversation, manage_reply, manage_pending_reply, create_reply, create_post_with_reply_control |
insights |
get_thread_insights, get_account_insights |
discovery |
keyword_search, list_mentions, list_profile_posts |
locations |
search_locations, get_location |
display |
embed_thread |
troubleshooting |
get_container_status, get_publishing_limit, debug_token |
Quick start: X
Create a client with the scopes your application needs. Provide WithAccessToken for calls to authenticated endpoint groups.
package main
import (
"context"
"fmt"
"github.com/social-ally/platform/x"
)
func main() {
client, err := x.NewXClient(
"client-id",
"",
"https://example.com/oauth/callback",
x.WithScopes(x.ScopeUsersRead, x.ScopeTweetRead),
x.WithAccessToken("user-access-token"),
)
if err != nil {
panic(err)
}
response, err := x.NewUsers(client).GetAuthenticatedUser(
context.Background(),
&x.RequestGetAuthenticatedUser{},
)
if err != nil {
panic(err)
}
fmt.Println(response.Success.Data.Username)
}
For an X confidential client, supply the client secret and x.WithConfidentialClient(). Token requests will use HTTP Basic authentication.
When an access token is obtained after client creation, derive an authenticated client without recreating the OAuth configuration:
authenticatedClient, err := client.WithAccessToken(tokens.Success.AccessToken)
if err != nil {
return err
}
OAuth authorization-code flow
OAuth groups create the provider authorization URL and exchange the returned code. Each package’s request and response types are named Request<Method> and Response<Method>.
client, err := x.NewXClient(
"client-id",
"",
"https://example.com/oauth/callback",
x.WithScopes(x.ScopeUsersRead),
)
if err != nil {
return err
}
authorize, err := x.NewOAuth(client).Authorize(ctx, &x.RequestAuthorize{
Query: x.RequestAuthorizeQuery{
State: "csrf-state",
CodeChallenge: "pkce-code-challenge",
},
})
if err != nil {
return err
}
// Redirect the user to authorize.URL.
tokens, err := x.NewOAuth(client).ExchangeCode(ctx, &x.RequestExchangeCode{
Body: x.RequestExchangeCodeBody{
Code: returnedCode,
CodeVerifier: "pkce-code-verifier",
},
})
if err != nil {
return err
}
_ = tokens.Success.AccessToken
TikTok supports PKCE with tiktok.WithPKCE(). X authorization-code flows require a PKCE challenge and verifier. Scope constants live in each package’s scope.go.
Endpoint groups
Construct a group from its platform client and call its typed method:
text := "Hello from Go"
posts := x.NewPosts(client)
response, err := posts.CreatePost(ctx, &x.RequestCreatePost{
Body: x.RequestCreatePostBody{Text: &text},
})
All authenticated calls attach the configured bearer token. Clients can use a custom transport for proxies, retries, tracing, or tests:
client, err := youtube.NewYouTubeClient(
"client-id", "client-secret", "https://example.com/callback",
youtube.WithScopes(youtube.ScopeYoutubeUpload),
youtube.WithAccessToken("access-token"),
youtube.WithHTTPClient(customHTTPClient),
)
YouTube video uploads accept media through RequestUploadVideo.Media (io.Reader) and use a multipart upload when media is provided.
Errors
Packages expose named sentinel errors for configuration, missing tokens, missing identifiers, nil endpoint clients, and OAuth validation. API responses outside the 2xx range return that package’s *APIError, which matches ErrUnexpectedStatus through errors.Is.
if errors.Is(err, x.ErrUnexpectedStatus) {
var apiErr *x.APIError
if errors.As(err, &apiErr) {
fmt.Println(apiErr.StatusCode, string(apiErr.Body))
}
}
Development
go test ./...
go vet ./...