{
  "id": "Wdrvpnwufq6E8tzj",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "Notion content calendar \u2192 Posta multi-platform schedule",
  "tags": [],
  "nodes": [
    {
      "id": "c958b119-539d-48b6-b9c8-237442c446f3",
      "name": "Sticky Note \u2013 Overview",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        3136,
        1200
      ],
      "parameters": {
        "width": 540,
        "height": 1000,
        "content": "## Notion content calendar \u2192 Posta multi-platform schedule\n\n### What it does\n\nEvery 15 minutes, this workflow polls a Notion database for rows that are\n`Status = Approved` and whose `Scheduled At` falls inside the next 15-min\nwindow. For each row it creates a Posta post, schedules it for that time,\nand updates the Notion row with the resulting Posta post URL.\n\n### Notion database schema (required columns)\n\n| Column                | Type           | Notes                                                                        |\n|-----------------------|----------------|------------------------------------------------------------------------------|\n| `Caption`             | Title (text)   | The post body. Used as the Posta caption.                                    |\n| `Status`              | Select         | One of: Draft, Approved, Scheduled, Posted, Failed.                          |\n| `Scheduled At`        | Date (w/ time) | When the post should go live.                                                |\n| `Social Account IDs`  | Text           | Comma-separated Posta social-account IDs (e.g. `35, 42, 99`).               |\n| `Media IDs`           | Text (optional)| Comma-separated Posta media IDs (upload to Posta first; this is by reference)|\n| `Posta Post URL`      | URL (optional) | The workflow writes the Posta post URL back here after scheduling.           |\n\n### Setup steps\n\n- [ ] Add your Posta credential (API token) to every Posta node\n- [ ] Add your Notion integration credential to the Notion nodes\n- [ ] In `Get approved rows`, set the database ID to your content calendar\n- [ ] Confirm the property names match your Notion columns exactly\n- [ ] Activate the workflow (top-right toggle) \u2014 the 15-min cron will start firing\n\n### Customisation\n\n- Tighten the schedule cadence (e.g. every 5 min) if you have many same-day rows.\n- Add an optional `If \u2014 Regenerate with AI` branch after `Split In Batches` to rewrite the caption per-platform via OpenAI before posting. Out of scope for v1."
      },
      "typeVersion": 1
    },
    {
      "id": "0cc754d5-ee8b-42d1-8de7-24284e08e6d1",
      "name": "Sticky Note \u2013 Step 1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        3728,
        1200
      ],
      "parameters": {
        "color": 7,
        "width": 620,
        "height": 360,
        "content": "## 1. Poll Notion every 15 min\n\nFetches every row in the calendar whose `Status = Approved` AND `Scheduled At \u2264 now + 15 min`. The cron interval and the time window are deliberately the same so each row is picked up exactly once."
      },
      "typeVersion": 1
    },
    {
      "id": "e6f406de-613f-401b-bf93-d32f86ce7084",
      "name": "Sticky Note \u2013 Step 2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        4400,
        1200
      ],
      "parameters": {
        "color": 7,
        "width": 360,
        "height": 344,
        "content": "## 2. Create + schedule each post\n\nFor every row returned, create a Posta post with the row's caption, social accounts and (optional) media, then schedule it for the row's `Scheduled At` time."
      },
      "typeVersion": 1
    },
    {
      "id": "a672e111-1751-4bd2-a36e-9b9dec6c6866",
      "name": "Sticky Note \u2013 Step 3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        4816,
        1200
      ],
      "parameters": {
        "color": 7,
        "width": 360,
        "height": 360,
        "content": "## 3. Write the result back to Notion\n\nFlips the row's `Status` to `Scheduled` and writes the Posta post URL into the `Posta Post URL` column so the calendar always reflects what actually shipped."
      },
      "typeVersion": 1
    },
    {
      "id": "56d4a10a-e222-4abd-aa47-4628a5933f07",
      "name": "Every 15 minutes",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        3760,
        1680
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "minutes",
              "minutesInterval": 15
            }
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "4282b2eb-54cb-4955-8e48-fd46271e9049",
      "name": "Get approved rows",
      "type": "n8n-nodes-base.notion",
      "position": [
        3968,
        1680
      ],
      "parameters": {
        "options": {},
        "resource": "databasePage",
        "operation": "getAll",
        "returnAll": true,
        "databaseId": {
          "__rl": true,
          "mode": "url",
          "value": "https://app.notion.com/p/3877383ff7d18062988ae03898b87fa1?v=3877383ff7d180748838000ce8ead0e6&source=copy_link"
        }
      },
      "credentials": {
        "notionApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "4728bab6-4971-4de4-a95d-101640386fdd",
      "name": "For each row",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        4160,
        1680
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 3
    },
    {
      "id": "dedc261b-265c-4b43-a2ea-ef140a79837f",
      "name": "Create a post",
      "type": "n8n-nodes-posta.posta",
      "position": [
        4448,
        1680
      ],
      "parameters": {
        "caption": "={{ $json.property_caption }}",
        "resource": "post",
        "operation": "create",
        "additionalFields": {
          "mediaIds": "={{ $json.property_media_i_ds ? $json.property_media_i_ds.split(',').map(s => s.trim()) : [] }}"
        },
        "socialAccountIds": "={{ String($json.property_social_account_id).split(',').map(s => s.trim()) }}",
        "platformConfigurations": {}
      },
      "credentials": {
        "postaApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "9c454a81-cc18-46f8-863c-4228d31ff6fc",
      "name": "Schedule the post",
      "type": "n8n-nodes-posta.posta",
      "position": [
        4640,
        1680
      ],
      "parameters": {
        "postId": "={{ $json.id }}",
        "operation": "schedule",
        "scheduledAt": "={{ DateTime.fromISO($('For each row').item.json.property_scheduled_at.start).toUTC().toISO() }}"
      },
      "credentials": {
        "postaApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "0e8772c4-2ccc-45d3-bac2-976d7931eb90",
      "name": "Mark row as scheduled",
      "type": "n8n-nodes-base.notion",
      "position": [
        4864,
        1680
      ],
      "parameters": {
        "pageId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $('For each row').item.json.id }}"
        },
        "options": {},
        "resource": "databasePage",
        "operation": "update",
        "propertiesUi": {
          "propertyValues": [
            {
              "key": "Status|status",
              "statusValue": "Scheduled"
            },
            {
              "key": "Posta Post URL|url",
              "urlValue": "={{ $json.platformPostUrl || $('Schedule the post').item.json.url || ('https://getposta.app/app/posts/' + $('Schedule the post').item.json.id) }}"
            }
          ]
        }
      },
      "credentials": {
        "notionApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "45a21d95-3912-4693-9446-94d89fcbe04a",
      "name": "Done",
      "type": "n8n-nodes-base.noOp",
      "position": [
        5024,
        1600
      ],
      "parameters": {},
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "binaryMode": "separate",
    "executionOrder": "v1"
  },
  "versionId": "347db8e6-f61f-42bf-b6cc-45a037128317",
  "nodeGroups": [],
  "connections": {
    "For each row": {
      "main": [
        [
          {
            "node": "Done",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Create a post",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Create a post": {
      "main": [
        [
          {
            "node": "Schedule the post",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Every 15 minutes": {
      "main": [
        [
          {
            "node": "Get approved rows",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get approved rows": {
      "main": [
        [
          {
            "node": "For each row",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Schedule the post": {
      "main": [
        [
          {
            "node": "Mark row as scheduled",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Mark row as scheduled": {
      "main": [
        [
          {
            "node": "For each row",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}