This workflow follows the HTTP Request → Supabase recipe pattern — see all workflows that pair these two integrations.
The workflow JSON
Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →
{
"name": "05-ig-publish",
"nodes": [
{
"parameters": {
"rule": {
"interval": [
{
"field": "cronExpression",
"expression": "*/10 * * * *"
}
]
}
},
"id": "cron-trigger",
"name": "Cron Trigger (every 10 min)",
"type": "n8n-nodes-base.scheduleTrigger",
"typeVersion": 1.1,
"position": [
0,
0
]
},
{
"parameters": {
"operation": "executeQuery",
"query": "select * from next_reel_to_publish()"
},
"id": "next-reel",
"name": "Supabase: next_reel_to_publish()",
"type": "n8n-nodes-base.supabase",
"typeVersion": 1,
"position": [
200,
0
],
"credentials": {
"supabaseApi": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"conditions": {
"number": [
{
"value1": "={{ $items().length }}",
"value2": 0,
"operation": "equal"
}
]
}
},
"id": "if-no-rows",
"name": "IF: No Rows",
"type": "n8n-nodes-base.if",
"typeVersion": 2,
"position": [
400,
0
]
},
{
"parameters": {
"operation": "executeQuery",
"query": "select token from api_tokens where id = 'ig_long_lived' limit 1"
},
"id": "load-token",
"name": "Load IG Token",
"type": "n8n-nodes-base.supabase",
"typeVersion": 1,
"position": [
600,
-100
],
"credentials": {
"supabaseApi": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"url": "=https://graph.facebook.com/v21.0/{{ $env.IG_BUSINESS_ACCOUNT_ID }}/media",
"method": "POST",
"sendBody": true,
"bodyContentType": "json",
"body": {
"media_type": "REELS",
"video_url": "={{ $('Supabase: next_reel_to_publish()').item.json.final_reel_url }}",
"caption": "={{ $('Supabase: next_reel_to_publish()').item.json.caption + '\\n\\n' + ($('Supabase: next_reel_to_publish()').item.json.hashtags ?? []).join(' ') }}",
"access_token": "={{ $('Load IG Token').item.json.token }}"
}
},
"id": "create-container",
"name": "Create Media Container",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
800,
-100
],
"onError": "continueErrorOutput"
},
{
"parameters": {
"amount": 15,
"unit": "seconds"
},
"id": "wait-15",
"name": "Wait 15s",
"type": "n8n-nodes-base.wait",
"typeVersion": 1.1,
"position": [
1000,
-100
]
},
{
"parameters": {
"url": "=https://graph.facebook.com/v21.0/{{ $('Create Media Container').item.json.id }}",
"method": "GET",
"sendQueryParameters": true,
"queryParameters": {
"parameters": [
{
"name": "fields",
"value": "status_code"
},
{
"name": "access_token",
"value": "={{ $('Load IG Token').item.json.token }}"
}
]
}
},
"id": "poll-container",
"name": "Poll Container Status",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
1200,
-100
]
},
{
"parameters": {
"jsCode": "// Track attempts per container. Bail at 20 attempts (~5 min @ 15s).\nconst containerId = $('Create Media Container').item.json.id;\nconst status = $input.first().json.status_code ?? 'UNKNOWN';\nconst data = $getWorkflowStaticData('node');\nconst key = `ig_${containerId}`;\nconst attempts = (data[key] ?? 0) + 1;\ndata[key] = attempts;\n\nif (status === 'FINISHED') {\n delete data[key];\n return [[{ json: { status, attempts, containerId } }], [], []];\n}\nif (status === 'ERROR') {\n delete data[key];\n return [[], [], [{ json: { status, attempts, containerId, reason: 'ig_container_error' } }]];\n}\nif (attempts >= 20) {\n delete data[key];\n return [[], [], [{ json: { status, attempts, containerId, reason: 'timeout_5min' } }]];\n}\nreturn [[], [{ json: { status, attempts, containerId } }], []];"
},
"id": "branch-container",
"name": "Branch Container Status",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
1400,
-100
]
},
{
"parameters": {
"url": "=https://graph.facebook.com/v21.0/{{ $env.IG_BUSINESS_ACCOUNT_ID }}/media_publish",
"method": "POST",
"sendBody": true,
"bodyContentType": "json",
"body": {
"creation_id": "={{ $('Create Media Container').item.json.id }}",
"access_token": "={{ $('Load IG Token').item.json.token }}"
}
},
"id": "publish-reel",
"name": "Publish Reel",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
1600,
-200
]
},
{
"parameters": {
"operation": "update",
"schema": "public",
"table": "reels_queue",
"filters": {
"conditions": [
{
"keyName": "id",
"condition": "eq",
"keyValue": "={{ $('Supabase: next_reel_to_publish()').item.json.id }}"
}
]
},
"fieldsToSend": "defineBelow",
"dataToSend": {
"values": [
{
"fieldId": "status",
"fieldValue": "posted"
},
{
"fieldId": "posted_at",
"fieldValue": "={{ $now.toISOString() }}"
},
{
"fieldId": "ig_media_id",
"fieldValue": "={{ $json.id }}"
}
]
}
},
"id": "supabase-posted",
"name": "Supabase Update (posted)",
"type": "n8n-nodes-base.supabase",
"typeVersion": 1,
"position": [
1800,
-200
],
"credentials": {
"supabaseApi": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"url": "={{ $env.ALERT_WEBHOOK_URL }}",
"method": "POST",
"sendBody": true,
"bodyContentType": "json",
"body": {
"content": "\u2705 **Posted**: {{ $('Supabase: next_reel_to_publish()').item.json.hook }}\nhttps://www.instagram.com/reel/{{ $('Publish Reel').item.json.id }}"
}
},
"id": "notify-posted",
"name": "Notify Posted",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
2000,
-200
]
},
{
"parameters": {
"url": "={{ $env.ALERT_WEBHOOK_URL }}",
"method": "POST",
"sendBody": true,
"bodyContentType": "json",
"body": {
"content": "\ud83d\udea8 **IG create-container FAILED** for reel `{{ $('Supabase: next_reel_to_publish()').item.json.id }}` ({{ $('Supabase: next_reel_to_publish()').item.json.hook }}). Reel stays `ready`; next cron will retry.\nError: {{ $json.error ?? JSON.stringify($json) }}"
}
},
"id": "alert-container-failed",
"name": "Alert: Container Create Failed",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
1000,
100
]
},
{
"parameters": {
"url": "={{ $env.ALERT_WEBHOOK_URL }}",
"method": "POST",
"sendBody": true,
"bodyContentType": "json",
"body": {
"content": "\u26a0\ufe0f **IG container timeout/error** for reel `{{ $('Supabase: next_reel_to_publish()').item.json.id }}` (status={{ $json.status }}, reason={{ $json.reason }}). Reel stays `ready`; next cron retries."
}
},
"id": "alert-container-timeout",
"name": "Alert: Container Timeout",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
1600,
100
]
}
],
"connections": {
"Cron Trigger (every 10 min)": {
"main": [
[
{
"node": "Supabase: next_reel_to_publish()",
"type": "main",
"index": 0
}
]
]
},
"Supabase: next_reel_to_publish()": {
"main": [
[
{
"node": "IF: No Rows",
"type": "main",
"index": 0
}
]
]
},
"IF: No Rows": {
"main": [
[],
[
{
"node": "Load IG Token",
"type": "main",
"index": 0
}
]
]
},
"Load IG Token": {
"main": [
[
{
"node": "Create Media Container",
"type": "main",
"index": 0
}
]
]
},
"Create Media Container": {
"main": [
[
{
"node": "Wait 15s",
"type": "main",
"index": 0
}
],
[
{
"node": "Alert: Container Create Failed",
"type": "main",
"index": 0
}
]
]
},
"Wait 15s": {
"main": [
[
{
"node": "Poll Container Status",
"type": "main",
"index": 0
}
]
]
},
"Poll Container Status": {
"main": [
[
{
"node": "Branch Container Status",
"type": "main",
"index": 0
}
]
]
},
"Branch Container Status": {
"main": [
[
{
"node": "Publish Reel",
"type": "main",
"index": 0
}
],
[
{
"node": "Wait 15s",
"type": "main",
"index": 0
}
],
[
{
"node": "Alert: Container Timeout",
"type": "main",
"index": 0
}
]
]
},
"Publish Reel": {
"main": [
[
{
"node": "Supabase Update (posted)",
"type": "main",
"index": 0
}
]
]
},
"Supabase Update (posted)": {
"main": [
[
{
"node": "Notify Posted",
"type": "main",
"index": 0
}
]
]
}
},
"settings": {},
"staticData": null,
"tags": [
"reels-automation"
],
"triggerCount": 1,
"updatedAt": "2026-04-18T00:00:00.000Z",
"versionId": "2"
}
Credentials you'll need
Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.
supabaseApi
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
05-ig-publish. Uses supabase, httpRequest. Scheduled trigger; 13 nodes.
Source: https://github.com/ksksrbiz-arch/reels-automation/blob/37630734bcd00a9986c9c64b4c4cdcc31014993d/n8n-workflows/05-ig-publish.json — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
This workflow ingests job postings from Greenhouse/Lever/Ashby job boards, Adzuna, and RemoteOK into a Supabase jobs pool, then daily uses Anthropic Claude to score a short list against a single candi
This workflow solves a common problem with RSS feeds: they often only provide a short summary or snippet of the full article. This template automatically monitors a list of your favorite blog RSS feed
This workflow is a multi-system document synchronization pipeline built in n8n, designed to automatically sync and back up files between Microsoft SharePoint, Supabase/Postgres, and Google Drive.
03 - Recordatorio 4h (CON VERIFICACIÓN) ✅. Uses supabase, httpRequest, twilio. Scheduled trigger; 17 nodes.
02 - Recordatorio 24h antes (CON VERIFICACIÓN) ✅. Uses supabase, httpRequest, twilio. Scheduled trigger; 17 nodes.