Integrating Instagram Graph API with AWS Lambda: Building a Photo Aggregation System for Event Pages

What Was Done

We integrated Instagram's Graph API into an existing Lambda function to automatically surface @sailjada Instagram posts alongside guest-uploaded photos on event charter pages. The system queries Instagram's media endpoints filtered by date/time windows matching guest photo uploads, enabling a unified photo experience without manual curation.

The Lambda function shipcaptaincrew (deployed in us-east-1, AWS account 782785212866) already had dormant Instagram integration code—it returned empty arrays when environment variables were missing. This walkthrough activates that integration by obtaining and storing two critical values: IG_USER_ID (the Instagram Business Account ID) and IG_ACCESS_TOKEN (a long-lived Graph API token).

Technical Details: Authentication Flow

Instagram Graph API requires Business or Creator accounts linked to a Facebook Page. The authentication involves a multi-step token exchange process:

  • Short-lived token generation: Created via the Graph API Explorer with scopes instagram_basic and pages_show_list
  • IG_USER_ID retrieval: Two sequential Graph API calls—first to the Facebook Page to get the instagram_business_account ID, then to extract the numeric user ID
  • Long-lived token exchange: Converts the short-lived token (valid ~2 hours) to a long-lived token (valid 60 days) using the app's credentials

Why this approach? Instagram Graph API doesn't support password-based or refresh token flows. The 60-day long-lived token requires periodic renewal (every 30-45 days as a safety margin) using the same exchange mechanism, which can be automated via EventBridge for hands-off operation.

Step 1: Add the Correct Product to Your Facebook App

The initial blocker was a misconfigured product. The app had "Messaging" added, which grants permissions for Instagram DM functionality—not media reads. This required adding the Instagram Graph API product separately:

  1. Navigate to developers.facebook.com/apps
  2. Select the sailjada-social app
  3. Click Add Product in the left sidebar
  4. Search for and select Instagram Graph API (distinct from Basic Display and Messaging products)
  5. Choose Instagram Graph API as the access type during setup

After adding the product, link the @sailjada Instagram account via API setup → Add Instagram account, logging in with the account's credentials. This establishes the business relationship required for token issuance.

Step 2: Generate Initial Short-Lived Token

Use the Graph API Explorer to obtain a short-lived access token with the correct scopes:

1. Go to developers.facebook.com/tools/explorer
2. Select "sailjada-social" app from the dropdown
3. Click "Generate Access Token"
4. Select the Facebook Page linked to @sailjada
5. Add scopes: instagram_basic, pages_show_list
6. Copy the generated token (valid for ~2 hours)

Store this temporary token in a secure location—you'll exchange it for a long-lived token in the next step.

Step 3: Retrieve IG_USER_ID via Graph API Calls

Execute two API calls using the short-lived token. First, fetch the Instagram Business Account ID from your Facebook Page:

curl -s "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 is your IG_USER_ID. Then query the Instagram Business Account directly to confirm the structure:

curl -s "https://graph.instagram.com/v18.0/{IG_USER_ID}?fields=id,username&access_token={SHORT_LIVED_TOKEN}"

Important: The numeric ID in the response (not the username) is the value you'll store as the IG_USER_ID environment variable.

Step 4: Exchange for Long-Lived Token

Convert the short-lived token to a 60-day long-lived token using your app credentials:

curl -s "https://graph.instagram.com/v18.0/access_token?grant_type=fb_exchange_token&client_id={APP_ID}&client_secret={APP_SECRET}&access_token={SHORT_LIVED_TOKEN}"

The access_token field in the response is your IG_ACCESS_TOKEN—store this value securely. The expires_in field confirms the 60-day validity window.

Infrastructure: Lambda Environment Variable Configuration

Update the shipcaptaincrew Lambda function with the two retrieved values. Use the AWS CLI to avoid exposing credentials in shell history:

aws lambda update-function-configuration \
  --function-name shipcaptaincrew \
  --region us-east-1 \
  --environment "Variables={IG_USER_ID=,IG_ACCESS_TOKEN=,...}"

Alternatively, store these in AWS Secrets Manager and retrieve them within the Lambda handler for better security posture. The function code already contains conditional logic to check for these variables and skip Instagram integration if they're absent.

Key Architectural Decisions

  • Long-lived tokens over refresh flows: Instagram Graph API doesn't support OAuth refresh tokens. The 60-day window requires periodic renewal—acceptable for a low-frequency integration like photo aggregation.
  • Business Account requirement: Personal Instagram accounts don't support Graph API media access. @sailjada must remain configured as a Creator or Business account linked to a Facebook Page.
  • Scope minimalism: instagram_basic (media read) and pages_show_list (page enumeration) are the minimum scopes. No DM, comment, or story permissions are requested.
  • Date/time windowing in Lambda: The function filters Instagram posts by comparing timestamps to guest photo uploads, avoiding duplicate or stale content.

Verification and Next Steps

After updating the Lambda environment variables, navigate to shipcaptaincrew.queenofsandiego.com/g/2026-04-29 (or any past event date with both guest photos and Instagram posts). The page should now display Instagram media alongside uploaded photos.

For production reliability, implement a monthly token refresh scheduled via EventBridge:

  • Create an EventBridge rule that triggers every 30 days
  • Target a Lambda function that invokes the token exchange call and updates Secrets Manager
  • Monitor CloudWatch logs for failed refreshes to catch token expiration before it impacts the live site

This eliminates manual token rotation and ensures the integration remains active across deployment cycles.