AutomationFlowsWeb Scraping › Generate Stale Page Reports for Confluence Spaces with REST API V1 and V2

Generate Stale Page Reports for Confluence Spaces with REST API V1 and V2

ByAlexander Schnabl @alexschnabl on n8n.io

This workflow generates a stale page report for Confluence spaces, helping teams keep documentation accurate, relevant, and actively maintained. Identifies Confluence pages not updated within a defined cutoff period (in days). Supports both: Confluence REST API v1 (CQL search),…

Event trigger★★★★☆ complexity18 nodesHTTP Request
Web Scraping Trigger: Event Nodes: 18 Complexity: ★★★★☆ Added:

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

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": "9JYvVCRYkzaaUURK",
  "name": "Report stale pages in Confluence",
  "tags": [
    {
      "id": "0FRymMOqi6UCCYTI",
      "name": "free",
      "createdAt": "2025-12-25T11:06:36.527Z",
      "updatedAt": "2025-12-25T11:06:36.527Z"
    },
    {
      "id": "ks1tninGT7ZLrbrc",
      "name": "template",
      "createdAt": "2025-12-31T15:16:19.399Z",
      "updatedAt": "2025-12-31T15:16:19.399Z"
    }
  ],
  "nodes": [
    {
      "id": "86a3fab8-8a58-486b-a6bd-410fe3227d46",
      "name": "When clicking \u2018Execute workflow\u2019",
      "type": "n8n-nodes-base.manualTrigger",
      "position": [
        -800,
        -272
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "aeabbb6d-18eb-4165-9de2-a49ad7a88cae",
      "name": "Set Variables",
      "type": "n8n-nodes-base.set",
      "position": [
        -576,
        -272
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "0d1afc81-e801-46dc-b23e-a6a2b00e69e3",
              "name": "atlassianDomain",
              "type": "string",
              "value": "https://yourDomain.atlassian.net"
            },
            {
              "id": "67cd8d60-6c1b-4913-be82-866f80dbea3b",
              "name": "spaceKeys",
              "type": "string",
              "value": "space1, space2"
            },
            {
              "id": "850d7428-fbb9-4f0d-9177-7d1fc4f8a55a",
              "name": "cutoffDateDays",
              "type": "number",
              "value": 30
            },
            {
              "id": "385ef989-9a3c-4bc7-ab03-6051b6de3467",
              "name": "apiV2",
              "type": "boolean",
              "value": true
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "01d2e5be-51e6-4875-ae2f-9263c0a54c01",
      "name": "Confluence - Get Spaces",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -64,
        -144
      ],
      "parameters": {
        "url": "={{ $json.atlassianDomain }}/wiki/api/v2/spaces",
        "options": {},
        "sendQuery": true,
        "authentication": "genericCredentialType",
        "genericAuthType": "httpBasicAuth",
        "queryParameters": {
          "parameters": [
            {
              "name": "keys",
              "value": "={{ $json.spaceKeys }}"
            },
            {
              "name": "type",
              "value": "=global"
            }
          ]
        }
      },
      "credentials": {
        "httpBasicAuth": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.3
    },
    {
      "id": "f6ae755d-ca03-4667-94c1-ba477e3834d1",
      "name": "Format Space Ids",
      "type": "n8n-nodes-base.set",
      "position": [
        160,
        -144
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "4599d31e-0fe3-4a62-a731-3f97d12548ac",
              "name": "spaceIds",
              "type": "array",
              "value": "={{ $json.results.map(item => item.id) }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "1b57be44-b8e8-4fe8-b8a0-75a83f2df4bb",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -160,
        -208
      ],
      "parameters": {
        "color": 7,
        "width": 1376,
        "height": 240,
        "content": "## Confluence API v2"
      },
      "typeVersion": 1
    },
    {
      "id": "b94622d4-d90c-4058-854f-21d53d15b672",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -160,
        -464
      ],
      "parameters": {
        "color": 7,
        "width": 1376,
        "height": 240,
        "content": "## Confluence API v1"
      },
      "typeVersion": 1
    },
    {
      "id": "9e5b51a5-5bdd-4fbf-88f5-826f327e014c",
      "name": "Confluence - Get Outdated Spaces via CQL",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -64,
        -400
      ],
      "parameters": {
        "url": "={{ $json.atlassianDomain }}/wiki/rest/api/search",
        "options": {},
        "sendQuery": true,
        "authentication": "genericCredentialType",
        "genericAuthType": "httpBasicAuth",
        "queryParameters": {
          "parameters": [
            {
              "name": "cql",
              "value": "=lastmodified < now(\"-{{ $json.cutoffDateDays }}d\") AND type=page {{ $json.spaceKeys.length > 0 ? `AND space IN (${$json.spaceKeys})` : ``}}"
            },
            {
              "name": "limit",
              "value": "50"
            }
          ]
        }
      },
      "credentials": {
        "httpBasicAuth": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.3
    },
    {
      "id": "7a114039-4852-4d46-8cbe-086cf5f1be72",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -160,
        -608
      ],
      "parameters": {
        "color": 4,
        "width": 352,
        "height": 128,
        "content": "## Confluence API Reference\n* [V1 CQL Search](https://developer.atlassian.com/cloud/confluence/rest/v1/api-group-search/#api-wiki-rest-api-search-get)\n* [V2 Get Spaces](https://developer.atlassian.com/cloud/confluence/rest/v2/api-group-space/#api-spaces-get)\n* [V2 Get Pages](https://developer.atlassian.com/cloud/confluence/rest/v2/api-group-page/#api-pages-get)"
      },
      "typeVersion": 1
    },
    {
      "id": "ec8e82bc-326b-403b-a383-ddc818edcd55",
      "name": "Filter Version by cutoffDate",
      "type": "n8n-nodes-base.filter",
      "position": [
        832,
        -144
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 3,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "b0dcb3ac-4a81-478e-b934-78356147965e",
              "operator": {
                "type": "dateTime",
                "operation": "beforeOrEquals"
              },
              "leftValue": "={{ $json.version.createdAt }}",
              "rightValue": "={{ new Date(Date.now() - $('Set Variables').first().json.cutoffDateDays * 24 * 60 * 60 * 1000) }}"
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "c3c963f4-09e2-460b-bbc3-6692c36ef8bf",
      "name": "Switch API Version",
      "type": "n8n-nodes-base.switch",
      "position": [
        -352,
        -272
      ],
      "parameters": {
        "rules": {
          "values": [
            {
              "outputKey": "V1",
              "conditions": {
                "options": {
                  "version": 3,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "46b706cb-7363-47ce-a1fa-b40e7b283a7e",
                    "operator": {
                      "type": "boolean",
                      "operation": "false",
                      "singleValue": true
                    },
                    "leftValue": "={{ $json.apiV2 }}",
                    "rightValue": ""
                  }
                ]
              },
              "renameOutput": true
            },
            {
              "outputKey": "V2",
              "conditions": {
                "options": {
                  "version": 3,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "212f16f1-390c-45a0-987d-abfe38ddca76",
                    "operator": {
                      "type": "boolean",
                      "operation": "true",
                      "singleValue": true
                    },
                    "leftValue": "={{ $json.apiV2 }}",
                    "rightValue": false
                  }
                ]
              },
              "renameOutput": true
            }
          ]
        },
        "options": {}
      },
      "typeVersion": 3.4
    },
    {
      "id": "57da6622-eecd-4978-9c87-a434d843764e",
      "name": "Set Report Data V2",
      "type": "n8n-nodes-base.set",
      "position": [
        1056,
        -144
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "dce1e9a4-ea8f-447c-b39c-19a50f3bd293",
              "name": "title",
              "type": "string",
              "value": "={{ $json.title }}"
            },
            {
              "id": "6f647d56-6713-49ce-a16e-afdf6318e086",
              "name": "status",
              "type": "string",
              "value": "={{ $json.status }}"
            },
            {
              "id": "d7a67733-d9c8-47dd-a9ab-e419ec7c8b94",
              "name": "lastUpdated",
              "type": "string",
              "value": "={{ $json.version.createdAt }}"
            },
            {
              "id": "84e8fe80-783f-44c4-8dac-561b2130426a",
              "name": "daysOverCutoff",
              "type": "string",
              "value": "={{ Math.max(0, Math.floor((Date.now() - Date.parse($json.version.createdAt)) / 86400000) - $('Set Variables').item.json.cutoffDateDays) }}"
            },
            {
              "id": "61f63211-2438-4ccd-ae0f-35b9af0b00d6",
              "name": "url",
              "type": "string",
              "value": "={{ $('Set Variables').first().json.atlassianDomain }}/wiki{{ $json._links.webui }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "92190adf-9303-44bd-9503-3cbc7ca13d89",
      "name": "Set Report Data V1",
      "type": "n8n-nodes-base.set",
      "position": [
        1056,
        -400
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "dce1e9a4-ea8f-447c-b39c-19a50f3bd293",
              "name": "title",
              "type": "string",
              "value": "={{ $json.title }}"
            },
            {
              "id": "6f647d56-6713-49ce-a16e-afdf6318e086",
              "name": "status",
              "type": "string",
              "value": "={{ $json.content.status }}"
            },
            {
              "id": "d7a67733-d9c8-47dd-a9ab-e419ec7c8b94",
              "name": "lastUpdated",
              "type": "string",
              "value": "={{ $json.lastModified }}"
            },
            {
              "id": "84e8fe80-783f-44c4-8dac-561b2130426a",
              "name": "daysOverCutoff",
              "type": "string",
              "value": "={{ Math.max(0, Math.floor((Date.now() - Date.parse($json.lastModified)) / 86400000) - $('Set Variables').item.json.cutoffDateDays) }}"
            },
            {
              "id": "61f63211-2438-4ccd-ae0f-35b9af0b00d6",
              "name": "url",
              "type": "string",
              "value": "={{ $('Set Variables').first().json.atlassianDomain }}/wiki{{ $json.url }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "eb9b413f-bf6d-462e-b50c-8f7347d1f7e2",
      "name": "Split Out Pages V1",
      "type": "n8n-nodes-base.splitOut",
      "position": [
        160,
        -400
      ],
      "parameters": {
        "options": {},
        "fieldToSplitOut": "results"
      },
      "typeVersion": 1
    },
    {
      "id": "0080113f-8918-4880-8f83-849c00686d33",
      "name": "Split Out Pages V2",
      "type": "n8n-nodes-base.splitOut",
      "position": [
        608,
        -144
      ],
      "parameters": {
        "options": {},
        "fieldToSplitOut": "results"
      },
      "typeVersion": 1
    },
    {
      "id": "970001e9-438d-46ac-a7a0-f2fa0cac6364",
      "name": "Aggregate",
      "type": "n8n-nodes-base.aggregate",
      "position": [
        1376,
        -272
      ],
      "parameters": {
        "options": {},
        "aggregate": "aggregateAllItemData",
        "destinationFieldName": "stalePages"
      },
      "typeVersion": 1
    },
    {
      "id": "20ead0de-fc37-4076-aa04-3f56ef8bb836",
      "name": "Confluence - Get Pages",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        384,
        -144
      ],
      "parameters": {
        "url": "={{ $('Set Variables').item.json.atlassianDomain }}/wiki/api/v2/pages",
        "options": {},
        "sendQuery": true,
        "authentication": "genericCredentialType",
        "genericAuthType": "httpBasicAuth",
        "queryParameters": {
          "parameters": [
            {
              "name": "space-id",
              "value": "={{ $json.spaceIds.join(\", \") }}"
            },
            {
              "name": "limit",
              "value": "50"
            }
          ]
        }
      },
      "credentials": {
        "httpBasicAuth": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.3
    },
    {
      "id": "51459632-b9ac-4948-9173-314b110f6d32",
      "name": "Sticky Note6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1632,
        -64
      ],
      "parameters": {
        "color": 6,
        "width": 768,
        "height": 224,
        "content": "### Notes\n- API v2 is preferred and future-proof; v1 exists for legacy compatibility.\n- Pagination limits are set to 50 items per request \u2014 increase if needed.\n- If results are empty:\n  - Verify space keys\n  - Confirm cutoff days logic\n  - Check API permissions for the token\n- Tested against Confluence Cloud.\n- Need help? \u2709\ufe0f **office@sus-tech.at**\n"
      },
      "typeVersion": 1
    },
    {
      "id": "a1f68570-063b-4964-b455-812a8560362b",
      "name": "Sticky Note7",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1632,
        -608
      ],
      "parameters": {
        "width": 768,
        "height": 528,
        "content": "## How it works\nThis workflow identifies stale Confluence pages based on last modification date. A **Set Variables** node defines the core inputs: your Atlassian domain, target space keys, an age threshold in days and whether to use the v1 or v2 Confluence API.\n\n- If **API v1** is selected, the workflow runs a CQL search that directly returns pages older than the cutoff date.\n- If **API v2** is enabled (recommended), the workflow first fetches spaces, then pages within those spaces, and filters them by their last modified timestamp.  \n\n\nRegardless of the path, each page is normalized into a consistent structure (title, space, URL, last updated, author). All results are combined into a single `stalePages` array, making the output easy to reuse for reporting, notifications, or exports.\n\n## Setup steps\n1. Open the **Set Variables** node and configure:\n   - `atlassianDomain`: Your Confluence base URL  \n   - `spaceKeys`: Comma-separated space keys (e.g. `DOCS,ENG`)  \n   - `cutoffDateDays`: Age threshold in days (e.g. `90`)  \n   - `apiV2`: `true` to use API v2, `false` for legacy CQL  \n2. Create an **HTTP Basic Auth** credential in n8n using your Atlassian email and API token.\n3. Assign this credential to all HTTP Request nodes in the workflow.\n4. (Optional) Add follow-up nodes for email, Slack alerts, or CSV export using the `stalePages` output.\n"
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "48160f38-785f-40c2-a1d1-436e3402cd6a",
  "connections": {
    "Set Variables": {
      "main": [
        [
          {
            "node": "Switch API Version",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Format Space Ids": {
      "main": [
        [
          {
            "node": "Confluence - Get Pages",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set Report Data V1": {
      "main": [
        [
          {
            "node": "Aggregate",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set Report Data V2": {
      "main": [
        [
          {
            "node": "Aggregate",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Split Out Pages V1": {
      "main": [
        [
          {
            "node": "Set Report Data V1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Split Out Pages V2": {
      "main": [
        [
          {
            "node": "Filter Version by cutoffDate",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Switch API Version": {
      "main": [
        [
          {
            "node": "Confluence - Get Outdated Spaces via CQL",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Confluence - Get Spaces",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Confluence - Get Pages": {
      "main": [
        [
          {
            "node": "Split Out Pages V2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Confluence - Get Spaces": {
      "main": [
        [
          {
            "node": "Format Space Ids",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Filter Version by cutoffDate": {
      "main": [
        [
          {
            "node": "Set Report Data V2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "When clicking \u2018Execute workflow\u2019": {
      "main": [
        [
          {
            "node": "Set Variables",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Confluence - Get Outdated Spaces via CQL": {
      "main": [
        [
          {
            "node": "Split Out Pages V1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}

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.

Pro

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

About this workflow

This workflow generates a stale page report for Confluence spaces, helping teams keep documentation accurate, relevant, and actively maintained. Identifies Confluence pages not updated within a defined cutoff period (in days). Supports both: Confluence REST API v1 (CQL search),…

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

More Web Scraping workflows → · Browse all categories →

Related workflows

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

Web Scraping

This workflow allows you to import any workflow from a file or another n8n instance and map the credentials easily. A multi-form setup guides you through the entire process At the beginning you have t

Execute Command, Read Write File, HTTP Request +3
Web Scraping

[n8n] Advanced URL Parsing and Shortening Workflow - Switchy.io Integration. Uses splitInBatches, stickyNote, httpRequest, html. Event-driven trigger; 56 nodes.

HTTP Request, GitHub, Stop And Error +1
Web Scraping

[](https://youtu.be/c7yCZhmMjtI)

HTTP Request, GitHub, Stop And Error +1
Web Scraping

This automation organizes your n8n workflows files into categorizes (Active, Template, Done, Archived) and uploads them directly to a categorized Google Drive folders. It is designed to help users man

Google Drive, HTTP Request, Time Saved
Web Scraping

Create Animated Stories using GPT-4o-mini, Midjourney, Kling and Creatomate API. Uses httpRequest. Event-driven trigger; 51 nodes.

HTTP Request