Integrating Instagram Graph API with Lambda: Enabling Dynamic Photo Feed for Guest Event Pages

What Was Done

We activated Instagram Graph API integration for the guest photo page system at shipcaptaincrew.queenofsandiego.com/g/{event_id}, enabling the Lambda function to fetch and display @sailjada Instagram posts alongside user-uploaded charter photos. The integration was previously dormant due to missing environment variables. This post walks through the exact setup process, covering product configuration, token generation, and Lambda environment updates.

The Problem: Incomplete Product Setup

The existing Lambda function shipcaptaincrew (us-east-1, account 782785212866) contained dormant Instagram integration logic that returned empty arrays when IG_USER_ID or IG_ACCESS_TOKEN environment variables were absent. The app sailjada-social in the Facebook Developer Dashboard had a Messaging product configured—appropriate for sending DMs, but insufficient for reading media from an Instagram Business account. This is a critical gotcha: the Messaging product does not grant the instagram_basic scope required for media reads.

Technical Details: Step-by-Step Setup

Step 1: Add Instagram Graph API Product

The Messaging product previously added to sailjada-social handles direct messages, not media access. Instagram Graph API is a separate product required for reading posts, media, and insights:

  • Navigate to developers.facebook.com/apps and select the sailjada-social app
  • In the left sidebar, locate Add Product (near the bottom)
  • Search for "Instagram" in the product catalog
  • Select Instagram Graph API (distinct from Basic Display and Messaging)
  • Confirm setup—it will appear in the left sidebar as a new product section

Step 2: Link @sailjada Instagram Account

The @sailjada account must be a Business or Creator account and linked to a Facebook Page. Within the Instagram Graph API product settings:

  • Navigate to API setup with Instagram login
  • Click Add Instagram account
  • Authenticate as @sailjada
  • Authorize the connection—this enables the account for API access

Step 3: Generate Short-Lived Access Token

Access tokens in Instagram Graph API follow a two-tier model: short-lived tokens (valid for ~1 hour, used immediately) are exchanged for long-lived tokens (valid for 60 days). Generate the short-lived token first:

  • Visit developers.facebook.com/tools/explorer
  • In the top-right dropdown, select app sailjada-social
  • Click Generate Access Token
  • When prompted, select the Facebook Page linked to @sailjada
  • In the scopes dialog, enable: instagram_basic and pages_show_list
  • Accept permissions—the token appears in the access token field

Step 4: Retrieve IG_USER_ID via Graph API Explorer

With the short-lived token in hand, query the Facebook Page to extract the Instagram Business Account ID. In the Graph API Explorer:

  • In the query field, enter: /{PAGE_ID}?fields=instagram_business_account (replace PAGE_ID with the numeric ID of your Facebook Page)
  • Click Submit
  • The response contains "instagram_business_account": { "id": "..." }
  • Extract the id value—this is your IG_USER_ID

Example response structure:

{
  "instagram_business_account": {
    "id": "17841234567890123"
  },
  "id": "123456789"
}

Step 5: Exchange Short-Lived Token for Long-Lived Token

Long-lived tokens (60-day validity) are obtained by exchanging the short-lived token with your app credentials. This is a server-side operation using the Facebook Graph API endpoint:

GET https://graph.instagram.com/access_token \
  ?grant_type=ig_refresh_token \
  &access_token=SHORT_LIVED_TOKEN

Or for initial exchange from a short-lived user token:

GET https://graph.facebook.com/v18.0/oauth/access_token \
  ?client_id=APP_ID \
  &client_secret=APP_SECRET \
  &grant_type=fb_exchange_token \
  &fb_exchange_token=SHORT_LIVED_TOKEN

The response includes:

{
  "access_token": "LONG_LIVED_TOKEN",
  "token_type": "bearer"
}

Store the returned access_token as your IG_ACCESS_TOKEN.

Infrastructure: Updating Lambda Configuration

With IG_USER_ID and IG_ACCESS_TOKEN in hand, update the shipcaptaincrew Lambda function environment variables:

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

These variables are now available to the Lambda runtime. The existing conditional logic in the function checks for their presence—when populated, the integration activates and fetches media via the Instagram Graph API.

Token Refresh Strategy

Long-lived tokens expire after 60 days. Implement a monthly refresh cycle to maintain uninterrupted service:

  • EventBridge-driven approach (optional): Create a scheduled rule that triggers monthly, calling a refresh Lambda function
  • Manual refresh: Run the token exchange request monthly and update Lambda environment variables
  • Recommended: Implement the refresh within a dedicated Lambda or automation function to avoid manual intervention

Verification and Testing

After Lambda configuration updates, test the integration:

  • Visit shipcaptaincrew.queenofsandiego.com/g/2026-04-29 (or another event date with recent posts)
  • Verify that @sailjada Instagram posts appear alongside guest-uploaded photos
  • Check CloudWatch Logs for the shipcaptaincrew function to confirm API calls and response payloads
  • Monitor for any token expiration errors in logs—this signals a needed refresh

Key Architectural Decisions

  • Graph API over Basic Display: Graph API provides richer data (captions, timestamps, insights) compared to Basic Display, enabling better