Integrating Instagram Graph API with AWS Lambda for Dynamic Photo Galleries
This post details the technical implementation of Instagram Graph API integration within an AWS Lambda function to dynamically populate guest photo galleries. The system pulls approved user-uploaded photos alongside official Instagram content from the same event window, creating a cohesive media feed without manual curation.
What Was Done
We activated dormant Instagram integration logic in the shipcaptaincrew Lambda function (region: us-east-1, account: 782785212866) that previously returned empty arrays due to missing environment variables. The integration now:
- Fetches media from the
@sailjadaInstagram Business account using Graph API credentials - Filters posts by event date/time window matching guest photo uploads
- Merges Instagram and guest-uploaded photos for display at
shipcaptaincrew.queenofsandiego.com/g/{event_id}(e.g.,/g/2026-04-29) - Implements automatic token refresh via 60-day long-lived access tokens with monthly refresh strategy
Technical Details: Instagram Graph API Setup
Step 1: Add Instagram Graph API Product
The critical first step is selecting the correct Facebook app product. Navigate to developers.facebook.com/apps, open the sailjada-social application, and click Add Product in the left sidebar. Search for Instagram Graph API—not Instagram Basic Display or Messaging. The Messaging product (if previously added) grants DM scopes but lacks the instagram_basic scope required for media reads.
Step 2: Connect the Business Account
The Instagram account @sailjada must be configured as a Business or Creator account and linked to a Facebook Page. Within the app's Instagram Graph API section, navigate to API setup with Instagram login and select Add Instagram account, then authenticate as the account owner.
Step 3: Generate Short-Lived Access Token
Use the Facebook Graph API Explorer at developers.facebook.com/tools/explorer:
- Select app:
sailjada-social - Generate an Access Token
- Select the Facebook Page linked to
@sailjada - Request scopes:
instagram_basic,pages_show_list
Step 4: Retrieve Instagram User ID
With the short-lived token, execute two API calls to obtain the Instagram Business Account ID:
# First call: Get the page ID
curl -X GET "https://graph.instagram.com/v18.0/me?fields=id,name&access_token=TOKEN"
# Second call: Get Instagram Business Account ID from the page
curl -X GET "https://graph.instagram.com/v18.0/{PAGE_ID}?fields=instagram_business_account&access_token=TOKEN"
The id value within instagram_business_account is the IG_USER_ID environment variable value.
Step 5: Exchange for Long-Lived Token
The short-lived token expires quickly. Exchange it for a 60-day long-lived token using your app credentials:
curl -X GET "https://graph.instagram.com/v18.0/access_token" \
-d "grant_type=ig_refresh_token" \
-d "access_token={SHORT_LIVED_TOKEN}" \
-d "client_id={APP_ID}" \
-d "client_secret={APP_SECRET}"
The returned access_token is stored as the IG_ACCESS_TOKEN environment variable.
Infrastructure Changes
Lambda Environment Variables
Update the shipcaptaincrew Lambda function in us-east-1 with two new environment variables:
IG_USER_ID: The Instagram Business Account numeric IDIG_ACCESS_TOKEN: The 60-day long-lived access token
Configuration command:
aws lambda update-function-configuration \
--function-name shipcaptaincrew \
--region us-east-1 \
--environment Variables="{IG_USER_ID=...,IG_ACCESS_TOKEN=...,EXISTING_VAR=...}"
IAM Permissions
The Lambda execution role requires no additional permissions—Instagram API calls occur via HTTPS from Lambda to Graph API endpoints, with authentication handled by the access token in request headers. The existing role should include:
logs:CreateLogGroup,logs:CreateLogStream,logs:PutLogEvents- Any existing S3, DynamoDB, or other AWS service permissions for guest photo storage
Key Architectural Decisions
Why Long-Lived Tokens Over OAuth Flow
The shipcaptaincrew Lambda is stateless and event-driven. Implementing a full OAuth redirect flow would require a separate web service to handle the callback and store tokens. Instead, we use long-lived tokens (valid 60 days) with a monthly refresh strategy. This avoids operational complexity while maintaining token freshness.
Monthly Token Refresh Strategy
Rather than refreshing on every request (wasteful), we refresh monthly via an EventBridge rule that triggers a dedicated Lambda function on the first of each month. This function calls the token exchange endpoint and updates the IG_ACCESS_TOKEN environment variable. Optional setup; manual quarterly updates are acceptable for low-traffic scenarios.
Media Filtering Logic
The Lambda function calls the Instagram Graph API endpoint:
GET /v18.0/{IG_USER_ID}/media?fields=id,caption,media_type,media_url,timestamp&access_token={IG_ACCESS_TOKEN}
Returned posts are filtered client-side within the Lambda to match the event's date/time window (e.g., all posts between 2026-04-29 00:00 and 2026-04-29 23:59). This avoids repeated API calls while remaining flexible for retroactive filtering.
Error Handling
If IG_USER_ID or IG_ACCESS_TOKEN environment variables are missing or invalid, the function returns an empty array rather than failing the entire request. Guest photos still display; Instagram media is simply absent. This graceful degradation ensures the gallery page remains functional during credential issues.
Verification
After updating Lambda environment variables, navigate to shipcaptaincrew.queenofsandiego.com/g/2026-04-29 (or another upcoming event date). The guest photo section should render alongside Instagram posts from @sailjada matching that event date. Check CloudWatch Logs for the Lambda function to verify API calls and timestamps.