Integrating Instagram Graph API with AWS Lambda for Guest Photo Aggregation
We recently enabled Instagram media integration in our guest photo page system at shipcaptaincrew.queenofsandiego.com/g/{event_id}. This post documents the technical approach to connecting the Instagram Graph API to our Lambda function, the architectural decisions behind token management, and the setup process we implemented.
What Was Done
The shipcaptaincrew Lambda function (us-east-1, account 782785212866) now pulls Instagram posts from the @sailjada business account and displays them alongside guest-uploaded charter photos within a 24-hour event window. Previously, the Instagram integration code existed but remained dormant due to missing credentials. We implemented a complete token acquisition and refresh strategy to activate this feature.
Technical Architecture
Instagram Graph API Product Setup
The critical first step was adding the correct product to our Facebook app (sailjada-social). While the app previously had the Messaging product configured (for direct message use cases), that product type does not grant the instagram_basic scope required to read media objects. The solution involved:
- Navigating to
developers.facebook.com/appsand selecting thesailjada-socialapp - Adding the Instagram Graph API product (distinct from Basic Display and Messaging variants)
- Connecting the @sailjada business account via the Instagram Graph API setup flow in the app dashboard
Why this approach: The Instagram Graph API product is designed for server-to-server interactions with business accounts and grants the minimal scopes needed for media read operations. This is more secure than broad permissions and follows the principle of least privilege.
Token Acquisition Workflow
We implemented a two-stage token exchange process:
- Short-lived token generation: Using the Graph API Explorer at
developers.facebook.com/tools/explorer, we generated a short-lived access token (valid ~hours) with scopesinstagram_basicandpages_show_list. This token is bound to the user who generated it and is unsuitable for long-term server use. - IG_USER_ID retrieval: With the short-lived token, we made two API calls:
This returned the Facebook Page ID linked to @sailjada. A subsequent call extracted the Instagram Business Account ID:curl "https://graph.instagram.com/v18.0/me/accounts?access_token=SHORT_LIVED_TOKEN"
Thecurl "https://graph.instagram.com/v18.0/{PAGE_ID}?fields=instagram_business_account&access_token=SHORT_LIVED_TOKEN"idfield withininstagram_business_accountbecame ourIG_USER_IDenvironment variable. - Long-lived token exchange: We exchanged the short-lived token for a long-lived token (60-day validity) using the OAuth token exchange endpoint with our app's credentials:
The returnedcurl -X GET "https://graph.instagram.com/v18.0/oauth/access_token?grant_type=ig_refresh_token&access_token=SHORT_LIVED_TOKEN&client_id=APP_ID&client_secret=APP_SECRET"access_tokenbecame ourIG_ACCESS_TOKENLambda environment variable.
Lambda Environment Configuration
The shipcaptaincrew function's configuration was updated with two new environment variables:
IG_USER_ID— the Instagram Business Account ID extracted in step 2IG_ACCESS_TOKEN— the long-lived token from the OAuth exchange
These were applied via the AWS Lambda update command (credentials redacted):
aws lambda update-function-configuration \
--function-name shipcaptaincrew \
--region us-east-1 \
--environment Variables="{IG_USER_ID=...,IG_ACCESS_TOKEN=...,..."
The Lambda code already contained conditional logic to return an empty array if these variables were undefined, so activation required only environment variable injection—no function code changes.
Key Architectural Decisions
Token Lifespan and Refresh Strategy
We chose 60-day long-lived tokens over indefinite tokens because:
- Security rotation: Automatic expiration forces periodic credential rotation, limiting blast radius if a token leaks.
- Operational simplicity: A monthly EventBridge rule can trigger a Lambda that calls the token exchange endpoint and updates the function's environment variables. This avoids manual intervention while respecting the 60-day window.
- Instagram API design: Long-lived tokens are the documented pattern for server-side integrations and are the only choice if immediate user login isn't feasible.
Business Account Requirement
We confirmed that @sailjada is configured as a Business or Creator account (not a Consumer account). Only business accounts have an associated Instagram Graph API ID and can be accessed server-side. This is an Instagram platform constraint, not an implementation choice, but it's worth noting for any future account changes.
Scopes and Permissions
We requested only instagram_basic and pages_show_list scopes. The instagram_basic scope grants access to media objects, media fields, and user information. pages_show_list allows enumeration of Facebook pages linked to the authenticating user. This combination is the minimum required to fetch a list of media from @sailjada without requesting write or insights permissions.
Verification and Next Steps
After environment variable deployment, the Lambda became active. We verified functionality by visiting shipcaptaincrew.queenofsandiego.com/g/2026-04-29 (or any recent event date) and confirming that Instagram posts from @sailjada within the 24-hour window appear alongside guest photos.
The token refresh strategy should be formalized via an EventBridge rule that triggers a helper Lambda monthly. This helper would:
- Call the Instagram token exchange endpoint with the current
IG_ACCESS_TOKEN - Write the new token back to the
shipcaptaincrewfunction's environment - Log the operation for audit trails
Until this is implemented, manual token refresh is required every 60 days, so calendar reminders should be set for the token expiration date (which can be decoded from the JWT if needed).
Summary
The Instagram Graph API integration is now live. The key lesson was understanding that different Facebook app products grant different scopes—choosing the right product at setup time saved significant troubleshooting. The two-stage token flow (short-lived → long-lived) balances security and operational convenience for server-side integrations. Moving forward, automating the token refresh will eliminate manual maintenance and ensure the feature remains active indefinitely.
```