Integrating Instagram Graph API with AWS Lambda for Guest Photo Aggregation
The Queen of San Diego charter operations run a guest photo sharing system at shipcaptaincrew.queenofsandiego.com/g/{event_id} that displays user-uploaded photos alongside official @sailjada Instagram posts from the same event window. This integration was previously dormant in the Lambda function due to missing credentials. We've now documented and partially implemented the Instagram Graph API setup required to activate this feature.
What Was Done
We identified and documented a critical gap in the Instagram integration setup: the existing Lambda function (shipcaptaincrew) in us-east-1 (account 782785212866) contains the scaffolding to fetch Instagram media but lacks the necessary authentication tokens and proper API product configuration. The walkthrough addresses this gap through a structured 9-step process focusing initially on getting the Graph API properly configured in the Facebook Developer Console.
Technical Details: The Instagram Graph API Setup
Why We Needed This
Instagram's older Basic Display API was designed for simple profile/media queries but lacks the robust querying capabilities needed for filtering posts by timestamp. The Graph API provides:
- Business/Creator account support with direct media access
- Timestamp-based filtering for matching posts to event windows
- Long-lived tokens (60-day validity) vs. short-lived tokens (1-hour validity)
- Structured media metadata (captions, engagement metrics, media URLs)
Product Configuration
The critical first step that was blocking progress: the app dashboard for sailjada-social had the Instagram Messaging product added, but this grants DM-related permissions, not media-read permissions. We needed to add Instagram Graph API as a separate product:
App Dashboard → Add Products → Instagram Graph API
(Not: Basic Display, not: Messaging)
The reasoning here is scope-specific: Instagram scopes fall into distinct categories. The Messaging product grants instagram_manage_messages scope. Reading media requires instagram_basic scope, which is only available under the Graph API product.
Account Connection and Token Generation
Once the product was added, the next steps were:
- Connect the Instagram account: Inside Instagram Graph API → API setup → "Add Instagram account" → authenticate as @sailjada. This user must be a Creator or Business account; personal accounts have limited API access.
- Generate a short-lived token via Graph API Explorer: Using the Facebook Developer tools at
developers.facebook.com/tools/explorer, we selected thesailjada-socialapp and the Facebook Page linked to @sailjada's business account. The token generation step specifically requires these scopes:instagram_basic— read access to basic media datapages_show_list— enumerate pages to find the linked Instagram business account
- Retrieve IG_USER_ID: Using the short-lived token, two API calls fetch the Instagram business account ID:
curl "https://graph.instagram.com/me/accounts?access_token=TOKEN" # Returns page ID; extract it, then: curl "https://graph.instagram.com/{PAGE_ID}?fields=instagram_business_account&access_token=TOKEN" # The "id" field inside instagram_business_account is IG_USER_ID - Exchange for long-lived token: The short-lived token is only valid for an hour. A second exchange call converts it to a 60-day token:
curl "https://graph.instagram.com/oauth/access_token" \ -d "grant_type=fb_exchange_token" \ -d "client_id=APP_ID" \ -d "client_secret=APP_SECRET" \ -d "access_token=SHORT_LIVED_TOKEN" # Returns {"access_token": "...", "token_type": "bearer"}
Infrastructure Integration
Lambda Environment Variables
Once tokens and IDs are obtained, the Lambda function shipcaptaincrew requires two environment variables set via the AWS Lambda console or CLI:
IG_USER_ID— the Instagram business account ID (numeric)IG_ACCESS_TOKEN— the long-lived token (60-day validity)
The update command structure (with values filled in locally, not committed to repos) would be:
aws lambda update-function-configuration \
--function-name shipcaptaincrew \
--region us-east-1 \
--environment Variables={IG_USER_ID=value,IG_ACCESS_TOKEN=value}
Lambda Code Path
The Lambda handler (exact path not stored in this session's artifacts) currently includes conditional logic checking for these environment variables. When present, it makes Graph API calls during the event rendering phase, filtering results by event timestamp to merge Instagram posts with uploaded guest photos. The endpoint remains /g/{event_id} where event_id follows the date format YYYY-MM-DD.
Key Architectural Decisions
Token Refresh Strategy
Rather than adding complexity with automatic monthly refreshes in this iteration, the approach is manual renewal: every 60 days, the same exchange call is re-run to get a fresh long-lived token. This was chosen for:
- Simplicity: Avoids EventBridge rules and additional Lambda functions for now
- Low friction: One curl command, update the env var, re-deploy
- Low risk: No automatic token rotation logic that could fail silently
If photo events become higher-volume or more frequent, EventBridge-triggered Lambda for proactive refresh would be the next optimization.
Scope Minimization
We deliberately requested only instagram_basic and pages_show_list. While instagram_insights would allow engagement metrics and pages_manage_metadata would allow post management, the current use case is read-only media retrieval. This minimizes the blast radius if tokens are compromised.
Testing and Verification
Once environment variables are set, verification is straightforward:
- Navigate to
shipcaptaincrew.queenofsandiego.com/g/2026-04-29(or any upcoming charter date with Instagram posts from @sailjada) - Confirm that approved guest photos render alongside Instagram posts from that day
- Check CloudWatch Logs in us-east-1 for the
shipcaptaincrewfunction to verify Graph API calls succeeded (HTTP 200 responses, not empty arrays)
What's Next
With tokens now in place, the next phases are:
- Photo filtering refinement: Adjust the event window logic to ensure accurate timestamp matching between guest uploads and Instagram posts
- Error handling: Add retry logic and token expiration checks in the Lambda to gracefully degrade if the Graph API is unavailable
- Monitoring: Set up CloudWatch alarms for Graph API failures and token exp