Integrating Instagram Graph API with AWS Lambda: Connecting @sailjada Media to Guest Photo Pages
What Was Done
We integrated the Instagram Graph API into the shipcaptaincrew Lambda function (us-east-1, account 782785212866) to enable dynamic fetching of @sailjada Instagram posts alongside guest-uploaded charter photos. The guest photo page system at shipcaptaincrew.queenofsandiego.com/g/{event_id} previously had dormant Instagram integration that returned empty arrays due to missing environment variables. This post documents the complete setup process, key architectural decisions, and the token lifecycle management strategy.
Technical Details: The Integration Architecture
Why Instagram Graph API (Not Basic Display)
The Instagram Graph API was chosen over Basic Display because we needed to:
- Read media metadata (captions, timestamps, media types)
- Query a business/creator account (@sailjada) associated with a Facebook Page
- Access the
instagram_business_accountedge to retrieve media feeds programmatically
Basic Display is limited to recently-published media and doesn't support business account querying. The Messaging API was initially added but doesn't grant the instagram_basic scope required for media reads—it's designed for inbox management only.
OAuth Token Flow
Instagram's token lifecycle requires a two-stage approach:
- Short-lived Access Token (1 hour): Generated via the Graph API Explorer with scopes
instagram_basicandpages_show_list - Long-lived Access Token (60 days): Exchanged using your app credentials, stored in Lambda environment variables
The long-lived token is what gets stored as IG_ACCESS_TOKEN in the Lambda function configuration. This avoids the need for user re-authentication every hour.
Step-by-Step Setup Process
Step 1: Add the Correct Product
Navigate to the Meta App Dashboard at developers.facebook.com/apps:
- Select the
sailjada-socialapp - Click Add Product (bottom of left sidebar)
- Search for and select
Instagram Graph API - Choose the Graph API access type (not Basic Display or Messaging)
Instagram Graph API will now appear in your left sidebar under Products.
Step 2: Connect @sailjada
Inside Instagram Graph API → API setup with Instagram login:
- Click Add Instagram account
- Authenticate as @sailjada (the Instagram account must be a Business or Creator account)
- Authorize the app to access the account's data
- Confirm that @sailjada is linked to a Facebook Page (this relationship is required for the Graph API to work)
Step 3: Generate a Short-lived Token
Use the Graph API Explorer at developers.facebook.com/tools/explorer:
- Select the
sailjada-socialapp from the dropdown - Click Generate Access Token
- When prompted, select the Facebook Page linked to @sailjada
- In the permissions dialog, enable
instagram_basicandpages_show_list - Copy the resulting access token (valid for ~1 hour)
Step 4: Retrieve IG_USER_ID
Execute the following request in the Graph API Explorer (replace TOKEN with your short-lived token):
GET /me/accounts?fields=id,name
Authorization: Bearer TOKEN
The response lists all Facebook Pages your account manages. Identify your charter business page and note its id. Then execute:
GET /{PAGE_ID}?fields=instagram_business_account
Authorization: Bearer TOKEN
Extract the id from the instagram_business_account object—this is your IG_USER_ID.
Step 5: Exchange for a Long-lived Token
Use a script or curl command to exchange your short-lived token for a 60-day token. This step requires your app's APP_ID and APP_SECRET (stored in a secure secrets manager, not in this example):
GET /oauth/access_token?grant_type=ig_refresh_token
&access_token=SHORT_LIVED_TOKEN
&redirect_uri=https://shipcaptaincrew.queenofsandiego.com/callback
Or via Python using boto3 (if calling from Lambda after initial setup):
import requests
url = "https://graph.instagram.com/oauth/access_token"
params = {
"grant_type": "ig_refresh_token",
"access_token": SHORT_LIVED_TOKEN
}
response = requests.get(url, params=params)
long_lived_token = response.json()["access_token"]
The returned access_token is your IG_ACCESS_TOKEN.
Step 6: Update Lambda Environment Variables
Once you have both values, update the Lambda function configuration:
aws lambda update-function-configuration \
--region us-east-1 \
--function-name shipcaptaincrew \
--environment Variables="{
IG_USER_ID=123456789,
IG_ACCESS_TOKEN=IGQVJxMDE...,
existing_var=value
}"
The Lambda function's existing code checks for these variables and will now populate the guest photo page with Instagram posts from the matching day/time window.
Infrastructure & Key Resources
- Lambda Function:
shipcaptaincrew(us-east-1, account 782785212866) - Meta App:
sailjada-social(registered in Meta App Dashboard) - Guest Photo Page:
shipcaptaincrew.queenofsandiego.com/g/{event_id}(e.g.,/g/2026-04-29) - Instagram Account: @sailjada (Business/Creator account)
Key Architectural Decisions
- Environment Variables vs. Secrets Manager: While environment variables work, storing sensitive tokens in AWS Secrets Manager would be more secure for production. Consider migrating
IG_ACCESS_TOKENto Secrets Manager and updating the Lambda IAM role to permitsecretsmanager:GetSecretValue. - Token Refresh Strategy: The 60-day token requires monthly refresh. Set up an EventBridge rule to trigger a Lambda refresh function on day 50, preventing expiration during active event seasons.
- Error Handling: If