From d7a18dce43be153e56faf26d17c35861a3327b96 Mon Sep 17 00:00:00 2001 From: Trevor O'Hare Date: Sat, 23 May 2026 14:56:46 +0000 Subject: [PATCH] fix: support separate Threads App ID from Meta Meta assigns a distinct App ID for the "Access the Threads API" use case, which differs from the main Facebook App ID. Using the Facebook App ID for Threads OAuth results in error 4476002 ("No app ID was sent with the request"). Add PLATFORM_THREADS_APP_ID / PLATFORM_THREADS_APP_SECRET env vars that fall back to the shared Meta credentials when not set. Fixes #45 Co-Authored-By: Claude Opus 4.6 (1M context) --- .env.example | 4 ++++ README.md | 6 ++++++ config/settings/base.py | 10 ++++++++-- 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/.env.example b/.env.example index 039571ca..ed6bbb57 100644 --- a/.env.example +++ b/.env.example @@ -36,6 +36,10 @@ PLATFORM_FACEBOOK_APP_ID= PLATFORM_FACEBOOK_APP_SECRET= PLATFORM_INSTAGRAM_APP_ID= PLATFORM_INSTAGRAM_APP_SECRET= +# Threads - Meta assigns a separate App ID for the "Access the Threads API" use case. +# Falls back to PLATFORM_FACEBOOK_APP_ID/SECRET if not set. +PLATFORM_THREADS_APP_ID= +PLATFORM_THREADS_APP_SECRET= # LinkedIn - see README "LinkedIn" section. Choose Path A or Path B (or both). # Path B (Community Management API) credentials are automatically reused for # personal connections, giving refresh tokens + inbox. diff --git a/README.md b/README.md index fb81921a..79720fd4 100644 --- a/README.md +++ b/README.md @@ -379,6 +379,12 @@ Facebook, Instagram, and Threads all use the same Meta app credentials. PLATFORM_FACEBOOK_APP_ID=your-app-id PLATFORM_FACEBOOK_APP_SECRET=your-app-secret ``` +6. **Threads App ID (if different):** Meta assigns a separate App ID for the "Access the Threads API" use case. You can find it under **Use cases → Access the Threads API → Settings** in your app dashboard. If it differs from your main App ID, set: + ``` + PLATFORM_THREADS_APP_ID=your-threads-app-id + PLATFORM_THREADS_APP_SECRET=your-threads-app-secret + ``` + If not set, these fall back to `PLATFORM_FACEBOOK_APP_ID` / `PLATFORM_FACEBOOK_APP_SECRET`. ### Instagram (Direct, via Instagram Login) diff --git a/config/settings/base.py b/config/settings/base.py index 87653aac..d51a04b9 100644 --- a/config/settings/base.py +++ b/config/settings/base.py @@ -311,6 +311,10 @@ "app_id": env("PLATFORM_INSTAGRAM_APP_ID", default=""), "app_secret": env("PLATFORM_INSTAGRAM_APP_SECRET", default=""), } +_THREADS_CREDENTIALS = { + "app_id": env("PLATFORM_THREADS_APP_ID", default="") or _META_CREDENTIALS["app_id"], + "app_secret": env("PLATFORM_THREADS_APP_SECRET", default="") or _META_CREDENTIALS["app_secret"], +} _LINKEDIN_LEGACY_CLIENT_ID = env("PLATFORM_LINKEDIN_CLIENT_ID", default="") _LINKEDIN_LEGACY_CLIENT_SECRET = env("PLATFORM_LINKEDIN_CLIENT_SECRET", default="") @@ -348,10 +352,12 @@ _LINKEDIN_PERSONAL_CREDENTIALS = {"client_id": "", "client_secret": ""} PLATFORM_CREDENTIALS_FROM_ENV = { - # Meta platforms - Facebook, Instagram, and Threads share the same app + # Meta platforms - Facebook and Instagram share the same app. + # Threads may use a separate App ID assigned by Meta's "Access the Threads API" + # use case; falls back to the shared Meta credentials when not set. "facebook": _META_CREDENTIALS, "instagram": _META_CREDENTIALS, - "threads": _META_CREDENTIALS, + "threads": _THREADS_CREDENTIALS, # Instagram (Direct) - uses Instagram Login with separate Instagram App credentials. # Despite the platform key, this targets Professional (Business/Creator) IG accounts # without requiring a linked Facebook Page. See providers/instagram_login.py.