{
  "name": "Automated social engine - Instagram",
  "nodes": [
    {
      "parameters": {},
      "id": "00000000-0000-4000-8000-000000000018",
      "name": "When clicking ‘Test workflow’",
      "type": "n8n-nodes-base.manualTrigger",
      "typeVersion": 1,
      "position": [
        0,
        0
      ]
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "00000000-0000-4000-8000-000000000019",
              "name": "idea",
              "value": "Our new PostSider n8n workflows are live",
              "type": "string"
            },
            {
              "id": "00000000-0000-4000-8000-000000000020",
              "name": "tone",
              "value": "confident and friendly",
              "type": "string"
            },
            {
              "id": "00000000-0000-4000-8000-000000000021",
              "name": "mode",
              "value": "approval",
              "type": "string"
            },
            {
              "id": "00000000-0000-4000-8000-000000000022",
              "name": "imageUrl",
              "value": "",
              "type": "string"
            }
          ]
        },
        "options": {}
      },
      "id": "00000000-0000-4000-8000-000000000023",
      "name": "1. Post idea",
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        220,
        0
      ]
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 2
          },
          "conditions": [
            {
              "id": "00000000-0000-4000-8000-000000000024",
              "leftValue": "={{ $json.imageUrl }}",
              "rightValue": "",
              "operator": {
                "type": "string",
                "operation": "isNotEmpty",
                "name": "filter.operator.isNotEmpty"
              }
            }
          ],
          "combinator": "and"
        }
      },
      "id": "00000000-0000-4000-8000-000000000025",
      "name": "2. Own image?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.2,
      "position": [
        440,
        0
      ]
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://api.postsider.com/public/v1/upload-from-url",
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={\"url\": \"{{ $json.imageUrl }}\"}"
      },
      "id": "00000000-0000-4000-8000-000000000026",
      "name": "3a. Upload my image",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        660,
        -180
      ],
      "credentials": {
        "httpHeaderAuth": {
          "id": "1",
          "name": "PostSider API Key"
        }
      }
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://api.openai.com/v1/images/generations",
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={\n  \"model\": \"dall-e-3\",\n  \"prompt\": \"High-quality social media image about: {{ $('1. Post idea').first().json.idea }}. Clean composition, modern style, no text overlays.\",\n  \"n\": 1,\n  \"size\": \"1024x1024\",\n  \"response_format\": \"url\"\n}"
      },
      "id": "00000000-0000-4000-8000-000000000027",
      "name": "3b. Generate image (AI)",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        660,
        180
      ],
      "credentials": {
        "httpHeaderAuth": {
          "id": "2",
          "name": "OpenAI API Key"
        }
      }
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://api.postsider.com/public/v1/upload-from-url",
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={\"url\": \"{{ $json.data[0].url }}\"}"
      },
      "id": "00000000-0000-4000-8000-000000000028",
      "name": "4b. Upload AI image",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        880,
        180
      ],
      "credentials": {
        "httpHeaderAuth": {
          "id": "1",
          "name": "PostSider API Key"
        }
      }
    },
    {
      "parameters": {
        "mode": "combine",
        "combineBy": "combineByPosition",
        "options": {}
      },
      "id": "00000000-0000-4000-8000-000000000029",
      "name": "5. Image ready",
      "type": "n8n-nodes-base.merge",
      "typeVersion": 3.1,
      "position": [
        1100,
        0
      ]
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 2
          },
          "conditions": [
            {
              "id": "00000000-0000-4000-8000-000000000030",
              "leftValue": "={{ ($('1. Post idea').first().json.mode || '').toLowerCase() }}",
              "rightValue": "approval",
              "operator": {
                "type": "string",
                "operation": "equals",
                "name": "filter.operator.equals"
              }
            }
          ],
          "combinator": "and"
        }
      },
      "id": "00000000-0000-4000-8000-000000000031",
      "name": "6. Mode?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.2,
      "position": [
        1320,
        0
      ]
    },
    {
      "parameters": {
        "method": "GET",
        "url": "https://api.postsider.com/public/v1/find-slot/[YOUR POSTSIDER INSTAGRAM CHANNEL ID]"
      },
      "id": "00000000-0000-4000-8000-000000000032",
      "name": "7a. Find best slot",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        1540,
        -180
      ],
      "credentials": {
        "httpHeaderAuth": {
          "id": "1",
          "name": "PostSider API Key"
        }
      }
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://api.openai.com/v1/chat/completions",
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={\n  \"model\": \"gpt-4o-mini\",\n  \"temperature\": 0.8,\n  \"messages\": [\n    { \"role\": \"system\", \"content\": \"You write social media posts for Instagram. Rules: Caption of 2-4 short, human lines with a light hook, then 5-8 relevant hashtags. Visual language, warm and engaging. Respond with the post text only.\" },\n    { \"role\": \"user\", \"content\": \"Topic: {{ $('1. Post idea').first().json.idea }}. Tone: {{ $('1. Post idea').first().json.tone }}. Write the post.\" }\n  ]\n}"
      },
      "id": "00000000-0000-4000-8000-000000000033",
      "name": "8a. Generate post (AI)",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        1760,
        -180
      ],
      "credentials": {
        "httpHeaderAuth": {
          "id": "2",
          "name": "OpenAI API Key"
        }
      }
    },
    {
      "parameters": {
        "mode": "runOnceForAllItems",
        "jsCode": "const slot = $('7a. Find best slot').first().json; // { date } UTC, append 'Z'\nconst ai = $input.first().json;\nconst media = $('5. Image ready').first().json; // { id, path } from whichever upload ran\nconst content = (ai.choices?.[0]?.message?.content || '').trim();\nreturn [{\n  json: {\n    body: {\n      type: 'draft',\n      date: slot.date + 'Z',\n      shortLink: false,\n      tags: [],\n      posts: [{\n        integration: { id: '[YOUR POSTSIDER INSTAGRAM CHANNEL ID]' },\n        value: [{ content, image: [{ id: media.id, path: media.path }] }],\n        settings: {\"__type\":\"instagram\",\"post_type\":\"post\"}\n      }]\n    }\n  }\n}];"
      },
      "id": "00000000-0000-4000-8000-000000000034",
      "name": "9a. Build draft",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1980,
        -180
      ]
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://api.postsider.com/public/v1/posts",
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={{ JSON.stringify($json.body) }}",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Idempotency-Key",
              "value": "=ps-{{ $now.toISO() }}"
            }
          ]
        }
      },
      "id": "00000000-0000-4000-8000-000000000035",
      "name": "10a. Create draft",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        2200,
        -180
      ],
      "credentials": {
        "httpHeaderAuth": {
          "id": "1",
          "name": "PostSider API Key"
        }
      }
    },
    {
      "parameters": {
        "method": "POST",
        "url": "=https://api.postsider.com/public/v1/posts/{{ $json.postId }}/request-approval"
      },
      "id": "00000000-0000-4000-8000-000000000036",
      "name": "11a. Request approval",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        2420,
        -180
      ],
      "credentials": {
        "httpHeaderAuth": {
          "id": "1",
          "name": "PostSider API Key"
        }
      }
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://api.openai.com/v1/chat/completions",
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={\n  \"model\": \"gpt-4o-mini\",\n  \"temperature\": 0.8,\n  \"messages\": [\n    { \"role\": \"system\", \"content\": \"You write social media posts for Instagram. Rules: Caption of 2-4 short, human lines with a light hook, then 5-8 relevant hashtags. Visual language, warm and engaging. Respond with the post text only.\" },\n    { \"role\": \"user\", \"content\": \"Topic: {{ $('1. Post idea').first().json.idea }}. Tone: {{ $('1. Post idea').first().json.tone }}. Write the post.\" }\n  ]\n}"
      },
      "id": "00000000-0000-4000-8000-000000000037",
      "name": "8b. Generate post (AI)",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        1540,
        180
      ],
      "credentials": {
        "httpHeaderAuth": {
          "id": "2",
          "name": "OpenAI API Key"
        }
      }
    },
    {
      "parameters": {
        "mode": "runOnceForAllItems",
        "jsCode": "const ai = $input.first().json;\nconst media = $('5. Image ready').first().json; // { id, path } from whichever upload ran\nconst content = (ai.choices?.[0]?.message?.content || '').trim();\nreturn [{\n  json: {\n    body: {\n      type: 'now',\n      date: '',\n      shortLink: false,\n      tags: [],\n      posts: [{\n        integration: { id: '[YOUR POSTSIDER INSTAGRAM CHANNEL ID]' },\n        value: [{ content, image: [{ id: media.id, path: media.path }] }],\n        settings: {\"__type\":\"instagram\",\"post_type\":\"post\"}\n      }]\n    }\n  }\n}];"
      },
      "id": "00000000-0000-4000-8000-000000000038",
      "name": "9b. Build post",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1760,
        180
      ]
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://api.postsider.com/public/v1/posts",
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={{ JSON.stringify($json.body) }}",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Idempotency-Key",
              "value": "=ps-{{ $now.toISO() }}"
            }
          ]
        }
      },
      "id": "00000000-0000-4000-8000-000000000039",
      "name": "10b. Publish now",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        1980,
        180
      ],
      "credentials": {
        "httpHeaderAuth": {
          "id": "1",
          "name": "PostSider API Key"
        }
      }
    },
    {
      "parameters": {
        "content": "WHAT THIS DOES\nTurns your post idea into an Instagram image post: AI writes the caption, the image is generated with dall-e-3 (or your own image if you set \"imageUrl\"), PostSider uploads it and publishes immediately or via the approval queue.\n\nSETUP (once, about 3 minutes)\n1. PostSider API key: app.postsider.com > Settings > API > Create key. It starts with ps_ and is shown once, so save it.\n2. n8n credentials (both type Header Auth):\n   - \"PostSider API Key\": Name = Authorization, Value = your ps_ key. Select it on every node that talks to PostSider.\n   - \"OpenAI API Key\": Name = Authorization, Value = Bearer sk-... . Select it on the \"(AI)\" nodes.\n3. Channel: replace [YOUR POSTSIDER INSTAGRAM CHANNEL ID] with a real channel id. Find it in the app under Settings > Channels.\n\n4. Image (image platforms only): leave \"imageUrl\" in \"1. Post idea\" empty to generate an image with AI, or paste a URL of your own image to use that instead.\n\nHOW TO RUN\n1. Open \"1. Post idea\" and set: idea (your topic), tone (optional), mode = \"approval\" (draft goes into the approval queue, approve in the app and PostSider schedules it) or mode = \"now\" (publishes immediately). The mode check is case-insensitive.\n2. Click \"Test workflow\".\n\nIMAGE POST: this workflow also generates an image with OpenAI (dall-e-3) and uploads it to PostSider via /public/v1/upload-from-url, so the post is a proper image post. To use your own image instead, paste its URL in \"imageUrl\" in \"1. Post idea\" and AI generation is skipped.\n\nSELF-HOSTED POSTSIDER\nReplace api.postsider.com with your domain; add /api if your install serves the API under /api.",
        "height": 460,
        "width": 520,
        "color": 3
      },
      "id": "00000000-0000-4000-8000-000000000040",
      "name": "How to use",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        0,
        -440
      ]
    },
    {
      "parameters": {
        "content": "SETUP STEP BY STEP\nFollow in order. Do this once per workflow.\n\nSTEP 1 - Create the n8n credentials (do this once, both type Header Auth):\n  a. \"PostSider API Key\": Name = Authorization, Value = your ps_ key (app.postsider.com > Settings > API > Create key).\n  b. \"OpenAI API Key\": Name = Authorization, Value = Bearer sk-... (your OpenAI key, platform.openai.com).\n\nSTEP 2 - \"1. Post idea\" (Set node):\n  idea = your topic (e.g. \"Our new PostSider n8n workflows are live\")\n  tone = optional style (e.g. \"confident and friendly\")\n  mode = \"approval\" (goes into the approval queue) or \"now\" (publishes immediately)\n  imageUrl = leave empty to generate an image with AI, or paste a URL of your own image\n\nSTEP 3 - Select the \"PostSider API Key\" credential on these nodes:\n  - \"7a. Find best slot\" (Find best slot)\n  - \"10a. Create draft\" (Create draft)\n  - \"11a. Request approval\" (Request approval)\n  - \"10b. Publish now\" (Publish now)\n\nSTEP 4 - Select the \"OpenAI API Key\" credential on these nodes:\n  - \"8a. Generate post (AI)\" (Generate post, approval)\n  - \"8b. Generate post (AI)\" (Generate post, now)\n  - \"3b. Generate image (AI)\" (AI image generation)\n  - \"3a. Upload my image\" and \"4b. Upload AI image\" use the \"PostSider API Key\" credential instead.\n\nSTEP 5 - Replace the channel id:\n  Open \"7a. Find best slot\", \"10a. Create draft\", \"9a. Build draft\" and \"9b. Build post\" and replace [YOUR POSTSIDER INSTAGRAM CHANNEL ID] with your real channel id (app > Settings > Channels).\n\nSTEP 6 - Run:\n  Click \"Test workflow\" once to verify everything works before activating the workflow.",
        "height": 640,
        "width": 620,
        "color": 3
      },
      "id": "00000000-0000-4000-8000-000000000041",
      "name": "Setup step by step",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        0,
        -940
      ]
    }
  ],
  "connections": {
    "1. Post idea": {
      "main": [
        [
          {
            "node": "2. Own image?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "2. Own image?": {
      "main": [
        [
          {
            "node": "3a. Upload my image",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "3b. Generate image (AI)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "3a. Upload my image": {
      "main": [
        [
          {
            "node": "5. Image ready",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "3b. Generate image (AI)": {
      "main": [
        [
          {
            "node": "4b. Upload AI image",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "4b. Upload AI image": {
      "main": [
        [
          {
            "node": "5. Image ready",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "5. Image ready": {
      "main": [
        [
          {
            "node": "6. Mode?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "When clicking ‘Test workflow’": {
      "main": [
        [
          {
            "node": "1. Post idea",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "6. Mode?": {
      "main": [
        [
          {
            "node": "7a. Find best slot",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "8b. Generate post (AI)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "7a. Find best slot": {
      "main": [
        [
          {
            "node": "8a. Generate post (AI)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "8a. Generate post (AI)": {
      "main": [
        [
          {
            "node": "9a. Build draft",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "9a. Build draft": {
      "main": [
        [
          {
            "node": "10a. Create draft",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "10a. Create draft": {
      "main": [
        [
          {
            "node": "11a. Request approval",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "8b. Generate post (AI)": {
      "main": [
        [
          {
            "node": "9b. Build post",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "9b. Build post": {
      "main": [
        [
          {
            "node": "10b. Publish now",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "settings": {
    "executionOrder": "v1"
  },
  "pinData": {},
  "active": false,
  "tags": [
    "PostSider",
    "Automated social engine",
    "AI",
    "Instagram"
  ]
}