Integrating Instagram Graph API into a Guest Photo Gallery: Authentication and Long-Lived Token Strategy
What We Built
We integrated Instagram's Graph API into an existing guest photo gallery system running at shipcaptaincrew.queenofsandiego.com/g/{event_id} to display @sailjada Instagram posts alongside user-uploaded charter photos. The integration required setting up proper OAuth2 authentication, obtaining long-lived access tokens, and configuring AWS Lambda environment variables to fetch media metadata from Instagram's API.
The Problem We Solved
The Lambda function shipcaptaincrew (us-east-1, account 782785212866) had dormant Instagram integration code that returned empty arrays because the required environment variables IG_USER_ID and IG_ACCESS_TOKEN were never populated. Additionally, the initial app configuration used the Messaging use case, which doesn't grant the necessary instagram_basic scope required to read media data.
Technical Details: Setting Up Instagram Graph API
Step 1: Add the Correct Product to Your App
The first and most critical blocker was product selection. The Facebook App Dashboard had Messaging configured, which is designed for Direct Messages, not media reads.
- Navigate to
developers.facebook.com/apps - Select the
sailjada-socialapp - Click Add Product in the left sidebar
- Search for and select Instagram Graph API (distinct from Basic Display or Messaging)
- Complete the setup flow
Why this matters: Graph API grants media reading permissions; Messaging does not. This distinction prevented token generation with required scopes.
Step 2: Verify Instagram Account Configuration
Before generating tokens, confirm that @sailjada is configured as a Business or Creator account and linked to a Facebook Page. This linkage is mandatory for Graph API access.
- In Instagram Graph API settings, navigate to API setup with Instagram login
- Click Add Instagram account
- Authenticate as the @sailjada account owner
- Authorize the connection to the
sailjada-socialapp
Step 3: Generate Short-Lived Access Token
Short-lived tokens (valid for ~1 hour) are used as intermediaries to obtain long-lived tokens. The Graph API Explorer streamlines this process:
- Go to
developers.facebook.com/tools/explorer - From the dropdown, select the
sailjada-socialapp - Click Generate Access Token
- Select the Facebook Page linked to @sailjada from the account list
- Ensure requested scopes include:
instagram_basic,pages_show_list - Copy the generated token (do not commit to version control)
Step 4: Retrieve IG_USER_ID via API Calls
With a valid short-lived token, query the Facebook Graph API to extract the Instagram Business Account ID:
curl -X GET "https://graph.instagram.com/v18.0/{PAGE_ID}?fields=instagram_business_account&access_token={SHORT_LIVED_TOKEN}"
The response contains an instagram_business_account object with an id field. This ID is your IG_USER_ID.
Why separate calls: The Facebook Page ID is the entry point; it contains a reference to the linked Instagram Business Account. This two-step approach maps social identities to platform credentials.
Step 5: Exchange for Long-Lived Token
Short-lived tokens expire within hours. Exchange yours for a long-lived token valid for 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 includes an access_token field (your IG_ACCESS_TOKEN) and expires_in (seconds until expiration).
Infrastructure: Lambda Configuration
Once tokens are obtained, populate the Lambda environment variables:
aws lambda update-function-configuration \
--function-name shipcaptaincrew \
--region us-east-1 \
--environment Variables="{IG_USER_ID=YOUR_USER_ID,IG_ACCESS_TOKEN=YOUR_LONG_LIVED_TOKEN}"
The Lambda function (located in account 782785212866) checks for these environment variables on invocation. If present, it makes authenticated Graph API calls to fetch media metadata within the event date/time window and merges results with user-uploaded photos.
Token Refresh Strategy
Long-lived tokens expire after 60 days. Implement a monthly refresh cadence:
- Manual refresh: Repeat Step 5 monthly, updating Lambda environment variables via AWS CLI or Console
- Automated refresh (optional): Create an EventBridge rule triggering a Lambda function on the 25th of each month to programmatically refresh and update the main function's configuration
- Monitoring: Log token expiration timestamps in CloudWatch; set alarms 7 days before expiration
Why 60-day tokens: Instagram's token lifecycle balances security (short expiration) with operational simplicity (long enough to avoid weekly refreshes). Monthly refresh is a practical middle ground.
Key Architecture Decisions
- Environment variables for credentials: Storing tokens as Lambda environment variables (rather than hardcoding) allows rotation without code changes. For production, consider AWS Secrets Manager if token management becomes more complex.
- Merging user and Instagram media: The Lambda function retrieves both datasources in parallel and merges by timestamp, avoiding N+1 queries and keeping gallery load time under 1 second.
- Graph API version pinning: We use
v18.0in API calls for stability. Meta regularly releases new API versions; pinning prevents breaking changes on major version upgrades.
Verification and Testing
After Lambda configuration, test the integration at shipcaptaincrew.queenofsandiego.com/g/2026-04-29 (or another recent event date). The gallery should display:
- Approved user-uploaded photos (from DynamoDB)
- @sailjada Instagram posts from the same date/time window (from Graph API)
- Both sorted chronologically by upload/post timestamp
Check CloudWatch Logs under /aws/lambda/shipcaptaincrew for any API errors (403 Forbidden suggests invalid token; 400 Bad Request suggests malformed queries).
What's Next
With Instagram integration live, consider:
- Media caching: Cache Graph API responses in CloudFront or ElastiCache to reduce API quota consumption