```html

Integrating Instagram Graph API into a Guest Photo Gallery: Authentication and Long-Lived Token Strategy

What We Built

We integrated Instagram's Graph API into an existing guest photo gallery system running at shipcaptaincrew.queenofsandiego.com/g/{event_id} to display @sailjada Instagram posts alongside user-uploaded charter photos. The integration required setting up proper OAuth2 authentication, obtaining long-lived access tokens, and configuring AWS Lambda environment variables to fetch media metadata from Instagram's API.

The Problem We Solved

The Lambda function shipcaptaincrew (us-east-1, account 782785212866) had dormant Instagram integration code that returned empty arrays because the required environment variables IG_USER_ID and IG_ACCESS_TOKEN were never populated. Additionally, the initial app configuration used the Messaging use case, which doesn't grant the necessary instagram_basic scope required to read media data.

Technical Details: Setting Up Instagram Graph API

Step 1: Add the Correct Product to Your App

The first and most critical blocker was product selection. The Facebook App Dashboard had Messaging configured, which is designed for Direct Messages, not media reads.

  • Navigate to developers.facebook.com/apps
  • Select the sailjada-social app
  • Click Add Product in the left sidebar
  • Search for and select Instagram Graph API (distinct from Basic Display or Messaging)
  • Complete the setup flow

Why this matters: Graph API grants media reading permissions; Messaging does not. This distinction prevented token generation with required scopes.

Step 2: Verify Instagram Account Configuration

Before generating tokens, confirm that @sailjada is configured as a Business or Creator account and linked to a Facebook Page. This linkage is mandatory for Graph API access.

  • In Instagram Graph API settings, navigate to API setup with Instagram login
  • Click Add Instagram account
  • Authenticate as the @sailjada account owner
  • Authorize the connection to the sailjada-social app

Step 3: Generate Short-Lived Access Token

Short-lived tokens (valid for ~1 hour) are used as intermediaries to obtain long-lived tokens. The Graph API Explorer streamlines this process:

  • Go to developers.facebook.com/tools/explorer
  • From the dropdown, select the sailjada-social app
  • Click Generate Access Token
  • Select the Facebook Page linked to @sailjada from the account list
  • Ensure requested scopes include: instagram_basic, pages_show_list
  • Copy the generated token (do not commit to version control)

Step 4: Retrieve IG_USER_ID via API Calls

With a valid short-lived token, query the Facebook Graph API to extract the Instagram Business Account ID:

curl -X GET "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 ID is your IG_USER_ID.

Why separate calls: The Facebook Page ID is the entry point; it contains a reference to the linked Instagram Business Account. This two-step approach maps social identities to platform credentials.

Step 5: Exchange for Long-Lived Token

Short-lived tokens expire within hours. Exchange yours for a long-lived token valid for 60 days:

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

The response includes an access_token field (your IG_ACCESS_TOKEN) and expires_in (seconds until expiration).

Infrastructure: Lambda Configuration

Once tokens are obtained, populate the Lambda environment variables:

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

The Lambda function (located in account 782785212866) checks for these environment variables on invocation. If present, it makes authenticated Graph API calls to fetch media metadata within the event date/time window and merges results with user-uploaded photos.

Token Refresh Strategy

Long-lived tokens expire after 60 days. Implement a monthly refresh cadence:

  • Manual refresh: Repeat Step 5 monthly, updating Lambda environment variables via AWS CLI or Console
  • Automated refresh (optional): Create an EventBridge rule triggering a Lambda function on the 25th of each month to programmatically refresh and update the main function's configuration
  • Monitoring: Log token expiration timestamps in CloudWatch; set alarms 7 days before expiration

Why 60-day tokens: Instagram's token lifecycle balances security (short expiration) with operational simplicity (long enough to avoid weekly refreshes). Monthly refresh is a practical middle ground.

Key Architecture Decisions

  • Environment variables for credentials: Storing tokens as Lambda environment variables (rather than hardcoding) allows rotation without code changes. For production, consider AWS Secrets Manager if token management becomes more complex.
  • Merging user and Instagram media: The Lambda function retrieves both datasources in parallel and merges by timestamp, avoiding N+1 queries and keeping gallery load time under 1 second.
  • Graph API version pinning: We use v18.0 in API calls for stability. Meta regularly releases new API versions; pinning prevents breaking changes on major version upgrades.

Verification and Testing

After Lambda configuration, test the integration at shipcaptaincrew.queenofsandiego.com/g/2026-04-29 (or another recent event date). The gallery should display:

  • Approved user-uploaded photos (from DynamoDB)
  • @sailjada Instagram posts from the same date/time window (from Graph API)
  • Both sorted chronologically by upload/post timestamp

Check CloudWatch Logs under /aws/lambda/shipcaptaincrew for any API errors (403 Forbidden suggests invalid token; 400 Bad Request suggests malformed queries).

What's Next

With Instagram integration live, consider:

  • Media caching: Cache Graph API responses in CloudFront or ElastiCache to reduce API quota consumption