n8nflow.net logo

Automated Instagram Reels Posting from Airtable Content Calendar

by Sulieman SaidUpdated: Last update a month agoSource: n8n.io
Loading workflow viewer...

A guide to understand, operate, and extend the workflow.


1) What this workflow does (and why it’s useful)

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:

  • Your team plans everything in Airtable (user-friendly, collaborative).
  • n8n posts for you at the right time, every time.
  • You keep full control (no third-party SaaS lock-in, no manual uploads).
  • Later, you can reuse the same queue to post YouTube Shorts / TikTok (omnichannel).

Core flow (one row = one post):

  1. Cron starts the workflow at a set time.
  2. Airtable – Search grabs due rows: status = "To Post" AND scheduled_at <= NOW() AND platform = "IG".
  3. Split Out processes each row individually.
  4. Set (Map fields) normalizes Airtable fields → video_url, caption, recordId.
  5. IG: Create Media Container registers your video as REEL.
  6. Wait 90s lets IG process the video.
  7. IG: Publish Reel publishes the container.
  8. Airtable – Update marks the row as Posted , stores ig_media_id, and timestamp.

2) Architecture at a glance

[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).


3) Airtable schema (recommended)

Create a table (e.g., Posts) with these fields:

FieldTypePurpose
video_urlURL or TextDirectly accessible (public) URL to your MP4
captionLong textFinal caption (hashtags, line breaks, emojis)
platformSingle selectSet IG for this workflow
statusSingle selectTo Post → will be picked up; Posted later
scheduled_atDate/Time (UTC)When to post
ig_media_idText (optional)Filled by n8n after publishing
posted_atDate/TimeFilled 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.


4) Prerequisites & credentials

  • Instagram Business/Creator account connected to a Facebook Page.
  • IG User ID for the connected account.
  • Long-lived IG Access Token with permissions to create and publish content.
  • n8n environment variables (Settings → Environments):
    • IG_API_VERSION (e.g., v21.0)
    • IG_USER_ID
    • IG_ACCESS_TOKEN
  • Airtable credential in n8n using a Personal Access Token (as in your example).
  • A publicly accessible video_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.

5) Node-by-node deep dive (what each node expects/returns)

A) Cron Trigger

  • What it does: Starts the workflow on a schedule (daily at 09:00 in the template).
  • How to use: Adjust hours/minutes to your cadence (hourly, twice a day, etc.).

B) Airtable: Search records

  • Operation: search
  • Base/Table: Select from dropdowns (matches your account).
  • Options → filterByFormula: AND({status}='To Post', {scheduled_at}<=NOW(), {platform}='IG')
  • Return: An array under records[]. Each record has id and fields.

C) Split Out: records

  • What it does: Turns the records[] array into individual items.
  • Why: Downstream steps can then act on each post separately.

D) Set: Map fields

  • What it does: Normalizes data to predictable keys and keeps the recordId.
  • Outputs:
    • recordId = {{$json.id}}
    • video_url = {{$json.fields.video_url}}
    • caption = {{$json.fields.caption}}
    • scheduled_at = {{$json.fields.scheduled_at}}

E) IG: Create Media Container (REELS)

  • Endpoint: POST https://graph.facebook.com/{v}/{ig-user-id}/media
  • Body params:
    • video_url = {{$json.video_url}}
    • caption = {{$json.caption}}
    • media_type=REELS
    • share_to_feed=true (optional)
    • access_token=${IG_ACCESS_TOKEN}
  • Return: JSON with container id under id (this is your creation_id for publishing).

F) Wait 90s

  • Why: IG needs time to process the video behind video_url.
  • Tip: If your videos are large or high bitrate, you may increase to 120–180s.

G) IG: Publish Reel

  • Endpoint: POST https://graph.facebook.com/{v}/{ig-user-id}/media_publish
  • Body params:
    • creation_id = {{$json.id}} (the container id from step E)
    • access_token = ${IG_ACCESS_TOKEN}
  • Return: JSON with id = ig_media_id (the published media).

H) Airtable: Update record

  • What it does: Writes results back to the same row.
  • Fields updated (example):
    • status = "Posted"
    • ig_media_id = {{$json.id}}
    • posted_at = {{$now}}

6) First-run checklist (do this once)

  1. In both Airtable nodes , pick your Base and Table (via dropdown).
  2. Confirm filterByFormula matches your field names exactly.
  3. Add one test row in Airtable:
    • video_url = a public MP4 URL
    • caption = a small caption
    • platform = IG
    • status = To Post
    • scheduled_at = in the past (so it’s due now)
  4. Set Cron to run in the next minute (or click Execute Workflow manually).
  5. Confirm the flow:
    • Airtable search → returns 1 record
    • Container created → you get an id
    • After 90s → Publish returns a media id
    • Airtable updated → row becomes Posted with ig_media_id and posted_at

7) Daily operations (how to use it day-to-day)

  • Your team fills Airtable with upcoming posts.
  • Keep status = To Post, set accurate scheduled_at in UTC.
  • n8n’s Cron checks regularly and posts due items.
  • After publishing, the row is marked Posted (so it won’t re-post).

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.