Integrating Instagram Graph API with AWS Lambda: Connecting @sailjada Media to Guest Photo Pages
What Was Done
We implemented Instagram Graph API integration into the shipcaptaincrew Lambda function (us-east-1, account 782785212866) to dynamically fetch and display @sailjada Instagram posts alongside guest-uploaded charter photos on the guest photo page system at shipcaptaincrew.queenofsandiego.com/g/{event_id}. The Lambda function now reads environment variables IG_USER_ID and IG_ACCESS_TOKEN to populate the media feed for specific event dates.
The integration was previously dormant—returning an empty array when credentials were missing. This walkthrough documents the step-by-step process to activate it, including Facebook App configuration, token generation, and Lambda environment variable setup.
Technical Details: Facebook App Configuration
The foundation for Instagram Graph API access requires proper Facebook App product setup. The initial configuration included a Messaging product, which was incorrect for our use case. The key decision was to add a separate Instagram Graph API product (not Basic Display API, not Messaging API).
Product Selection Rationale:
- Instagram Graph API — Allows reading media, captions, and metadata from business/creator accounts. Grants the
instagram_basicscope needed for media reads. - Basic Display API — Read-only but lacks media insights and requires a more restrictive flow.
- Messaging API — For direct message handling only; does not grant media-reading scopes.
The app ID is sailjada-social, configured in the Facebook Developer Dashboard at developers.facebook.com/apps.
Token Generation Flow
Instagram Graph API uses a two-tier token system: short-lived tokens (valid for ~1 hour) and long-lived tokens (valid for 60 days). Our implementation uses the long-lived token approach to minimize token refresh overhead.
Step 1: Generate Short-Lived Token
Using the Graph API Explorer at developers.facebook.com/tools/explorer:
- Select the
sailjada-socialapp from the dropdown - Click "Generate Access Token"
- Select the Facebook Page linked to @sailjada's business account
- Request scopes:
instagram_basic,pages_show_list
This generates a short-lived token used only for the next step.
Step 2: Retrieve IG_USER_ID
The short-lived token is used to query the Facebook Graph API and extract the Instagram Business Account ID. Two API calls are required:
# First call: Get the page ID and instagram_business_account reference
curl -X GET "https://graph.instagram.com/v18.0/[PAGE_ID]?fields=instagram_business_account&access_token=[SHORT_LIVED_TOKEN]"
# Extract the instagram_business_account.id from the response
# Second call: Confirm the account structure
curl -X GET "https://graph.instagram.com/v18.0/[IG_USER_ID]?fields=id,username&access_token=[SHORT_LIVED_TOKEN]"
The id field from the response is your IG_USER_ID. Store this value—it's constant and identifies the @sailjada account within the Graph API.
Step 3: Exchange for Long-Lived Token
Using the short-lived token, exchange it for a long-lived token (valid 60 days):
curl -X GET "https://graph.instagram.com/v18.0/access_token?grant_type=ig_refresh_token&access_token=[SHORT_LIVED_TOKEN]"
The response contains a new access_token field with extended expiration. This is your IG_ACCESS_TOKEN.
Infrastructure: Lambda Environment Variables
Once tokens are obtained, update the shipcaptaincrew Lambda function with environment variables using the AWS CLI:
aws lambda update-function-configuration \
--function-name shipcaptaincrew \
--region us-east-1 \
--environment Variables="{IG_USER_ID=[YOUR_IG_USER_ID],IG_ACCESS_TOKEN=[YOUR_IG_ACCESS_TOKEN]}"
The Lambda code already contains conditional logic to read these variables. When both are present, the function queries the Instagram Graph API endpoint:
https://graph.instagram.com/v18.0/[IG_USER_ID]/media?fields=id,caption,media_type,media_url,timestamp&access_token=[IG_ACCESS_TOKEN]
Results are filtered by event date (matching the requested event_id date) and merged with approved guest photo uploads before rendering at /g/{event_id}.
Key Decisions
Why 60-Day Long-Lived Tokens Instead of Short-Lived: Reduces API calls during token refresh. A 60-day lifecycle allows monthly or quarterly refresh cycles via EventBridge-triggered Lambda, avoiding runtime token exchanges that would add latency to the guest photo page load.
Why Separate Graph API Product: The Messaging product added earlier was a configuration mistake. Messaging APIs do not grant the instagram_basic scope; they're designed for DM functionality. Graph API is the correct product for media reads.
Why Filter by Event Date: @sailjada may post multiple times daily. The guest photo page for a specific event (e.g., /g/2026-04-29) only displays media from that date's charter. The Lambda filters Instagram media by the timestamp field, matching the event date window.
Verification and Monitoring
After updating Lambda environment variables, verify the integration by visiting a guest photo page with a recent event date:
shipcaptaincrew.queenofsandiego.com/g/2026-04-29
Guest photos and @sailjada Instagram posts from April 29, 2026 should appear together. If the Instagram feed is empty, check:
- CloudWatch Logs for the
shipcaptaincrewfunction (log group:/aws/lambda/shipcaptaincrew) - Verify
IG_USER_IDandIG_ACCESS_TOKENare correctly set in the function's environment variables - Confirm the access token hasn't expired (EventBridge refresh may be needed)
What's Next
Implement monthly token refresh via AWS EventBridge. Create a rule that triggers the token exchange call on the 1st of each month, updating Lambda environment variables automatically. This eliminates manual token management and prevents service disruption from expired credentials.