AutomationFlowsAI & RAG › Publish Ai-written Linkedin Posts with Openai Gpt-5 Mini and Canvora

Publish Ai-written Linkedin Posts with Openai Gpt-5 Mini and Canvora

ByJonnie Lane @marketer-360 on n8n.io

This workflow runs on a Tue/Thu schedule to generate a LinkedIn post with OpenAI, create a matching LinkedIn-ready image via the Canvora API, and then publish the post text plus the downloaded image to LinkedIn. Runs every Tuesday and Thursday at 9:00 AM. Sets the post topic…

Cron / scheduled trigger★★★★☆ complexityAI-powered20 nodesOpenAIHTTP RequestLinkedIn
AI & RAG Trigger: Cron / scheduled Nodes: 20 Complexity: ★★★★☆ AI nodes: yes Added:

This workflow corresponds to n8n.io template #17746 — we link there as the canonical source.

This workflow follows the HTTP Request → LinkedIn 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 →

Download .json
{
  "id": "NToMW6sFTYKqdLrT",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "AI Post \u2192 Canvora Visual \u2192 LinkedIn",
  "tags": [],
  "nodes": [
    {
      "id": "1d159558-7769-4012-aa11-4ed3ab6f85bb",
      "name": "Every Tue & Thu 9am",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        29472,
        11280
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "cronExpression",
              "expression": "0 9 * * 2,4"
            }
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "1513afaa-c561-4a80-8b27-61b0dcf26605",
      "name": "Set Post Parameters",
      "type": "n8n-nodes-base.set",
      "position": [
        29696,
        11280
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "p1",
              "name": "topic",
              "type": "string",
              "value": "practical automation wins for small teams"
            },
            {
              "id": "p2",
              "name": "brandId",
              "type": "string",
              "value": ""
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "4cccb730-d73e-4105-a8c4-3136bffe4719",
      "name": "Write LinkedIn Post",
      "type": "@n8n/n8n-nodes-langchain.openAi",
      "position": [
        29904,
        11280
      ],
      "parameters": {
        "modelId": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-5-mini",
          "cachedResultName": "gpt-5-mini"
        },
        "options": {},
        "messages": {
          "values": [
            {
              "content": "=You are a LinkedIn ghostwriter. Write ONE specific, non-generic LinkedIn post (120-180 words, a concrete angle, a short hook line, no hashtags spam) about: {{ $('Set Post Parameters').item.json.topic }}. Return ONLY the post text."
            }
          ]
        }
      },
      "typeVersion": 1.8
    },
    {
      "id": "224bc9c2-e423-4a15-bc5f-1b7b28962db5",
      "name": "Extract Post Text",
      "type": "n8n-nodes-base.code",
      "position": [
        30176,
        11280
      ],
      "parameters": {
        "jsCode": "const t = $json.message?.content ?? $json.text ?? $json.content ?? '';\nreturn [{ json: { postText: String(t).trim() } }];"
      },
      "typeVersion": 2
    },
    {
      "id": "d6f80700-20b8-4e77-a7c4-c0990f14527e",
      "name": "Post Concept to Canvora",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        30464,
        11280
      ],
      "parameters": {
        "url": "https://api.canvora.ai/api/generations",
        "method": "POST",
        "options": {},
        "jsonBody": "={{ JSON.stringify(Object.assign({\n  inputType: 'idea',\n  inputContent: $('Extract Post Text').item.json.postText,\n  title: 'LinkedIn visual',\n  outputFormats: ['linkedin_post']\n}, $('Set Post Parameters').item.json.brandId ? { brandId: $('Set Post Parameters').item.json.brandId } : {})) }}",
        "sendBody": true,
        "specifyBody": "json",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth"
      },
      "typeVersion": 4.2
    },
    {
      "id": "73c3e0d8-0d17-499d-90b7-0327293ccd89",
      "name": "Wait 30s",
      "type": "n8n-nodes-base.wait",
      "position": [
        30816,
        11280
      ],
      "parameters": {
        "amount": 30
      },
      "typeVersion": 1.1
    },
    {
      "id": "ddd94b3f-9583-40b1-8ef6-b95af8ad38bc",
      "name": "Fetch Generation Status",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        31024,
        11280
      ],
      "parameters": {
        "url": "=https://api.canvora.ai/api/generations/{{ $('Post Concept to Canvora').item.json.generation.id }}",
        "options": {},
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth"
      },
      "typeVersion": 4.2
    },
    {
      "id": "7d0161d4-cd9a-4943-9099-9500e015dcfe",
      "name": "If Generation Done",
      "type": "n8n-nodes-base.if",
      "position": [
        31232,
        11280
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 1,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "t31",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              },
              "leftValue": "={{ ['completed','failed','partial','cancelled'].includes($json.generation.status) }}",
              "rightValue": true
            }
          ]
        }
      },
      "typeVersion": 2
    },
    {
      "id": "fa629c69-90a7-4463-a4b6-841fbea413f2",
      "name": "If Timed Out",
      "type": "n8n-nodes-base.if",
      "position": [
        31232,
        11488
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 1,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "t32",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              },
              "leftValue": "={{ $runIndex >= 20 }}",
              "rightValue": true
            }
          ]
        }
      },
      "typeVersion": 2
    },
    {
      "id": "e4b6c8ea-d035-4a44-b7fe-d110d4c6d2a6",
      "name": "If Generation Succeeded",
      "type": "n8n-nodes-base.if",
      "position": [
        31584,
        11280
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 1,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "t33",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              },
              "leftValue": "={{ ['completed','partial'].includes($json.generation.status) }}",
              "rightValue": true
            }
          ]
        }
      },
      "typeVersion": 2
    },
    {
      "id": "cebb7708-5fa2-4e88-832e-fb9af60af051",
      "name": "Pick Visual URL",
      "type": "n8n-nodes-base.code",
      "position": [
        31792,
        11280
      ],
      "parameters": {
        "jsCode": "const g = $input.first().json.generation;\nconst fileUrl = (g.outputs && g.outputs[0] && g.outputs[0].fileUrl) || '';\nreturn [{ json: { fileUrl, postText: $('Extract Post Text').item.json.postText } }];"
      },
      "typeVersion": 2
    },
    {
      "id": "b31c08d8-2a3f-4a88-a33e-b0396628eecb",
      "name": "Download Visual",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        32000,
        11280
      ],
      "parameters": {
        "url": "={{ $json.fileUrl }}",
        "options": {
          "response": {
            "response": {
              "responseFormat": "file"
            }
          }
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "2a354319-edf8-421d-9be4-84a06a74e331",
      "name": "Publish to LinkedIn",
      "type": "n8n-nodes-base.linkedIn",
      "position": [
        32208,
        11280
      ],
      "parameters": {
        "text": "={{ $('Pick Visual URL').item.json.postText }}",
        "additionalFields": {},
        "shareMediaCategory": "IMAGE"
      },
      "typeVersion": 1
    },
    {
      "id": "dfcc930a-986e-4e79-a631-1b2f9989c100",
      "name": "Generation Failed (credits auto-refunded)",
      "type": "n8n-nodes-base.noOp",
      "position": [
        31968,
        11712
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "ada5238b-46a0-4044-8c07-73a772884308",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        28752,
        11008
      ],
      "parameters": {
        "color": 7,
        "width": 560,
        "height": 1108,
        "content": "## AI Writes the Post, Canvora Designs It \u2192 Publish to LinkedIn\n\n### How it works\nOn a schedule, an AI model writes one specific LinkedIn post about your topic.\nCanvora turns that concept into a finished, on-brand **LinkedIn visual**, and\nthe workflow **publishes the post + image straight to LinkedIn** \u2014 no manual\nstep. Because Canvora returns a hosted image URL, the visual is downloaded and\nattached natively (no separate S3/Cloudinary upload needed).\n\n### Setup steps\n- Create a free Canvora account at canvora.ai \u2014 free credits, no card \u2014 and\n  copy an API key from Integrations \u2192 API Keys (all plans).\n- In each Canvora HTTP Request node, add a **Header Auth** credential:\n  name `X-API-Key`, value your `vd_...` key.\n- Add your OpenAI credential (or swap the node for Claude / Gemini).\n- Connect your LinkedIn credential (personal or organization).\n- Edit \"Set Post Parameters\" \u2014 set your topic and optional `brandId`.\n\n### Customization\n- Change the cron in the trigger to your posting cadence.\n- Swap `linkedin_post` for `linkedin_carousel` to publish a multi-slide post\n  (100+ formats: GET https://api.canvora.ai/api/formats).\n- Pass a `brandId` (GET /api/brands) to lock the visual to your brand kit.\n- Prefer human review? Change the LinkedIn node to \"create draft\" or route to\n  a Gmail draft first.\n- Cost: 1 visual = 10 credits per post.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "01a2bcdd-9b99-4cad-a7d6-376dda824f23",
      "name": "Sticky Note100",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        29408,
        11120
      ],
      "parameters": {
        "color": 7,
        "width": 908,
        "height": 358,
        "content": "## Write the post\n\nOn a schedule, set your topic and an AI model writes one specific LinkedIn post; the text is extracted for Canvora."
      },
      "typeVersion": 1
    },
    {
      "id": "eb3c1faa-84c2-4928-b228-7d9f99c103ea",
      "name": "Sticky Note101",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        30400,
        11040
      ],
      "parameters": {
        "color": 7,
        "width": 256,
        "height": 390,
        "content": "## Design the visual\n\nSends the post concept to Canvora, which designs an on-brand LinkedIn visual."
      },
      "typeVersion": 1
    },
    {
      "id": "e0cbdc00-c3ca-4d90-9e10-c51fde1af01d",
      "name": "Sticky Note102",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        30768,
        11120
      ],
      "parameters": {
        "color": 7,
        "width": 650,
        "height": 530,
        "content": "## Poll generation status\n\nWaits between checks, fetches the state, and loops until the visual finishes or it times out."
      },
      "typeVersion": 1
    },
    {
      "id": "55011942-ad57-4ccb-88f6-4aecae5365b1",
      "name": "Sticky Note103",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        31504,
        11120
      ],
      "parameters": {
        "color": 7,
        "width": 908,
        "height": 310,
        "content": "## Publish to LinkedIn\n\nOn success, downloads the hosted visual and publishes the post + image straight to LinkedIn."
      },
      "typeVersion": 1
    },
    {
      "id": "835a92fd-c6a8-4497-bf84-2f8b92f165d2",
      "name": "Sticky Note104",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        31904,
        11488
      ],
      "parameters": {
        "color": 7,
        "width": 256,
        "height": 390,
        "content": "## Handle failure\n\nIf generation fails or times out, credits are refunded automatically."
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "binaryMode": "separate",
    "availableInMCP": false,
    "executionOrder": "v1"
  },
  "versionId": "e7f2528c-6006-427c-a661-91a4ce958533",
  "nodeGroups": [],
  "connections": {
    "Wait 30s": {
      "main": [
        [
          {
            "node": "Fetch Generation Status",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "If Timed Out": {
      "main": [
        [
          {
            "node": "Generation Failed (credits auto-refunded)",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Wait 30s",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Download Visual": {
      "main": [
        [
          {
            "node": "Publish to LinkedIn",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Pick Visual URL": {
      "main": [
        [
          {
            "node": "Download Visual",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract Post Text": {
      "main": [
        [
          {
            "node": "Post Concept to Canvora",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "If Generation Done": {
      "main": [
        [
          {
            "node": "If Generation Succeeded",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "If Timed Out",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Every Tue & Thu 9am": {
      "main": [
        [
          {
            "node": "Set Post Parameters",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set Post Parameters": {
      "main": [
        [
          {
            "node": "Write LinkedIn Post",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Write LinkedIn Post": {
      "main": [
        [
          {
            "node": "Extract Post Text",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch Generation Status": {
      "main": [
        [
          {
            "node": "If Generation Done",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "If Generation Succeeded": {
      "main": [
        [
          {
            "node": "Pick Visual URL",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Generation Failed (credits auto-refunded)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Post Concept to Canvora": {
      "main": [
        [
          {
            "node": "Wait 30s",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

About this workflow

This workflow runs on a Tue/Thu schedule to generate a LinkedIn post with OpenAI, create a matching LinkedIn-ready image via the Canvora API, and then publish the post text plus the downloaded image to LinkedIn. Runs every Tuesday and Thursday at 9:00 AM. Sets the post topic…

Source: https://n8n.io/workflows/17746/ — original creator credit. Request a take-down →

More AI & RAG workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

AI & RAG

Daily trigger scans your Notion database for unpublished blog ideas AI generates complete blog posts + engaging LinkedIn content using OpenAI (Blog Posting is not implemented yet) Creates custom image

Notion, Error Trigger, Gmail +3
AI & RAG

Automate LinkedIn Posts with AI. Uses scheduleTrigger, stickyNote, notion, linkedIn. Scheduled trigger; 11 nodes.

Notion, LinkedIn, HTTP Request +1
AI & RAG

This template is based on the following template. Thank you for the groundwork, Matheus. Store your snippets of text in a Notion table. Each snippet should have an image associated with it (copy + pas

Notion, LinkedIn, HTTP Request +1
AI & RAG

AI Institutional Stock Valuation Engine with Risk Scoring & Scenario Targets

Google Sheets, XML, HTTP Request +3
AI & RAG

Overview This is a production-grade, fully automated stock analysis system built entirely in n8n. It combines institutional-level financial analysis, dual AI model consensus, and a self-improving back

Google Sheets, XML, HTTP Request +3