Integrating Instagram Graph API with AWS Lambda: Adding Social 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 display @sailjada Instagram posts alongside guest-uploaded charter photos on the guest gallery page at shipcaptaincrew.queenofsandiego.com/g/{event_id}. The integration was dormant in the codebase but lacked proper token provisioning and Instagram app configuration. This walkthrough documents the complete setup process from app configuration through Lambda environment variable deployment.

Technical Details: Instagram Graph API Setup

Step 1: Product Configuration in Facebook App Dashboard

The critical first step that was blocking implementation: the app had a "Messaging" product added, which grants Direct Message scopes but not media read permissions. Instagram Graph API requires a separate product.

  • Navigate to developers.facebook.com/apps and select the sailjada-social app
  • Click Add Product in the left sidebar (near the bottom)
  • Search for and select Instagram Graph API (distinct from Basic Display and Messaging products)
  • Complete setup — this grants access to media endpoints and business account data

Why this matters: The Messaging product only grants instagram_manage_messages scope. Reading media requires instagram_basic and pages_show_list scopes, which are only available under the Instagram Graph API product.

Step 2: Instagram Account Connection

The @sailjada account must be a Business or Creator account linked to a Facebook Page, and explicitly connected in the app settings:

  • In Instagram Graph API section of app dashboard, select API setup with Instagram login
  • Click Add Instagram account
  • Log in as @sailjada to authorize the connection

Step 3: Generate Short-Lived Access Token

Use the Graph API Explorer to generate an initial token with the required scopes:

  • Visit developers.facebook.com/tools/explorer
  • Select sailjada-social app from the dropdown
  • Click Generate Access Token
  • Select the Facebook Page linked to @sailjada
  • In the scopes list, select: instagram_basic and pages_show_list

This produces a short-lived token (typically 1 hour) used in the next step.

Step 4: Extract IG_USER_ID from Page Data

Use the short-lived token to query the Facebook Page and retrieve the linked Instagram Business Account ID:

curl -s "https://graph.facebook.com/v18.0/{PAGE_ID}?fields=instagram_business_account&access_token={SHORT_LIVED_TOKEN}" | jq .

The response contains instagram_business_account.id — this is your IG_USER_ID.

Step 5: Exchange for Long-Lived Token

The short-lived token is only valid for ~1 hour. Exchange it for a long-lived token (60 days) that can be stored in Lambda environment variables:

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

The returned access_token is your IG_ACCESS_TOKEN.

Why exchange tokens: Short-lived tokens expire quickly; long-lived tokens allow Lambda to read Instagram data without requesting a new token on every invocation. The 60-day expiration requires a monthly refresh strategy (covered below).

Infrastructure: Lambda Configuration

Function Details

  • Function name: shipcaptaincrew
  • Region: us-east-1
  • Account: 782785212866
  • Runtime: Python 3.x (with boto3 and requests libraries)
  • Execution role: Standard Lambda service role with no special Instagram API permissions needed (API calls are made from Lambda code, not via AWS credentials)

Environment Variables to Deploy

Update Lambda configuration with the two values obtained above. Use the AWS CLI or console:

aws lambda update-function-configuration \
  --function-name shipcaptaincrew \
  --region us-east-1 \
  --environment Variables='{IG_USER_ID=17841400000000000,IG_ACCESS_TOKEN=IGQWRfNDAwODAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMD