arazzo: 1.0.1 info: title: Confluence Upsert a Page by Title summary: Find a page by title within a space and update it if it exists, otherwise create it. description: >- The most common Confluence sync pattern: a system of record pushes a document into a space and must not create duplicates on the second run. The workflow resolves the space key to an id, searches that space for a page with the exact title, and then branches. When a page matches it fetches the current version and issues a version-incremented update; when nothing matches it creates a new page. Every step spells out its request inline so the flow can be read and executed without opening the underlying OpenAPI description. version: 1.0.0 sourceDescriptions: - name: confluenceCloudV2 url: ../openapi/confluence-cloud-v2.yml type: openapi workflows: - workflowId: upsert-page-by-title summary: Upsert a single Confluence page into a space, keyed on the page title. description: >- Resolves the space, looks for an existing current page whose title exactly matches the supplied title, and either updates the matched page or creates a new one. inputs: type: object required: - spaceKey - title - body properties: spaceKey: type: string description: The space key to upsert the page into (e.g. "ENG"). title: type: string description: The page title used as the natural key for the match. body: type: string description: The page body in Confluence storage format (XHTML). versionMessage: type: string description: Optional changelog message recorded on the new version when updating. newVersionNumber: type: integer description: >- The version number to write on the update path, which Confluence requires to be the current version plus one. Arazzo runtime expressions have no arithmetic, so the caller supplies this value; the readCurrentVersion step returns currentVersion to compute it from and to verify against. steps: - stepId: resolveSpace description: >- Resolve the supplied space key to the numeric space id required to filter pages and to write. operationId: getSpaces parameters: - name: keys in: query value: $inputs.spaceKey - name: status in: query value: current - name: limit in: query value: 1 successCriteria: - condition: $statusCode == 200 - context: $response.body condition: $.results.length > 0 type: jsonpath outputs: spaceId: $response.body#/results/0/id - stepId: findPage description: >- Search the resolved space for a current page whose title exactly matches the supplied title, returning at most one match. operationId: getPages parameters: - name: space-id in: query value: $steps.resolveSpace.outputs.spaceId - name: title in: query value: $inputs.title - name: status in: query value: current - name: limit in: query value: 1 successCriteria: - condition: $statusCode == 200 outputs: matchedPageId: $response.body#/results/0/id onSuccess: - name: pageExists type: goto stepId: readCurrentVersion criteria: - context: $response.body condition: $.results.length > 0 type: jsonpath - name: pageMissing type: goto stepId: createNewPage criteria: - context: $response.body condition: $.results.length == 0 type: jsonpath - stepId: readCurrentVersion description: >- Read the matched page to capture its current version number. Confluence rejects an update that does not carry the next sequential version. operationId: getPageById parameters: - name: id in: path value: $steps.findPage.outputs.matchedPageId - name: body-format in: query value: storage successCriteria: - condition: $statusCode == 200 outputs: currentVersion: $response.body#/version/number spaceId: $response.body#/spaceId parentId: $response.body#/parentId - stepId: updateExistingPage description: >- Replace the matched page body with the supplied content, incrementing the version number by one. A 409 here means another writer moved the version first and the flow should be retried from findPage. operationId: updatePage parameters: - name: id in: path value: $steps.findPage.outputs.matchedPageId requestBody: contentType: application/json payload: id: $steps.findPage.outputs.matchedPageId status: current title: $inputs.title spaceId: $steps.readCurrentVersion.outputs.spaceId body: representation: storage value: $inputs.body version: number: $inputs.newVersionNumber message: $inputs.versionMessage successCriteria: - condition: $statusCode == 200 outputs: pageId: $response.body#/id versionNumber: $response.body#/version/number webui: $response.body#/_links/webui onSuccess: - name: done type: end - stepId: createNewPage description: >- Create a new page in the resolved space when no page matched the title. operationId: createPage requestBody: contentType: application/json payload: spaceId: $steps.resolveSpace.outputs.spaceId status: current title: $inputs.title body: representation: storage value: $inputs.body successCriteria: - condition: $statusCode == 200 outputs: pageId: $response.body#/id versionNumber: $response.body#/version/number webui: $response.body#/_links/webui outputs: spaceId: $steps.resolveSpace.outputs.spaceId updatedPageId: $steps.updateExistingPage.outputs.pageId createdPageId: $steps.createNewPage.outputs.pageId