Integrating Instagram Graph API with AWS Lambda: Enabling Social Photo Display in Guest Event Pages
Overview: What Was Done
We activated dormant Instagram integration in the shipcaptaincrew Lambda function to display @sailjada Instagram posts alongside guest-uploaded charter photos on event-specific gallery pages. The integration reads from Instagram's Graph API and merges results with locally-stored guest photos, providing a unified timeline view at URLs like shipcaptaincrew.queenofsandiego.com/g/{event_id}.
Problem: The Lambda function contained conditional logic that returned an empty array when IG_USER_ID and IG_ACCESS_TOKEN environment variables were missing. The Instagram integration existed but was never wired up to the Facebook app infrastructure.
Solution: Configure the Instagram Graph API product in the Facebook Developer app, generate long-lived access tokens with appropriate scopes, and populate Lambda environment variables to enable token-based requests to Instagram's media endpoints.
Technical Architecture
Current Lambda Function Structure
The shipcaptaincrew Lambda function (AWS account 782785212866, region us-east-1) uses the following conditional pattern:
if (IG_USER_ID && IG_ACCESS_TOKEN) {
// Query Instagram Graph API for media
// Filter by event date/time window
// Merge with guest photos array
} else {
// Return guest photos only (current behavior)
}
The function expects two environment variables:
IG_USER_ID– The Instagram Business Account ID (numeric string)IG_ACCESS_TOKEN– Long-lived access token valid for ~60 days
Instagram Graph API Integration Points
The Lambda makes authenticated requests to Instagram's Graph API endpoint:
GET https://graph.instagram.com/{IG_USER_ID}/media
?fields=id,caption,media_type,media_url,timestamp
&access_token={IG_ACCESS_TOKEN}
Results are filtered server-side by comparing the post's timestamp field against the event's date and a configurable time window (typically ±4 hours from event start).
Step-by-Step Implementation: Facebook App Configuration
Step 1: Add Instagram Graph API Product (Critical First Step)
Why this matters: The app previously had a "Messaging" use case added, which grants instagram_manage_messages scope for DM automation—not media reading. Instagram Graph API must be added as a separate product to grant instagram_basic scope.
- Navigate to
developers.facebook.com/apps - Open app
sailjada-social - In the left sidebar, locate and click Add Product (typically near the bottom of the product list)
- Search for Instagram and select Instagram Graph API (not "Basic Display" or "Messaging")
- Complete setup; Instagram Graph API will appear as a new sidebar item
Step 2: Connect @sailjada Instagram Account
The @sailjada account must be classified as a Business or Creator account and linked to a Facebook Page.
- In Instagram Graph API settings, click API Setup
- Select Add Instagram Account
- Authenticate using @sailjada's credentials
- Authorize the app to read media and insights
Step 3: Generate Short-Lived Access Token
Using the Graph API Explorer tool ensures token generation with correct scopes:
- Visit
developers.facebook.com/tools/explorer - Select app
sailjada-socialfrom the top dropdown - Click Generate Access Token
- Select the Facebook Page linked to @sailjada
- Add scopes:
instagram_basicandpages_show_list - Copy the generated token (valid for ~2 hours)
Step 4: Retrieve IG_USER_ID via API Calls
Use the short-lived token to query the Facebook Page's linked Instagram Business Account:
curl -s "https://graph.facebook.com/v18.0/{PAGE_ID}?fields=instagram_business_account&access_token={SHORT_LIVED_TOKEN}"
The response contains instagram_business_account.id—this is your IG_USER_ID.
Step 5: Exchange for Long-Lived Token
Why long-lived tokens: Short-lived tokens expire in ~2 hours. Exchanging them for long-lived tokens (60-day validity) eliminates the need for hourly token refresh in Lambda.
curl -s "https://graph.instagram.com/access_token?grant_type=ig_refresh_token&access_token={SHORT_LIVED_TOKEN}"
The response access_token field is your IG_ACCESS_TOKEN. Store this securely (see Infrastructure section below).
Infrastructure: AWS Secrets and Environment Configuration
Lambda Environment Variables
Update the shipcaptaincrew Lambda function configuration via AWS CLI:
aws lambda update-function-configuration \
--function-name shipcaptaincrew \
--region us-east-1 \
--environment Variables="{IG_USER_ID=,IG_ACCESS_TOKEN=}"
Alternative (recommended for secrets): Store tokens in AWS Secrets Manager and reference them via Lambda execution role permissions, rather than exposing them as plaintext environment variables.
Token Refresh Strategy
Instagram long-lived tokens expire after 60 days. Implement one of two refresh strategies:
- Manual refresh: Re-run the token exchange curl command monthly and update Lambda environment variables via AWS CLI
- Automated refresh (optional): Create an EventBridge rule that triggers a helper Lambda monthly to exchange the token and update Secrets Manager
Key Decisions and Rationale
- Long-lived tokens over short-lived: Reduces API call overhead and complexity. Lambda doesn't need to re-authenticate on every invocation.
- Server-side filtering by timestamp: Instagram API doesn't offer date-range filters, so filtering occurs in Lambda after retrieving media. This is more efficient than paginating through months of posts.
- Separate Graph API product: Ensures correct OAuth scopes are granted. Messaging and media reading require different permission sets.
- Facebook Page intermediary: Instagram Business Accounts must be linked to a Facebook Page to use Graph API. This is a required architecture constraint from Meta.