Instagram Publishing Pipeline

A 70-node pipeline producing three surfaces from one run — feed post, story and reel — through Instagram's container protocol, with two nested async polling loops that both give up rather than hang.

Client
EpsolDev
Category
Automation Engineering
Completed
2026-08-15
Built with
n8n, Google Vertex AI, REST API
Topics
API Development, Automation
Instagram Publishing Pipeline

n8n 70 nodes 3 surfaces per run Publishing daily

The largest of the five platform pipelines, because Instagram is the only one that can produce three different things from a single run — a feed post, a story and a reel — each with its own publish protocol.

The whole Instagram workflow: the feed path across the top, the reel generation and upload chain below

Part of the Social Distribution Network; the post it distributes comes from the Blog Automation Engine.


Shared front half

Dispatch, the site loop, the schedule gate and the claim gate

Every platform pipeline opens the same way, and for the same reason as the blog engine: one graph serves every client site.

Schedule ─┐
          ├─> Config ─> Dispatch ─┬─> WH Site      (one site, from the webhook)
Webhook  ─┘                       └─> sites_list   (all enabled sites)
                                            │
                                      Loop Over Sites
                                            │
                         Get Config ─> IG Due? ─> Claim Run ─> Claim Granted?

IG Due? is per-site scheduling — a site posting three times a week and one posting daily share this workflow and this trigger. The claim gate then prevents a scheduled tick and a manual webhook from double-posting the same site.


Caption and image, each with a fallback

Caption generation, primary and fallback image generation, and the reel submission branch below

Content comes from the control plane — CBM Next Post → CBM Get Identity → CBM Get Prompts — so tone and brand voice are configured per site rather than baked into the graph.

Generation never gets one attempt:

Gen Image Primary ─> Have Image 1? ─┬─ yes ─> Prep Image
                                    └─ no  ─> Wait ─> Gen Image Fallback
                                                          │
                                                Have Image 2? ─┬─ yes ─> Prep Image
                                                               └─ no  ─> Gen Failed

The Wait between attempts matters: the usual cause of a first-attempt miss is a transient rate limit, and retrying immediately reproduces it exactly.


The media round-trip

Instagram will not take image bytes. It takes a publicly fetchable URL. So the workflow uploads the generated image into the content platform's media library only to obtain that URL — and deletes it once Instagram has ingested it:

Prep Image → CBM Media Upload → Parse Media → publish → CBM Media Delete

The library never fills up with thousands of one-use social images. The delete sits after publish verification, so a failed post keeps its asset for inspection.


Publishing, and then two more surfaces

Credentials, the container protocol, and the story and reel publish chains

Credentials are fetched per run (CBM Get IG Creds → Parse Creds → Creds OK?), so no token lives in the workflow and a revoked one exits cleanly back to the site loop.

The feed post follows Instagram's real protocol rather than an optimistic shortcut:

  • IG Create Container — hand over the caption and media URL
  • Wait IG — let the platform process it
  • IG Publish — promote the container to a live post
  • Verify Publish → Published? — re-read the result before believing it

Only once Published? is true do the extras run:

Story — IG Story Enabled? → container → wait → publish. A second, simpler container cycle.

Reel — the deepest branch in the whole set, and the reason this graph is 70 nodes.


Two asynchronous services in series

The reel path waits on two separate queues that are not ours, and neither wait is unbounded.

First, video generation:

Reel Prep Op -> Reel Wait Poll -> Reel Veo Poll -> Reel Poll Gate
                     ^                                  │
                     │                          Reel Video Ready?
                     │                              │        │
                     └──── no ── Reel Give Up? ─────┘        yes
                                      │                       │
                                    yes -> Reel Gen Failed     v
                                                        Reel Capture Video

Then, Instagram's own container processing — the same shape again: Reel St Wait → Reel St Check → Reel St Gate → Reel St Ready? → Reel St Giveup?.

Both loops have an explicit give-up A workflow that waits forever on someone else's queue eventually holds every execution slot on the instance. Each give-up rejoins CBM Record Post, so a reel that never rendered is recorded as a miss instead of vanishing.


What gets written back

CBM Record Post runs once, at the end, on every path — published, generation failed, reel gave up. The control plane's "what have we posted" view stays truthful because the workflow reports its misses as carefully as its successes.


Stack

n8n Instagram Graph API Google Vertex AI Imagen Veo JavaScript REST API

All projects