12 KiB
Meta (Facebook & Instagram) API Setup Guide
This guide provides step-by-step instructions for setting up Meta Graph API integration for managing Facebook Pages and Instagram Business accounts.
Table of Contents
- Overview
- Prerequisites
- Meta for Developers Setup
- Environment Configuration
- OAuth Redirect URI Configuration
- Permissions & Scopes
- Webhook Configuration
- Development vs Production
- Troubleshooting
Overview
API Version: Graph API v24.0
Base URL: https://graph.facebook.com/v24.0
Auth URL: https://www.facebook.com/v24.0/dialog/oauth
Features Supported
-
Facebook Pages:
- Fetch page posts
- Read comments on posts
- Reply to comments as the Page
-
Instagram Business:
- Fetch Instagram media posts
- Read comments on posts
- Reply to comments (with nesting limitations)
How It Works
- User authenticates with Facebook
- App discovers all Facebook Pages the user manages
- For each Page, app also discovers linked Instagram Business accounts
- Page Access Tokens are permanent (don't expire if app is active)
Prerequisites
- A Facebook account with admin access to at least one Facebook Page
- An Instagram Business Account linked to your Facebook Page
- Access to Meta for Developers
- HTTPS-enabled server for production
Linking Instagram to Facebook Page
- Go to your Facebook Page settings
- Navigate to Instagram → Connect Account
- Log in to your Instagram Business account
- Authorize the connection
Meta for Developers Setup
Step 1: Create a Meta App
- Navigate to Meta for Developers
- Click "Create App"
- Select "Business" as the app type
- Fill in the details:
- App Name: Your application name (e.g., "PX360 Social Manager")
- App Contact Email: Your contact email
- Business Account: Select your business (if applicable)
- Click "Create App"
- Complete security verification if prompted
Step 2: Configure Basic Settings
- Go to "Settings" → "Basic"
- Fill in required fields:
- Privacy Policy URL: Your privacy policy URL
- User Data Deletion: Provide deletion instructions or URL
- Category: Select "Business Tools"
- Add App Domains (your application's domain)
- Click "Save Changes"
Step 3: Add Facebook Login Product
- Go to "Add Products" (left sidebar)
- Find "Facebook Login" and click "Set Up"
- Select "Web" as platform
- Enter your site URL
- Configure OAuth settings (see Redirect URI section below)
Step 4: Get App Credentials
- Go to "Settings" → "Basic"
- Copy the following:
- App ID → This is your
META_APP_ID - App Secret → Click "Show" → This is your
META_APP_SECRET
- App ID → This is your
⚠️ Important: Never expose your App Secret in client-side code.
Environment Configuration
Django Settings (settings.py)
# Meta (Facebook/Instagram) API Configuration
META_APP_ID = 'your_app_id_here'
META_APP_SECRET = 'your_app_secret_here'
META_REDIRECT_URI = 'https://yourdomain.com/social/callback/META/'
META_WEBHOOK_VERIFY_TOKEN = 'your_random_secret_string_here'
Environment Variables (.env)
META_APP_ID=your_app_id_here
META_APP_SECRET=your_app_secret_here
META_REDIRECT_URI=https://yourdomain.com/social/callback/META/
META_WEBHOOK_VERIFY_TOKEN=your_random_secret_string_here
OAuth Redirect URI Configuration
In Meta Developer Portal
- Go to "Facebook Login" → "Settings"
- Under "Valid OAuth Redirect URIs", add:
- Development:
http://127.0.0.1:8000/social/callback/META/ - Production:
https://yourdomain.com/social/callback/META/
- Development:
- Click "Save Changes"
Development vs Production URIs
| Environment | Redirect URI |
|---|---|
| Development | http://127.0.0.1:8000/social/callback/META/ |
| Production | https://yourdomain.com/social/callback/META/ |
⚠️ Note: Meta accepts HTTP for localhost but requires HTTPS for production.
Permissions & Scopes
The application requests the following OAuth scopes:
| Scope | Description | Required |
|---|---|---|
pages_manage_engagement |
Reply to comments | ✅ Yes |
pages_read_engagement |
Read comments and reactions | ✅ Yes |
pages_show_list |
Discover pages and get tokens | ✅ Yes |
pages_read_user_content |
Read user-generated content | ✅ Yes |
instagram_basic |
Basic Instagram info | ✅ Yes |
instagram_manage_comments |
Manage Instagram comments | ✅ Yes |
public_profile |
Basic user profile | ✅ Yes |
Code Reference
# apps/social/utils/meta.py
BASE_GRAPH_URL = "https://graph.facebook.com/v24.0"
BASE_AUTH_URL = "https://www.facebook.com/v24.0"
META_SCOPES = [
"pages_manage_engagement",
"pages_read_engagement",
"pages_show_list",
"pages_read_user_content",
"instagram_basic",
"instagram_manage_comments",
"public_profile",
]
App Review Requirements
Some permissions require Meta's App Review:
- Go to "App Review" → "Permissions and Features"
- Request permissions that require review
- Submit detailed use case and screencast
- Typical use case explanation:
"This application helps businesses manage their social media presence by allowing them to read and respond to comments on their Facebook Pages and Instagram Business accounts from a centralized dashboard."
Webhook Configuration
Webhooks allow real-time notifications for new comments.
Step 1: Create Webhook Endpoint
Your application needs an endpoint to receive webhook events:
POST /social/webhooks/meta/
Step 2: Configure Webhook in Meta Portal
- Go to "Webhooks" in your app dashboard
- Click "Add Subscription"
- Enter your callback URL:
https://yourdomain.com/social/webhooks/meta/ - Enter your verify token (from
META_WEBHOOK_VERIFY_TOKEN) - Click "Verify and Save"
Step 3: Subscribe to Events
- After verification, select subscriptions:
- Page Events:
feed,comments - Instagram Events:
comments,mentions
- Page Events:
Step 4: Subscribe Individual Pages
For each Page, subscribe to webhook events:
# Done automatically during account connection
from apps.social.services.meta import MetaService
MetaService.subscribe_webhook(page_id, page_access_token)
Webhook Verification Handler
def verify_webhook(request):
mode = request.GET.get('hub.mode')
challenge = request.GET.get('hub.challenge')
verify_token = request.GET.get('hub.verify_token')
if mode == 'subscribe' and verify_token == settings.META_WEBHOOK_VERIFY_TOKEN:
return HttpResponse(challenge, status=200)
return HttpResponse(status=403)
Development vs Production
Development Setup
| Setting | Value |
|---|---|
META_REDIRECT_URI |
http://127.0.0.1:8000/social/callback/META/ |
| Protocol | HTTP allowed for localhost |
| App Mode | Development |
| App Review | Not required for testing |
| Test Users | Add yourself and team members |
Production Setup
| Setting | Value |
|---|---|
META_REDIRECT_URI |
https://yourdomain.com/social/callback/META/ |
| Protocol | HTTPS required |
| App Mode | Live |
| App Review | Required for sensitive permissions |
| Rate Limits | Higher limits for approved apps |
Using ngrok for Local Webhooks
# Install ngrok
npm install -g ngrok
# Create tunnel
ngrok http 8000
# Use ngrok URL for webhook
# Example: https://abc123.ngrok.io/social/webhooks/meta/
Troubleshooting
Common Error: "Error Validating Verification Code"
Cause: Redirect URI mismatch.
Solution:
- Check exact URL in Facebook Login → Settings → Valid OAuth Redirect URIs
- Ensure trailing slashes match
- Verify protocol (http vs https)
Common Error: "Permission Error (Code 200)"
Cause: Missing permissions or user doesn't have page access.
Solution:
- Verify all required scopes are requested
- Ensure user has Page Admin role
- Check if permission needs App Review approval
Common Error: "Invalid OAuth Access Token (Code 190)"
Cause: Token expired or invalid.
Solution:
- Page tokens should be permanent, but user tokens expire
- User may need to re-authenticate
- Check if app is in Development mode and user is a test user
Common Error: "Unsupported Post Request (Code 100)"
Cause: Trying to reply to a reply on Instagram (nested replies not supported).
Solution:
- Instagram only supports 1 level of comment nesting
- You can reply to a top-level comment, but cannot reply to a reply
- The application handles this gracefully
Common Error: "Non-Existent Field 'name' (Instagram)"
Cause: Instagram comments use username, not name for author.
Solution:
- The application dynamically selects fields based on platform
- This is handled automatically in the code
Common Error: "Rate Limit (Code 4, 17, 32)"
Cause: Too many API requests.
Solution:
- Application implements automatic retry with delay
- Wait for rate limit to reset (usually 1 hour)
- Reduce polling frequency
Common Error: "Page Not Found (Code 404)"
Cause: Page doesn't exist or user doesn't have access.
Solution:
- Verify page exists and is published
- Ensure user has Page Admin/Editor role
- Check page ID is correct
API Rate Limits
| Resource | Rate Limit |
|---|---|
| Graph API Calls | 200 calls/hour per user per app |
| Page-level Calls | Higher limits for page tokens |
| Webhook Events | Unlimited |
The application implements rate limiting to stay within bounds.
Facebook vs Instagram ID Detection
The application automatically detects platform based on ID format:
# Instagram IDs typically start with 17 or 18
if str(comment_id).startswith('17') and str(comment_id).isdigit():
platform = 'IG'
elif '_' in str(comment_id):
platform = 'FB' # Facebook IDs often contain underscore
Page Access Token Lifecycle
| Token Type | Lifetime | Notes |
|---|---|---|
| User Access Token | ~60 days | Short-lived, can be exchanged |
| Page Access Token | Permanent | Doesn't expire if app remains active |
| Instagram Token | Same as Page | Uses Page token for access |
✅ Good News: Page tokens are permanent. Once a user connects their account, the integration continues working indefinitely.
Verification
After setup, verify the integration:
For Facebook:
- Navigate to
/social/in your application - Click "Connect Facebook/Instagram"
- Authorize with Facebook
- Select your Facebook Page
- Verify posts are fetched
- Test replying to a comment
For Instagram:
- After connecting Facebook, Instagram accounts are auto-discovered
- Verify Instagram Business account appears in account list
- Check if Instagram media is fetched
- Test replying to an Instagram comment
Testing in Django Shell
from apps.social.services.meta import MetaService
from apps.social.models import SocialAccount
# Test Facebook
fb_account = SocialAccount.objects.filter(platform='FB').first()
posts = MetaService.fetch_posts(fb_account.platform_id, fb_account.access_token, 'FB')
print(f"Found {len(posts)} FB posts")
# Test Instagram
ig_account = SocialAccount.objects.filter(platform='IG').first()
if ig_account:
media = MetaService.fetch_posts(ig_account.platform_id, ig_account.access_token, 'IG')
print(f"Found {len(media)} IG media posts")
Support Resources
- Meta Graph API Documentation
- Facebook Login Guide
- Instagram Graph API
- Webhooks Documentation
- Meta Bug Tracker
Last Updated: February 2026 API Version: Meta Graph API v24.0