Integrating Instagram Graph API with AWS Lambda: Connecting @sailjada Media to Guest Photo Pages

What Was Done

We enabled Instagram media integration for the guest photo page system at shipcaptaincrew.queenofsandiego.com/g/{event_id}. Previously, the Lambda function had dormant Instagram integration code that returned empty arrays when credentials were missing. We've now established the full authentication pipeline to populate guest event pages with @sailjada Instagram posts from matching date/time windows, displayed alongside user-uploaded charter photos.

Technical Architecture

The solution involves three key components:

  • Facebook App Configuration: A Meta Developer app (sailjada-social) configured with Instagram Graph API product, properly scoped for media reads
  • Token Exchange Pipeline: Short-lived token generation → User ID lookup → Long-lived token exchange (60-day validity)
  • Lambda Environment Variables: The existing shipcaptaincrew Lambda function (us-east-1, account 782785212866) updated with IG_USER_ID and IG_ACCESS_TOKEN

Step-by-Step Setup

1. Add the Correct Product to Your Meta App

This is the critical first step. Many developers add "Messaging" or "Basic Display" — both of which lack the instagram_basic scope needed to read media endpoints.

  • Navigate to developers.facebook.com/apps
  • Select your app (sailjada-social)
  • In the left sidebar, click Add Product
  • Search for Instagram and select Instagram Graph API (the full API, not Basic Display)
  • Complete setup — it will appear in your left sidebar

2. Link Your Instagram Business Account

The @sailjada account must be a Business or Creator account (not a personal account) and linked to a Facebook Page. To verify:

  • In Instagram Graph API settings, click API setup with Instagram login
  • Click Add Instagram account
  • Authenticate as @sailjada. If you see "This account is not eligible," convert it to a Business account first
  • Once linked, note the associated Facebook Page ID

3. Generate a Short-Lived Access Token

We generate a short-lived token first to obtain the User ID, then exchange it for a 60-day token. Use the Graph API Explorer:

  • Visit developers.facebook.com/tools/explorer
  • In the top dropdown, select your app: sailjada-social
  • Click Generate Access Token
  • When prompted for permissions, select the Facebook Page linked to @sailjada
  • In the scopes panel, ensure instagram_basic and pages_show_list are checked
  • Copy the generated token (valid for ~2 hours)

4. Retrieve the Instagram User ID

With your short-lived token, make two API calls. First, get the Page's connected Instagram business account:

curl -X GET "https://graph.instagram.com/v18.0/{PAGE_ID}?fields=instagram_business_account&access_token={SHORT_LIVED_TOKEN}"

The response includes an instagram_business_account object with an id field — this is your IG_USER_ID. Save this value.

5. Exchange for a Long-Lived Token

Short-lived tokens expire in 2 hours. Exchange it for a 60-day long-lived token using your app credentials (stored securely in your deployment pipeline):

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

The response includes a new access_token (60-day validity) — this is your IG_ACCESS_TOKEN.

Infrastructure & Lambda Configuration

Update the shipcaptaincrew Lambda function with the credentials:

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

The existing Lambda code checks for these variables and, when present, fetches recent Instagram media from the @sailjada account using the endpoint:

GET https://graph.instagram.com/v18.0/{IG_USER_ID}/media?fields=id,caption,media_type,media_url,timestamp&access_token={IG_ACCESS_TOKEN}

The Lambda filters results by timestamp, matching posts within the event's date/time window.

Token Refresh Strategy

Instagram long-lived tokens expire after 60 days. Implement monthly refresh using the same exchange endpoint — no user re-authentication required. Options:

  • EventBridge Schedule: Trigger a Lambda monthly to refresh and update environment variables
  • Manual Refresh: Run the exchange call quarterly and update via the AWS CLI or Lambda console
  • Application-Level Caching: Cache the token in a DynamoDB table with TTL, refresh on expiry

We recommend the EventBridge approach for production — it removes manual intervention and centralizes token management.

Why These Design Decisions

  • Graph API over Basic Display: Graph API provides timestamp filtering, caption text, and media type — critical for matching Instagram posts to event windows. Basic Display only returns a URL.
  • 60-Day Tokens Over User Tokens: User-generated access tokens require re-authentication every 60 days. We generate them once, then exchange for app-controlled 60-day tokens that can be refreshed without user involvement.
  • Lambda Environment Variables: Storing credentials in Lambda env vars (encrypted at rest by AWS KMS) keeps them separate from code. Secrets Manager is overkill for non-rotating, non-sensitive tokens in this context.
  • Time Window Filtering in Lambda: The API returns all media; filtering by event timestamp in the Lambda function (not in the query) gives us flexibility to adjust window logic without re-deploying infrastructure.

Verification & Testing

After deploying credentials, test the integration:

  • Navigate to shipcaptaincrew.queenofsandiego.com/g/2026-04-29 (or any event date)
  • Look for Instagram posts from @sailjada in the photo feed