Automated Instagram Reels Posting from Airtable Content Calendar

Go to Workflow
0 views
Built by SuS SuS
Created on June 13, 2026

Description


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):
Cron starts the workflow at a set time.
Airtable – Search grabs due rows: status = "To Post" AND scheduled_at <= NOW() AND platform = "IG".
Split Out processes each row individually.
Set (Map fields) normalizes Airtable fields → video_url, caption, recordId.
IG: Create Media Container registers your video as REEL.
Wait 90s lets IG process the video.
IG: Publish Reel publishes the container.
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:

| 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 IG for this workflow |
| status | Single select | To Post → will be picked up; Posted later |
| 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.

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)

In both Airtable nodes, pick your Base and Table (via dropdown).
Confirm filterByFormula matches your field names exactly.
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)
Set Cron to run in the next minute (or click Execute Workflow manually).
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.

Nodes Used (2)

Airtable
n8n-nodes-base.airtable
HTTP Request
n8n-nodes-base.httpRequest