Keep the docs in sync

Publish a new version of your OpenAPI file to Confluence from GitHub Actions, GitLab CI, Bitbucket Pipelines or Azure DevOps.

Apifolio always shows the latest version of the attached file. To keep the docs in sync with your code, upload the spec as a new version of the same attachment from your CI pipeline. Confluence keeps every version, and the page updates by itself.

What you need

  • the page ID of the page that holds the spec (the number in the page URL, /pages/123456/...);
  • an Atlassian API token for a user who can edit that page, created at id.atlassian.com/manage-profile/security/api-tokens. Store it as a secret in your CI, never in the repository;
  • the file name used by the macro, for example openapi.yaml. Keep the same name so the macro finds the new version.

The request

curl --fail -sS -u "$CONFLUENCE_EMAIL:$CONFLUENCE_API_TOKEN" \
  -X PUT \
  -H "X-Atlassian-Token: no-check" \
  -F "[email protected]" \
  -F "minorEdit=true" \
  -F "comment=Updated from CI ($GIT_COMMIT)" \
  "https://your-site.atlassian.net/wiki/rest/api/content/$PAGE_ID/child/attachment"

PUT creates the attachment the first time and adds a new version afterwards. minorEdit=true avoids notifying page watchers on every build.

GitHub Actions

name: Publish API docs
on:
  push:
    branches: [main]
    paths: [openapi.yaml]
jobs:
  publish:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Upload openapi.yaml to Confluence
        env:
          CONFLUENCE_EMAIL: ${{ secrets.CONFLUENCE_EMAIL }}
          CONFLUENCE_API_TOKEN: ${{ secrets.CONFLUENCE_API_TOKEN }}
          PAGE_ID: "123456"
        run: |
          curl --fail -sS -u "$CONFLUENCE_EMAIL:$CONFLUENCE_API_TOKEN" -X PUT \
            -H "X-Atlassian-Token: no-check" \
            -F "[email protected]" -F "minorEdit=true" \
            -F "comment=Updated from ${GITHUB_SHA::7}" \
            "https://your-site.atlassian.net/wiki/rest/api/content/$PAGE_ID/child/attachment"

GitLab CI

publish-api-docs:
  image: curlimages/curl:latest
  rules:
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
      changes: [openapi.yaml]
  script:
    - >
      curl --fail -sS -u "$CONFLUENCE_EMAIL:$CONFLUENCE_API_TOKEN" -X PUT
      -H "X-Atlassian-Token: no-check"
      -F "[email protected]" -F "minorEdit=true"
      -F "comment=Updated from $CI_COMMIT_SHORT_SHA"
      "https://your-site.atlassian.net/wiki/rest/api/content/$PAGE_ID/child/attachment"

Bitbucket Pipelines

pipelines:
  branches:
    main:
      - step:
          name: Publish API docs
          image: curlimages/curl:latest
          script:
            - curl --fail -sS -u "$CONFLUENCE_EMAIL:$CONFLUENCE_API_TOKEN" -X PUT -H "X-Atlassian-Token: no-check" -F "[email protected]" -F "minorEdit=true" "https://your-site.atlassian.net/wiki/rest/api/content/$PAGE_ID/child/attachment"

Azure DevOps

steps:
  - script: |
      curl --fail -sS -u "$(CONFLUENCE_EMAIL):$(CONFLUENCE_API_TOKEN)" -X PUT \
        -H "X-Atlassian-Token: no-check" \
        -F "[email protected]" -F "minorEdit=true" \
        "https://your-site.atlassian.net/wiki/rest/api/content/$(PAGE_ID)/child/attachment"
    displayName: Publish API docs to Confluence

After a new version is uploaded, open the macro configuration and click Save once in a while to refresh the Confluence search digest.

View as Markdown