The queue is just a Sheet, on purpose
The VideoQueue tab has seven columns: video_key, title,
video_url, fb_caption, ig_caption, status,
published_at. No dashboard, no separate app โ anyone who can edit a spreadsheet can queue up a
week of content. The Code node's whole job is to grab the rows with status == 'ready' and take
the first one, so the order in the sheet is the order it posts.
Matching by video_key, not row number
Early on I matched updates by row position, and it went wrong the first time someone (me) reordered
rows while a run was in flight. Now every match โ reading which row is next, writing back that it published
โ goes through video_key, a stable string I set once per video. Row position drifts. Keys
don't.
The part that actually needs the Graph API
Facebook Page posting is a straightforward POST /{'{page-id}'}/videos with a
file_url and a description. Instagram is a two-step dance: first
POST /{'{ig-id}'}/media with media_type: REELS, the video URL, and a caption,
which hands back a creation_id โ then a second call, POST /{'{ig-id}'}/media_publish,
to actually publish it. In between, I wait 45 seconds flat rather than polling the container's processing
status. That's an honest shortcut: it works fine for short 15-20 second clips, but a longer video would need
real status polling instead of a fixed wait โ I just haven't needed it yet for what I'm posting.
The gotcha nobody mentions: video hosting
Both Graph API endpoints fetch the video by URL server-side โ there's no simple direct-binary-upload path through this flow. So the video needs to already be sitting somewhere with a real public HTTPS URL before either request goes out. I didn't stand up a separate video host for this: the finished MP4s just get copied into the same nginx docroot that already serves the rest of the site, so they're immediately reachable at a normal URL. One less moving part.
Closing the loop
Once both platforms confirm, a Merge node combines the results, the Sheet row flips to
published with a timestamp, and a Telegram message tells me it happened โ or, more usefully,
tells me when one side succeeded and the other didn't.
n8n Automation Hub