The hosted SaaS atDocumentation Index
Fetch the complete documentation index at: https://docs.letmepost.dev/llms.txt
Use this file to discover all available pages before exploring further.
api.letmepost.dev ships with platform-approved OAuth apps for every network we support. When you self-host, you bring your own — each platform requires that the OAuth client id match an app you control, registered against your own developer account.
Bluesky is the exception: it uses app passwords and doesn’t need a developer app at all.
For each platform below: register the app, configure the redirect URI exactly as listed (substituting your own ${BETTER_AUTH_URL} for the placeholder), paste the resulting client id + secret into your .env, and restart the API.
Throughout this page,
${BETTER_AUTH_URL} means whatever you set BETTER_AUTH_URL to — typically http://localhost:3000 in dev or https://api.letmepost.dev in prod. The redirect URI must match the platform’s record character-for-character, including trailing slash (or lack thereof).- Portal: linkedin.com/developers/apps
- Redirect URI:
${BETTER_AUTH_URL}/v1/accounts/oauth/linkedin/callback - Env vars:
LINKEDIN_CLIENT_ID,LINKEDIN_CLIENT_SECRET
- Sign In with LinkedIn using OpenID Connect — gives
openid,profile. - Share on LinkedIn — gives
w_member_social.
- Write:
openid,profile,w_member_social - Extended:
email,r_organization_social,w_organization_social
w_organization_social) requires LinkedIn’s Marketing Developer Platform (MDP) review — separate, slower process. The personal-posting flow doesn’t need MDP.
Twitter / X
- Portal: developer.x.com
- Redirect URI:
${BETTER_AUTH_URL}/v1/accounts/oauth/twitter/callback - Env vars:
TWITTER_CLIENT_ID,TWITTER_CLIENT_SECRET
- Type of App: Web App, Automated App or Bot
- Authentication: OAuth 2.0 with PKCE (Confidential client)
- Scopes (write):
tweet.read,tweet.write,users.read,offline.access - Scopes (extended):
like.read,follows.read
TWITTER_LAUNCH_CAP_PER_ACCOUNT (default 50) caps billable posts per rolling 30-day window per account, so an uncapped publish loop can’t run up the PPU bill.
- Portal: developers.pinterest.com/apps
- Redirect URI:
${BETTER_AUTH_URL}/v1/accounts/oauth/pinterest/callback - Env vars:
PINTEREST_CLIENT_ID,PINTEREST_CLIENT_SECRET
- Write:
boards:read,boards:write,pins:read,pins:write,user_accounts:read - Extended:
pins:read_secret
api.pinterest.com) is blocked with a hard “use sandbox” error until Pinterest approves Standard Access. While you wait:
PINTEREST_API_BASE once Standard Access is approved — it defaults back to https://api.pinterest.com/v5. The variable affects every /v5/* call and the OAuth token-exchange endpoint, since both live under the same host on Pinterest’s API.
Meta family
The Meta family used to be a single Facebook Login for Business app that fanned out to Facebook Pages, Instagram, and Threads. In the current build, each of those three is an independent OAuth flow with its own client credentials. You still register all three on developers.facebook.com/apps — Meta’s developer portal — but the apps, scopes, redirect URIs, and review tracks are separate.Facebook Pages
- Portal: developers.facebook.com/apps
- Redirect URI:
${BETTER_AUTH_URL}/v1/accounts/oauth/facebook/callback - Env vars:
META_APP_ID,META_APP_SECRET
- Facebook Login for Business
The redirect URI ends in
/facebook/callback, not /meta/callback. Earlier docs incorrectly said /meta/callback; if your Meta app has that registered, update it.META_GRAPH_VERSION pins the Graph API version (the provider has a default; bump it on each platform version cut and re-run the contract test suite).
Instagram (Instagram API with Instagram Login)
- Portal: developers.facebook.com/apps — same portal as Facebook, but you’ll enable the Instagram product → “Instagram API setup with Instagram Login” path.
- Redirect URI:
${BETTER_AUTH_URL}/v1/accounts/oauth/instagram/callback - Env vars:
INSTAGRAM_CLIENT_ID,INSTAGRAM_CLIENT_SECRET
graph.instagram.com instead of graph.facebook.com.
App Review is separate from the Facebook Login scopes — different scope namespace, different review cycle.
The optional INSTAGRAM_GRAPH_BASE, INSTAGRAM_OAUTH_AUTHORIZE_URL, INSTAGRAM_OAUTH_TOKEN_URL variables are test-only — they let the contract suite point at a mock server. Leave them blank in production.
Threads
- Portal: developers.facebook.com/apps — add the Threads API product.
- Authorize URL:
https://threads.net/oauth/authorize(NOTfacebook.com/dialog/oauth) - Redirect URI:
${BETTER_AUTH_URL}/v1/accounts/oauth/threads/callback - Env vars:
THREADS_CLIENT_ID,THREADS_CLIENT_SECRET
- Write:
threads_basic,threads_content_publish - Extended:
threads_manage_replies,threads_read_replies
THREADS_CLIENT_ID / THREADS_CLIENT_SECRET — do not reuse META_APP_ID.
Tokens are short-lived (1h) on first exchange, swapped server-side for 60-day long-lived tokens which are what letmepost persists.
App Review for threads_content_publish is required for production; Dev Mode with Tester accounts is fully functional in the meantime — same API, same response shapes, review only lifts the testers-only gate.
Optional: THREADS_API_BASE, THREADS_API_VERSION let tests point at a mock server. Defaults: https://graph.threads.net.
Bluesky
No registration. No client id. No secret. Bluesky’s documented integration path for third-party tools is the user-generated app password flow. The user creates an app password at bsky.app/settings/app-passwords, pastes it into the dashboard’s Bluesky connect form alongside their handle, and the API stores it encrypted withKEK_MASTER. There’s nothing to configure on a self-hosted instance — connecting Bluesky works the moment the API can reach bsky.social.
Verifying a connection
Once you’ve set credentials and restarted the API, the connect flow runs from the dashboard at/accounts. Pick the platform, complete OAuth at the provider, land back on the dashboard with a connected account row.
If OAuth fails, the error envelope includes a stable code and a docUrl pointing at the troubleshooting page — see platform_auth_failed for the most common cause (a redirect URI that doesn’t match the platform’s record character-for-character).