A guide to understand, operate, and extend the workflow.
Goal: Turn a simple Airtable sheet into a content calendar that automatically publishes Instagram Reels via the Instagram Graph API , on a schedule you control in n8n.
Why this matters:
Core flow (one row = one post):
status = "To Post" AND scheduled_at <= NOW() AND platform = "IG".video_url, caption, recordId.ig_media_id, and timestamp.[Cron] 
  → [Airtable: Search records]
    → [Split Out: records]
      → [Set: Map fields]
        → [IG: Create Media Container]
          → [Wait 90s]
            → [IG: Publish Reel]
              → [Airtable: Update record]
Sticky Notes inside the workflow explain each step (they’re rendered from parameters.content with Markdown).
Create a table (e.g., Posts) with these fields:
| Field | Type | Purpose | 
|---|---|---|
| video_url | URL or Text | Directly accessible (public) URL to your MP4 | 
| caption | Long text | Final caption (hashtags, line breaks, emojis) | 
| platform | Single select | Set IGfor this workflow | 
| status | Single select | To Post→ will be picked up;Postedlater | 
| scheduled_at | Date/Time (UTC) | When to post | 
| ig_media_id | Text (optional) | Filled by n8n after publishing | 
| posted_at | Date/Time | Filled by n8n after publishing | 
Filter used in the Airtable “Search records” node:
AND({status}='To Post', {scheduled_at}<=NOW(), {platform}='IG')
Tip: If you localize/rename fields, update the filter accordingly.
IG_API_VERSION (e.g., v21.0)IG_USER_IDIG_ACCESS_TOKENvideo_url (e.g., S3/GCS signed URL, public CDN, Drive/Dropbox direct link). The API pulls from your URL; it cannot fetch files behind logins.searchAND({status}='To Post', {scheduled_at}<=NOW(), {platform}='IG')records[]. Each record has id and fields.records[] array into individual items.recordId.recordId = {{$json.id}}video_url = {{$json.fields.video_url}}caption = {{$json.fields.caption}}scheduled_at = {{$json.fields.scheduled_at}}POST https://graph.facebook.com/{v}/{ig-user-id}/mediavideo_url = {{$json.video_url}}caption = {{$json.caption}}media_type=REELSshare_to_feed=true (optional)access_token=${IG_ACCESS_TOKEN}id (this is your creation_id for publishing).video_url.120–180s.POST https://graph.facebook.com/{v}/{ig-user-id}/media_publishcreation_id = {{$json.id}} (the container id from step E)access_token = ${IG_ACCESS_TOKEN}id = ig_media_id (the published media).status = "Posted"ig_media_id = {{$json.id}}posted_at = {{$now}}video_url = a public MP4 URLcaption = a small captionplatform = IGstatus = To Postscheduled_at = in the past (so it’s due now)idmedia idPosted with ig_media_id and posted_atstatus = To Post, set accurate scheduled_at in UTC.Backfilling:
If you need to post a bunch of older content, set scheduled_at in the past for those rows and let Cron pick them up. If needed, run the workflow manually.


